This commit is contained in:
julianb0 2019-08-21 16:57:32 +02:00
parent b38eab6d76
commit f1b3bf129b
No known key found for this signature in database
GPG Key ID: 9C7ACF0C053FB8A1
29 changed files with 698 additions and 528 deletions

View File

@ -394,7 +394,7 @@ pref2len = {
i_aliases = {
"inc_2" : "add_2",
"dec_2" : "sub_2",
#"dec_2" : "sub_2",
}
def parse_instr(line):
@ -564,13 +564,20 @@ def parse_instr(line):
instr_args += "%%imm8 {} {} {}".format(fmts["m_rr"]|mlen, '$'+reg1, '$'+reg2)
size += 3
# [reg+reg+imm]
else:
instr_args += "%%imm8 {} {} {} %%signed %%imm16 {}"\
.format(fmts["m_rriw"]|mlen, '$'+reg1, '$'+reg2, imm2)
size += 5
# [reg+imm16]
elif reg2 == 'zero':
instr_args += "%%imm8 {} {} %%signed %%imm16 {}"\
.format(fmts["m_rriw"]|mlen, '$'+reg1, imm2)
size += 4
# [reg+reg*imm+imm]
# [reg+reg+imm32]
else:
instr_args += "%%imm8 {} {} {} %%signed %%imm32 {}"\
.format(fmts["m_rrid"]|mlen, '$'+reg1, '$'+reg2, imm2)
size += 7
# [reg+reg*imm8+imm32]
else:
instr_args += "%%imm8 {} {} {} %%imm8 {} %%signed %%imm32 {}"\
.format(fmts["m_rrii"]|mlen, '$'+reg1, '$'+reg2, imm1, imm2)
@ -581,7 +588,7 @@ def parse_instr(line):
instr_args += "%%imm8 {} {}".format(fmts["m_r"]|mlen, '$'+word)
size += 2
# [imm], converted to [zero+imm]
# [imm32], converted to [zero+imm32]
else:
instr_args += "%%imm8 {} $zero $zero %%signed %%imm32 {}".format(fmts["m_rrid"]|mlen, word)
size += 7

3
ka/ABI
View File

@ -11,13 +11,14 @@ There is a 128-bytes red zone below 'rsp'.
A function's assembly code looks like this:
label:
enter N
enter N*8
...
...
...
leave
ret
'N' is the number of local variables used by the function.
'N' may be omitted if it is zero.
The above code is equivalent to (and can be substitued by) the following:
label:

2
ka/FIXME Normal file
View File

@ -0,0 +1,2 @@
Known issues:
- alignment issue... compile with _WANT_ALIGN, see &argv1pos not aligned by 8

View File

@ -1,18 +1,24 @@
; The OS/K Team licenses this file to you under the MIT license.
; See the LICENSE file in the project root for more information.
__cmdstart:
cmdstart:
jmp start
include "crt/crt.k"
FILE_LOADP := 0x121000 ; 4KB above stack
CMDCOM_CODE := 0x100000 ; 1MB
CMDCOM_STACK := 0x104000 ; + 16KB
; COMMAND.COM guarantees that programs
; are always loaded on a 16KB boundary
; This is guaranteed to be the case
; in all future versions as well
FILE_LOADP := 0x108000 ; + 32KB
start:
mov rsp, 0x120000
mov rsp, CMDCOM_STACK
mov rbp, zero
cls
call main
mov rax, Sys.EnterHaltMode
@ -20,8 +26,374 @@ start:
crash
include "usr/cmd/main.k"
include "usr/cmd/dir.k"
cmd.versionstr = "COMMAND.COM, version 0.1 (KVISC)\nCopyright (C) 2019, The OS/K Team\nMIT license (permissive), see LICENCE file in source tree"
argbuf.size := 256
argbuf = [argbuf.size]
argv0 = [argbuf.size]
argv1pos = 0
stdin_echoing = 1
prompt = [32]
main:
mov rsi, prompt
mov b[rsi+0], 'C'
mov b[rsi+1], ':'
mov b[rsi+2], '\'
mov b[rsi+3], '>'
mov b[rsi+4], ' '
.print_prompt:
call print, prompt
; empty stuff
call memzero, argbuf, argbuf.size
call memzero, argv0, argbuf.size
nul q[argv1pos]
# call nprint, argv0, argbuf.size
; iterator through argbuf
nul rcx
.input_loop:
pause
pause
pause
; Fill .buf with user input
scan rax
jraxz .input_loop
; ESC key pressed?
beq rax, 0x1B, .handle_EXIT
; backspace character?
bne rax, 8, .handle_input
; anything to delete?
jrcxz .input_loop ; no
; yes, delete it
dec rcx
add rdx, rcx, argbuf
nul b[rdx]
; update screen
bzr b[stdin_echoing], .input_loop
prn 8
jmp .input_loop
.handle_input:
bzr b[stdin_echoing], .se.z
prn rax
.se.z:
beq rax, 10, .extract_argv0
; when max line length is reached,
; force a newline
beq rcx, argbuf.size, .extract_argv0
; add character to buffer and increase iterator (rcx)
add rdx, rcx, argbuf
mov b[rdx], rax
inc rcx
; another one
jmp .input_loop
.extract_argv0:
; did we read anything at all?
; if not, just go back to waiting input
jrcxz .print_prompt
; find first whitespace or null-terminator
mov rcx, argbuf.size
mov rdx, argbuf
scasb rdx, ' '
; argv1 exists? if so, save its position
mov rsi, rdx
.next_space:
mov rcx, b[rsi]
jrcxz .do_extract
; skip spaces
bne rcx, ' ', .not_a_space
inc rsi
jmp .next_space
.not_a_space:
; if we're here, we found a
; non-zero non-space character
mov q[argv1pos], rsi
; fallthrough
.do_extract:
; how much do we copy?
sub rcx, rdx, argbuf
jrcxz .detect_builtin
dec rcx
mov rdi, argbuf
mov rsi, argv0
.copy_loop:
mov b[rsi], b[rdi]
inc rdi
inc rsi
loop .copy_loop
.detect_builtin:
.builtin_cls = "cls"
call strcmp, argv0, .builtin_cls
jraxz .handle_CLS
.builtin_crash = "crash"
call strcmp, argv0, .builtin_crash
jraxz .handle_CRASH
.builtin_date = "date"
call strcmp, argv0, .builtin_date
jraxz .handle_DATE
.builtin_dir = "dir"
call strcmp, argv0, .builtin_dir
jraxz .handle_DIR
.builtin_dump = "dump"
call strcmp, argv0, .builtin_dump
jraxz .handle_DUMP
.builtin_echo = "echo"
call strcmp, argv0, .builtin_echo
jraxz .handle_ECHO
.builtin_erase = "erase"
call strcmp, argv0, .builtin_erase
jraxz .handle_ERASE
.builtin_exit = "exit"
call strcmp, argv0, .builtin_exit
jraxz .handle_EXIT
.builtin_help = "help"
call strcmp, argv0, .builtin_help
jraxz .handle_HELP
.builtin_halt = "halt"
call strcmp, argv0, .builtin_halt
jraxz .handle_HALT
.builtin_make = "make"
call strcmp, argv0, .builtin_make
jraxz .handle_MAKE
.builtin_print = "print"
call strcmp, argv0, .builtin_print
jraxz .handle_PRINT
.builtin_prompt = "prompt"
call strcmp, argv0, .builtin_prompt
jraxz .handle_PROMPT
.builtin_remove = "remove"
call strcmp, argv0, .builtin_remove
jraxz .handle_REMOVE
.builtin_time = "time"
call strcmp, argv0, .builtin_time
jraxz .handle_TIME
.builtin_vers = "vers"
call strcmp, argv0, .builtin_vers
jraxz .handle_VERS
jmp .try_exec
;
; call builtins
;
include "usr/cmd-dir.k"
include "usr/cmd-exec.k"
include "usr/cmd-fsmisc.k"
.handle_CLS:
prn PRN_CLEAR
jmp .print_prompt
.handle_CRASH:
jmp abort
.handle_DATE:
call GetTimeUTC
mov rcx, b[rax+4]
inc rcx
push b[rax+3], rcx, w[rax+6]
call printf, .datefmt
inc rsp, 40
jmp .print_prompt
.datefmt = "%d/%d/%d\n"
.handle_DUMP:
dump
jmp .print_prompt
.handle_ECHO:
mov rax, q[argv1pos]
jraxz .echo.end
call print, rax
.echo.end:
prn 10
jmp .print_prompt
.handle_EXIT:
mov rax, Sys.Shutdown
trap 0
jmp .print_prompt
.handle_HALT:
mov rax, Sys.EnterHaltMode
trap 0
jmp .print_prompt
.handle_PROMPT:
mov ax0, prompt
mov ax1, q[argv1pos]
bzr ax1, .need_params
call strcpy
jmp .print_prompt
.handle_TIME:
call GetTimeUTC
push b[rax], b[rax+1], b[rax+2]
call printf, .timefmt
inc rsp, 24
jmp .print_prompt
.timefmt = "%d:%d:%d\n"
.handle_VERS:
call print, cmd.versionstr
prn 10
jmp .print_prompt
.handle_HELP:
call print, .helpmsg
call print, .helpmsg.cls
call print, .helpmsg.date
call print, .helpmsg.dir
call print, .helpmsg.dump
call print, .helpmsg.echo
call print, .helpmsg.erase
call print, .helpmsg.exit
call print, .helpmsg.help
call print, .helpmsg.halt
call print, .helpmsg.make
call print, .helpmsg.print
call print, .helpmsg.prompt
call print, .helpmsg.remove
call print, .helpmsg.time
call print, .helpmsg.ver
jmp .print_prompt
.helpmsg = "The following commands are built-in:\n"
.helpmsg.cls = " CLS Clear screen\n"
.helpmsg.date = " DATE Display current date\n"
.helpmsg.dir = " DIR Print contents of current directory\n"
.helpmsg.dump = " DUMP Toggles debug instruction dumping\n"
.helpmsg.echo = " ECHO Write arguments to standard output\n"
.helpmsg.erase = " ERASE Clear a file, making it blank\n"
.helpmsg.exit = " EXIT Initiate machine shutdown\n"
.helpmsg.help = " HELP Display these messages\n"
.helpmsg.halt = " HALT Put processor in halt mode\n"
.helpmsg.make = " MAKE Create an empty file\n"
.helpmsg.print = " PRINT Display contents of text file\n"
.helpmsg.prompt = " PROMPT Change the command line prompt\n"
.helpmsg.remove = " REMOVE Delete a file (permanently)\n"
.helpmsg.time = " TIME Display current time of day\n"
.helpmsg.ver = " VERS Display current COMMAND.COM version\n"
.exec_not_found:
push argv0
call printf, .enf_errmsg
inc rsp, 8
jmp .print_prompt
.enf_errmsg = "%s: file not found\n"
.file_not_found:
push q[argv1pos], argv0
call printf, .fnf_errmsg
inc rsp, 16
jmp .print_prompt
.fnf_errmsg = "%s: %s: file not found\n"
.empty_file:
push q[argv1pos], argv0
call printf, .ef_errmsg
inc rsp, 16
jmp .print_prompt
.ef_errmsg = "%s: %s: file was empty\n"
.couldnt_open:
push q[argv1pos], argv0
call printf, .cno_errmsg
inc rsp, 16
jmp .print_prompt
.cno_errmsg = "%s: %s: an error occured while opening file\n"
.couldnt_remove:
push q[argv1pos], argv0
call printf, .cne_errmsg
inc rsp, 16
jmp .print_prompt
.cne_errmsg = "%s: %s: an error occured while removing file\n"
.couldnt_read:
push q[argv1pos], argv0
call printf, .cnr_errmsg
inc rsp, 16
jmp .print_prompt
.cnr_errmsg = "%s: %s: an error occured while reading file\n"
.need_params:
call print, argv0
call print, .np_errmsg
jmp .print_prompt
.np_errmsg = ": need more parameters\n"

View File

@ -48,6 +48,11 @@ include "crt/fmt/ltostr.k"
include "crt/fmt/strtol.k"
include "crt/fmt/doprnt.k"
include "crt/fmt/printf.k"
exit:
mov rax, Sys.Exit
trap 0
abort:
crash

View File

@ -65,7 +65,7 @@ doprnt:
movzx ax0, b[r13]
bzr ax0, .main_loop
inc r13, 1
inc r13
call .doput
jmp .print_string
@ -99,7 +99,7 @@ doprnt:
.print_number:
; allocate itoa conversion buffer
dec rsp, 80
sub rsp, 80
mov r13, rsp
; assume modifier already set up ax2
@ -110,7 +110,7 @@ doprnt:
movzx ax0, b[r13]
bzr ax0, .pib_end_loop
inc r13, 1
inc r13
call .doput
jmp .print_itoa_buf
@ -155,7 +155,7 @@ doprnt:
;
.doput:
; update print count
inc r16, 1
inc r16
; if n==0, don't print
; we follow the C convention that sprintf()-like functions
@ -164,7 +164,7 @@ doprnt:
bzr r15, .r
; decrement n and print
dec r15, 1
dec r15
call r17
; did putc fail?

View File

@ -56,7 +56,7 @@ ltostr:
.next:
mov b[ax0], rdx
inc ax0, 1
inc ax0
div ax1, ax2
jmp .conv
@ -65,7 +65,7 @@ ltostr:
.fini:
jrcxz .cxz
mov b[ax0], '-'
inc ax0, 1
inc ax0
.cxz:
nul b[ax0]

View File

@ -38,7 +38,7 @@ print:
jraxz .r
prn rax
inc ax0, 1
inc ax0
jmp .l
@ -54,7 +54,7 @@ nprint:
.l:
prn b[ax0]
inc ax0, 1
inc ax0
loop .l
.r:
ret

View File

@ -39,13 +39,13 @@ strtoq:
.skip_spc:
bne b[rdx], ' ', .no_spc
inc rdx, 1
inc rdx
jmp .skip_spc
.no_spc:
; skip +
bne b[rdx], '+', .no_plus
inc rdx, 1
inc rdx
.no_plus:
; unsigned?
@ -53,7 +53,7 @@ strtoq:
; parse '-'
bne b[rdx], '-', .unsigned
inc rdx, 1
inc rdx
mov rsi, 1
.unsigned:
@ -63,7 +63,7 @@ strtoq:
; base prefix?
bne b[rdx], '0', .main_loop
inc rdx, 1
inc rdx
movzx rcx, b[rdx]
; "0x"/"0b" prefix
@ -88,7 +88,7 @@ strtoq:
; if not, leave rax = 0 and *rdx = 'b'
bne ax1, 2, .done
; else
inc rdx, 1
inc rdx
jmp .main_loop
.base_0:
@ -101,16 +101,16 @@ strtoq:
jmp .main_loop
.b0_not10:
inc rdx, 1
inc rdx
bne b[rdx], 'x', .b0_not16
inc rdx, 1
inc rdx
mov ax1, 16
jmp .main_loop
.b0_not16:
bne b[rdx], 'b', .b0_not2
inc rdx, 1
inc rdx
mov ax1, 2
jmp .main_loop
@ -120,28 +120,28 @@ strtoq:
.main_loop:
movzx rcx, b[rdx]
inc rdx, 1
inc rdx
; between 0 and 9?
bltu rcx, '0', .done
bltu '9', rcx, .not_digit10
; yes
dec rcx, '0'
sub rcx, '0'
jmp .next
.not_digit10:
bltu rcx, 'A', .done
bltu 'Z', rcx, .not_digitAZ
dec rcx, 55 ; 'A' - 10
sub rcx, 55 ; 'A' - 10
jmp .next
.not_digitAZ:
bltu rcx, 'a', .done
bltu 'z', rcx, .done
dec rcx, 87 ; 'a' - 10
sub rcx, 87 ; 'a' - 10
jmp .next
.next:

View File

@ -25,7 +25,7 @@ memzero:
.l:
nul b[ax0]
inc ax0, 1
inc ax0
loop .l
.r:

View File

@ -32,8 +32,8 @@ strcpy:
jrcxz .r
inc ax0, 1
inc ax1, 1
inc ax0
inc ax1
jmp .l
@ -50,8 +50,8 @@ strncpy:
.l:
mov b[ax0], b[ax1]
inc ax0, 1
inc ax1, 1
inc ax0
inc ax1
loop .l
@ -71,8 +71,8 @@ strnzcpy:
jraxz .r
inc ax0, 1
inc ax1, 1
inc ax0
inc ax1
loop .l
@ -102,11 +102,11 @@ strcmp:
add rcx, rax, rdx
jrcxz .r
inc rsi, 1
inc rsi
jmp .l
.r:
dec rax, rdx
sub rax, rdx
ret
;
@ -122,12 +122,12 @@ strncmp:
bne rax, rdx, .r
inc ax0, 1
inc ax1, 1
inc ax0
inc ax1
loop .l
.r:
dec rax, rdx
sub rax, rdx
ret
;
@ -170,7 +170,7 @@ strrev:
; the null terminator
mov rcx, STRLEN_MAX
scasb ax1, zero
dec ax1, 1
dec ax1
.l:
; copy, going backward though str
@ -179,8 +179,8 @@ strrev:
beq ax1, rsi, .r
inc ax0, 1
dec ax1, 1
inc ax0
dec ax1
jmp .l
.r:
@ -205,7 +205,7 @@ strrev2:
; the null terminator
mov rcx, STRLEN_MAX
scasb ax1, zero
dec ax1, 1
dec ax1
; increase ax0 while decreasing ax1, performing exchanges
.l:
@ -213,8 +213,8 @@ strrev2:
xchg b[ax0], b[ax1]
inc ax0, 1
dec ax1, 1
inc ax0
dec ax1
jmp .l
.r:

View File

@ -15,6 +15,20 @@ Sys.Shutdown := 0x00
;
Sys.Exit := 0x01
;
; EXEC syscall
;
; IN
; ax0 = new RIP to load
; ax1 = frame ID to switch to
;
; New frame ID must be higher than current
; frame ID, and cannot be below 5
;
; New CR1 is set so that new RIP corresponds to 1MB
;
Sys.ExecuteInFrame := 0x02
; FIND syscalls
;
; Find file on disk

View File

@ -10,13 +10,17 @@ include "crt/crt.k"
;
; Special addresses
;
DOSKRNL_CODE := 0x100000 ; 1MB (code)
DOSKRNL_STACK := 0x110000 ; + 64KB
TRAP0_STACK := 0x112000 ; + 8KB
INTR0_STACK := 0x114000 ; + 8KB
EXCT0_STACK := 0x118000 ; + 8KB
DOSKRNL_CODE := 0x100000 ; 1MB
DOSKRNL_STACK := 0x104000 ; + 16KB
TRAP0_STACK := 0x104800 ; + 18KB
INTR0_STACK := 0x105000 ; + 20KB
EXCT0_STACK := 0x105800 ; + 22KB
CMDCOM_LOADP := 0x120000 ; 1MB + 128KB
; The kernel guarantees that COMMAND.COM
; will always be loaded on a 16KB boundary
; This is guaranteed to be the case in all
; future versions as well
CMDCOM_LOADP := 0x108000 ; + 32KB
CMDCOM_MAXSZ := 0x80000 ; 512KB
;

18
ka/hello.k Normal file
View File

@ -0,0 +1,18 @@
; The OS/K Team licenses this file to you under the MIT license.
; See the LICENSE file in the project root for more information.
start:
jmp main
include "crt/crt.k"
main:
mov rsp, 0x104000
nul rbp
call print, .hellow
jmp exit
.hellow = "Hello World!\n"

View File

@ -48,8 +48,7 @@ RFS.LoadArgs:
ret
RFS.LoadReg:
.slot := 33
iocall CPUDEV, .slot
iocall CPUDEV, 33
ret
RFS.StoreReg:

View File

@ -18,7 +18,8 @@ ScreenOfDeath:
jmp .do_print
.not_con:
blt r14, 4, .not_krn
; rframes #2-#3-#4 belong to kernel
blt 4, r14, .not_krn
push .scr2_krn
jmp .do_print

View File

@ -20,7 +20,7 @@ DefaultExceptionHandler:
.err_udf = "Undefined behaviour exception\0\0"
.err_ill = "Illformed instruction exception"
.err_acc = "Invalid memory access exception"
.err_sys = "Supervisor-only exception used\0"
.err_sys = "Supervisor-only instruct. used\0"
.err_dbf = "Double fault exception~~~~~~~~\0"
.err_imp = "Feat. not implemented exception"
.err_ali = "Misalignmed address exception\0\0"

View File

@ -40,8 +40,11 @@ DefaultTrapHandler:
call RFS.LoadReg, r14, $rax
call RFS.LoadArgs, r14
; will be optimized with a table
; when we have a "finished" consistent API
jraxz .handle_Shutdown
beq rax, Sys.Exit, .handle_Exit
beq rax, Sys.ExecuteInFrame, .handle_EIF
beq rax, Sys.ReadFile, .handle_ReadFile
beq rax, Sys.OpenFile, .handle_OpenFile
beq rax, Sys.CloseFile, .handle_CloseFile
@ -51,8 +54,12 @@ DefaultTrapHandler:
beq rax, Sys.FindFirst, .handle_FindFirst
beq rax, Sys.EnterHaltMode, .handle_HaltMode
.sod:
call ScreenOfDeath, .badsyscall, r13
.wrong:
call ScreenOfDeath, .badparams, r13
.fini.savecx:
mov ax2, rcx
call RFS.StoreReg, r14, $rcx
@ -61,6 +68,7 @@ DefaultTrapHandler:
jmp TrapHandlers.epilog
.badsyscall = "Invalid syscall number in RAX"
.badparams = "Invalid syscall parameters"
;------------------------------------------------;
; Syscall implementations ;
@ -70,48 +78,91 @@ DefaultTrapHandler:
; Pass control to COMMAND.COM in frame 0
;
.handle_Exit:
; deactivate current rframe
bzr r14, .hE_nz ; unless it's 0...
call RFS.DeactivateFrame, r14
; Open COMMAND.COM
.hE_nz:
; open COMMAND.COM
call DISK.OpenFile, .cmdcom
; Crash on failure
; crash on failure
bltz rax, abort
; Load at CMDCOM_LOADP
; load at CMDCOM_LOADP
mov ax1, CMDCOM_LOADP
mov ax2, CMDCOM_MAXSZ
call DISK.ReadFile, rax
; Assume that COMMAND.COM being
; assume that COMMAND.COM being
; less then 4KB means something
; went wrong
blt rax, 0x1000, abort
; Close the handle
; close the handle
call DISK.CloseFile, rax
; Code address
; code address
mov ax2, 0x100000
call RFS.StoreReg, zero, $rip
; Usermode
; usermode
mov ax2, 3
call RFS.StoreReg, zero, $cr0
mov rcx, CMDCOM_LOADP
dec rcx, 0x100000
sub rcx, 0x100000
; Code offset
; code offset
mov ax2, rcx
call RFS.StoreReg, zero, $cr1
; Return frame
; return frame
nul r14
jmp .fini
.cmdcom = "command.com"
.handle_EIF:
blt ax1, 5, .wrong
; RIP can't be <1MB
mov rcx, 0x100000
blt ax0, rcx, .wrong
; add old CR1
add ax0, r12
; real RIP can't be <1MB+32KB either
; (kernel + cmdcom personal space)
add rdx, rcx, 0x8000
blt ax0, rcx, .wrong
; save rframe and compute new CR1
mov rbx, ax1
sub rdi, ax0, rcx
; activate rframe
call RFS.ActivateFrame, rbx
; save new CR1
mov ax2, rdi
call RFS.StoreReg, rbx, $cr1
; interruptible user mode
mov ax2, 3
call RFS.StoreReg, rbx, $cr0
; set RIP = 1MB
mov ax2, rcx
call RFS.StoreReg, rbx, $rip
; change return frame
mov r14, rbx
jmp .fini
;
; Disk API
;
@ -154,7 +205,6 @@ DefaultTrapHandler:
;
.handle_Shutdown:
call IDT.DelHandler, zero
stop
.handle_HaltMode:

View File

@ -3,16 +3,16 @@
N := 11
builtins.dir:
.handle_DIR:
push rbp
mov rbp, rsp
push r12, r13
push r14, r15
nul r12 # no. of files found
nul r13 # no. of directories found
nul r14 # total amount of bytes found
nul r12 ; no. of files found
nul r13 ; no. of directories found
nul r14 ; total amount of bytes found
call print, .dirmsg
@ -40,7 +40,7 @@ builtins.dir:
bnz rdx, .is_dir
; found a file
inc r12, 1
inc r12
; separate extension from file name
mov rcx, FNAME_MAX
@ -50,37 +50,37 @@ builtins.dir:
; print file name
sub ax1, rsi, rdi
dec ax1, 1
dec ax1
call nprint, rdi
; calculate where to put extension
sub rdi, rsi, .buf
dec rdi, 1
dec rdi
.ext_pad:
; print at least N non-space characters before extension
blte N, rdi, .print_ext
prn ' '
inc rdi, 1
inc rdi
jmp .ext_pad
.print_ext:
prn ' '
; here we print at least 4 characters excluding '.'
mov rcx, 4
prn ' '
bne b[rsi], '.', .print_ext.1
inc rsi, 1
inc rsi
.print_ext.1:
bzr b[rsi], .print_ext.2
; print and decrease rcx, unless it's already 0
prn b[rsi]
inc rsi, 1
inc rsi
jrcxz .print_ext.1
dec rcx, 1
dec rcx
jmp .print_ext.1
.print_ext.2:
@ -127,11 +127,11 @@ builtins.dir:
pop r13, r12
leave
ret
jmp .print_prompt
; special case: direcory
.is_dir:
inc r13, 1
inc r13
; use printf instead of print
; because it returns # of printed
@ -140,7 +140,7 @@ builtins.dir:
blte N, rax, .dir_no_pad
sub rcx, N, rax
dec rcx, 1
dec rcx
.dir.l:
prn ' '

56
ka/usr/cmd-exec.k Normal file
View File

@ -0,0 +1,56 @@
; The OS/K Team licenses this file to you under the MIT license.
; See the LICENSE file in the project root for more information.
.try_exec:
; try without appending ".com"
mov rax, Sys.OpenFile
mov ax0, argv0
trap 0
; we good?
blte zero, rax, .do_exec
; nope, append ".com" and try again
sub rcx, argbuf.size, 5
scasb ax0, zero ; find null-term
mov b[ax0+0], '.' ; ".com"
mov b[ax0+1], 'c'
mov b[ax0+2], 'o'
mov b[ax0+3], 'm'
nul b[ax0+4]
; try again
mov rax, Sys.OpenFile
mov ax0, argv0
trap 0
; still no good?
bltz rax, .exec_not_found
.do_exec:
; load file into memory
mov ax0, rax
mov ax1, FILE_LOADP
mov ax2, FILE_MAXSZ
mov rax, Sys.ReadFile
trap 0
; save load address
mov rcx, rax
; close file
mov rax, Sys.CloseFile
trap 0
; read anything?
bltz rcx, .couldnt_read
jrcxz .empty_file
; all good, let's go
mov rax, Sys.ExecuteInFrame
mov ax0, FILE_LOADP
mov ax1, 5
trap 0
; unreachable
jmp abort

60
ka/usr/cmd-fsmisc.k Normal file
View File

@ -0,0 +1,60 @@
; The OS/K Team licenses this file to you under the MIT license.
; See the LICENSE file in the project root for more information.
.handle_ERASE:
mov rax, Sys.RemoveFile
mov ax0, q[argv1pos]
bzr ax0, .need_params
trap 0
bltz rax, .couldnt_remove
jmp .handle_MAKE ; re-create it back
.handle_MAKE:
mov rax, Sys.CreateFile
mov ax0, q[argv1pos]
bzr ax0, .need_params
trap 0
bltz rax, .couldnt_open
jmp .print_prompt
.handle_PRINT:
mov rax, Sys.OpenFile
mov ax0, q[argv1pos]
bzr ax0, .need_params
trap 0
bltz rax, .file_not_found
mov ax0, rax
mov ax1, FILE_LOADP
mov ax2, FILE_MAXSZ
mov rax, Sys.ReadFile
trap 0
mov rcx, rax
mov rax, Sys.CloseFile
trap 0
bltz rcx, .couldnt_read
jrcxz .empty_file
call nprint, FILE_LOADP, rcx
jmp .print_prompt
.handle_REMOVE:
mov rax, Sys.RemoveFile
mov ax0, q[argv1pos]
bzr ax0, .need_params
trap 0
bltz rax, .couldnt_remove
jmp .print_prompt

View File

@ -1,430 +0,0 @@
; The OS/K Team licenses this file to you under the MIT license.
; See the LICENSE file in the project root for more information.
argbuf.size := 256
argbuf = [argbuf.size]
argv0 = [argbuf.size]
argv1pos = 0
stdin_echoing = 1
prompt = [32]
main:
mov rsi, prompt
mov b[rsi+0], 'C'
mov b[rsi+1], ':'
mov b[rsi+2], '\'
mov b[rsi+3], '>'
mov b[rsi+4], ' '
.print_prompt:
call print, prompt
; empty stuff
call memzero, argbuf, argbuf.size
call memzero, argv0, argbuf.size
nul q[argv1pos]
# call nprint, argv0, argbuf.size
; iterator through argbuf
nul rcx
.input_loop:
pause
pause
pause
; Fill .buf with user input
scan rax
jraxz .input_loop
; ESC key pressed?
beq rax, 0x1B, .handle_EXIT
; backspace character?
bne rax, 8, .handle_input
; anything to delete?
jrcxz .input_loop ; no
; yes, delete it
dec rcx, 1
add rdx, rcx, argbuf
nul b[rdx]
; update screen
bzr b[stdin_echoing], .input_loop
prn 8
jmp .input_loop
.handle_input:
bzr b[stdin_echoing], .se.z
prn rax
.se.z:
beq rax, 10, .extract_argv0
; when max line length is reached,
; force a newline
beq rcx, argbuf.size, .extract_argv0
; add character to buffer and increase iterator (rcx)
add rdx, rcx, argbuf
mov b[rdx], rax
inc rcx, 1
; another one
jmp .input_loop
.extract_argv0:
; did we read anything at all?
; if not, just go back to waiting input
jrcxz .print_prompt
; find first whitespace or null-terminator
mov rcx, argbuf.size
mov rdx, argbuf
scasb rdx, ' '
; argv1 exists? if so, save its position
mov rsi, rdx
.next_space:
mov rcx, b[rsi]
jrcxz .do_extract
; skip spaces
bne rcx, ' ', .not_a_space
inc rsi, 1
jmp .next_space
.not_a_space:
; if we're here, we found a
; non-zero non-space character
mov q[argv1pos], rsi
; fallthrough
.do_extract:
; how much do we copy?
sub rcx, rdx, argbuf
jrcxz .detect_builtin
dec rcx, 1
mov rdi, argbuf
mov rsi, argv0
.copy_loop:
mov b[rsi], b[rdi]
inc rdi, 1
inc rsi, 1
loop .copy_loop
.detect_builtin:
.builtin_cls = "cls"
call strcmp, argv0, .builtin_cls
jraxz .handle_CLS
.builtin_crash = "crash"
call strcmp, argv0, .builtin_crash
jraxz .handle_CRASH
.builtin_date = "date"
call strcmp, argv0, .builtin_date
jraxz .handle_DATE
.builtin_dir = "dir"
call strcmp, argv0, .builtin_dir
jraxz .handle_DIR
.builtin_dump = "dump"
call strcmp, argv0, .builtin_dump
jraxz .handle_DUMP
.builtin_echo = "echo"
call strcmp, argv0, .builtin_echo
jraxz .handle_ECHO
.builtin_erase = "erase"
call strcmp, argv0, .builtin_erase
jraxz .handle_ERASE
.builtin_exit = "exit"
call strcmp, argv0, .builtin_exit
jraxz .handle_EXIT
.builtin_help = "help"
call strcmp, argv0, .builtin_help
jraxz .handle_HELP
.builtin_halt = "halt"
call strcmp, argv0, .builtin_halt
jraxz .handle_HALT
.builtin_make = "make"
call strcmp, argv0, .builtin_make
jraxz .handle_MAKE
.builtin_print = "print"
call strcmp, argv0, .builtin_print
jraxz .handle_PRINT
.builtin_prompt = "prompt"
call strcmp, argv0, .builtin_prompt
jraxz .handle_PROMPT
.builtin_remove = "remove"
call strcmp, argv0, .builtin_remove
jraxz .handle_REMOVE
.builtin_time = "time"
call strcmp, argv0, .builtin_time
jraxz .handle_TIME
.builtin_vers = "vers"
call strcmp, argv0, .builtin_vers
jraxz .handle_VERS
jmp .command_not_found
;
; call builtins
;
.handle_CLS:
prn PRN_CLEAR
jmp .print_prompt
.handle_CRASH:
mov rax, 0xDEADBEEF
trap 0
jmp .print_prompt
.handle_DATE:
call GetTimeUTC
mov rcx, b[rax+4]
inc rcx, 1
push b[rax+3], rcx, w[rax+6]
call printf, .datefmt
inc rsp, 40
jmp .print_prompt
.datefmt = "%d/%d/%d\n"
.handle_DIR:
call builtins.dir
jmp .print_prompt
.handle_DUMP:
dump
jmp .print_prompt
.handle_ECHO:
mov rax, q[argv1pos]
jraxz .echo.end
call print, rax
.echo.end:
prn 10
jmp .print_prompt
.handle_ERASE:
mov rax, Sys.RemoveFile
mov ax0, q[argv1pos]
bzr ax0, .need_params
trap 0
bltz rax, .couldnt_remove
jmp .handle_MAKE ; re-create it back
.handle_EXIT:
mov rax, Sys.Shutdown
trap 0
jmp .print_prompt
.handle_HALT:
mov rax, Sys.EnterHaltMode
trap 0
jmp .print_prompt
.handle_MAKE:
mov rax, Sys.CreateFile
mov ax0, q[argv1pos]
bzr ax0, .need_params
trap 0
bltz rax, .couldnt_open
jmp .print_prompt
.handle_PRINT:
mov rax, Sys.OpenFile
mov ax0, q[argv1pos]
bzr ax0, .need_params
trap 0
bltz rax, .file_not_found
mov ax0, rax
mov ax1, FILE_LOADP
mov ax2, FILE_MAXSZ
mov rax, Sys.ReadFile
trap 0
mov rcx, rax
mov rax, Sys.CloseFile
trap 0
bltz rcx, .couldnt_read
jrcxz .empty_file
call nprint, FILE_LOADP, rcx
jmp .print_prompt
.handle_PROMPT:
mov ax0, prompt
mov ax1, q[argv1pos]
bzr ax1, .need_params
call strcpy
jmp .print_prompt
.handle_REMOVE:
mov rax, Sys.RemoveFile
mov ax0, q[argv1pos]
bzr ax0, .need_params
trap 0
bltz rax, .couldnt_remove
jmp .print_prompt
.handle_TIME:
call GetTimeUTC
push b[rax], b[rax+1], b[rax+2]
call printf, .timefmt
inc rsp, 24
jmp .print_prompt
.timefmt = "%d:%d:%d\n"
.handle_VERS:
call print, cmd.versionstr
prn 10
jmp .print_prompt
.handle_HELP:
call print, .helpmsg
call print, .helpmsg.cls
call print, .helpmsg.date
call print, .helpmsg.dir
call print, .helpmsg.dump
call print, .helpmsg.echo
call print, .helpmsg.erase
call print, .helpmsg.exit
call print, .helpmsg.help
call print, .helpmsg.halt
call print, .helpmsg.make
call print, .helpmsg.print
call print, .helpmsg.prompt
call print, .helpmsg.remove
call print, .helpmsg.time
call print, .helpmsg.ver
jmp .print_prompt
.helpmsg = "The following commands are built-in:\n"
.helpmsg.cls = " CLS Clear screen\n"
.helpmsg.date = " DATE Display current date\n"
.helpmsg.dir = " DIR Print contents of current directory\n"
.helpmsg.dump = " DUMP Toggles debug instruction dumping\n"
.helpmsg.echo = " ECHO Write arguments to standard output\n"
.helpmsg.erase = " ERASE Clear a file, making it blank\n"
.helpmsg.exit = " EXIT Initiate machine shutdown\n"
.helpmsg.help = " HELP Display these messages\n"
.helpmsg.halt = " HALT Put processor in halt mode\n"
.helpmsg.make = " MAKE Create an empty file\n"
.helpmsg.print = " PRINT Display contents of text file\n"
.helpmsg.prompt = " PROMPT Change the command line prompt\n"
.helpmsg.remove = " REMOVE Delete a file (permanently)\n"
.helpmsg.time = " TIME Display current time of day\n"
.helpmsg.ver = " VERS Display current COMMAND.COM version\n"
.command_not_found:
call print, argv0
call print, .cnf_errmsg
jmp .print_prompt
.cnf_errmsg = ": command not found\n"
.file_not_found:
push q[argv1pos], argv0
call printf, .fnf_errmsg
inc rsp, 16
jmp .print_prompt
.fnf_errmsg = "%s: %s: file not found\n"
.empty_file:
push q[argv1pos], argv0
call printf, .ef_errmsg
inc rsp, 16
jmp .print_prompt
.ef_errmsg = "%s: %s: file was empty\n"
.couldnt_open:
push q[argv1pos], argv0
call printf, .cno_errmsg
inc rsp, 16
jmp .print_prompt
.cno_errmsg = "%s: %s: an error occured while opening file\n"
.couldnt_remove:
push q[argv1pos], argv0
call printf, .cne_errmsg
inc rsp, 16
jmp .print_prompt
.cne_errmsg = "%s: %s: an error occured while removing file\n"
.couldnt_read:
push q[argv1pos], argv0
call printf, .cnr_errmsg
inc rsp, 16
jmp .print_prompt
.cnr_errmsg = "%s: %s: an error occured while reading file\n"
.need_params:
call print, argv0
call print, .np_errmsg
jmp .print_prompt
.np_errmsg = ": need more parameters\n"

View File

@ -23,7 +23,7 @@ size_t rfs_current_idx = 0;
CHK_INDEX(idx); \
if (rfs[idx] == NULL) \
_except(E_UDF, \
"cpudev: operation on inactive reframe #%u", idx);
"cpudev: operation on inactive rframe #%u", idx);
//----------------------------------------------------------------------------//

View File

@ -57,7 +57,7 @@ long diskdev_findnext(dev_t *dev)
if (lstat(name, &st) < 0)
{
perror("diskdev: couldn't stat file in directory: ");
//perror("diskdev: couldn't stat file in directory: ");
R(RCX) = -1;
R(RDX) = -1;
}
@ -102,7 +102,7 @@ long diskdev_open(dev_t *dev)
if (tmp < 0)
{
perror("diskdev: open");
//perror("diskdev: open");
return -1;
}

View File

@ -44,6 +44,7 @@ negv 1
negv 2
# Addition
inc 1
add 2
add 3
@ -52,6 +53,7 @@ addv 2
addv 3
# Substraction
dec 1
sub 2
sub 3

View File

@ -68,6 +68,7 @@ IMPL_START(negv, 2) {
//----------------------------------------------------------------------------//
IMPL_START(inc, 1) { SRCP(p1); *r1 = p1->val + 1; return 1; }
IMPL_START(add, 2) { SRCP(p1); SRCP(p2); *r1 = p1->val + p2->val; return 1; }
IMPL_START(add, 3) { SRCP(p2); SRCP(p3); *r1 = p2->val + p3->val; return 1; }
@ -97,6 +98,7 @@ IMPL_START(addv, 3) {
//----------------------------------------------------------------------------//
IMPL_START(dec, 1) { SRCP(p1); *r1 = p1->val - 1; return 1; }
IMPL_START(sub, 2) { SRCP(p1); SRCP(p2); *r1 = p1->val - p2->val; return 1; }
IMPL_START(sub, 3) { SRCP(p2); SRCP(p3); *r1 = p2->val - p3->val; return 1; }

View File

@ -11,7 +11,7 @@ Values for ModRMs:
(for memory accesses, xxxxx = access size)
001xxxxx [reg]
010xxxxx [reg+reg]
011xxxxx [reg+reg+imm16]
011xxxxx [reg+imm16]
100xxxxx [reg+reg+imm32]
101xxxxx [reg+reg*imm8+imm32]
110xxxxx [reg+imm64]

View File

@ -157,8 +157,8 @@ static void extract_param(instr_t *in, acc_t *p)
case 3:
p->type = AM_RRI;
p->reg1 = fetchb();
p->reg2 = fetchb();
p->imm2 = (short)fetchw();
p->reg2 = RZX;
p->imm1 = 1;
break;

View File

@ -36,13 +36,20 @@ ulong writestr(ulong addr, ulong maxn, char *str)
//----------------------------------------------------------------------------//
#ifdef _WANT_ALIGN
#define CHK_ALIGN(type) \
if (addr % alignof(type) > 0) { \
_except(E_ALI, \
"Non-aligned memory access: 0x%012lX (0x%012lX) by %lu", \
addr, real, alignof(type)); \
"Non-aligned memory access: 0x%012lX (0x%012lX) by %lu vs %lu", \
addr, real, alignof(type) - (addr % alignof(type)), \
alignof(type)); \
}
#else
#define CHK_ALIGN(type)
#endif
//----------------------------------------------------------------------------//
static ulong readmem8(ulong real, ulong addr)