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 = { i_aliases = {
"inc_2" : "add_2", "inc_2" : "add_2",
"dec_2" : "sub_2", #"dec_2" : "sub_2",
} }
def parse_instr(line): def parse_instr(line):
@ -564,13 +564,20 @@ def parse_instr(line):
instr_args += "%%imm8 {} {} {}".format(fmts["m_rr"]|mlen, '$'+reg1, '$'+reg2) instr_args += "%%imm8 {} {} {}".format(fmts["m_rr"]|mlen, '$'+reg1, '$'+reg2)
size += 3 size += 3
# [reg+reg+imm] # [reg+imm16]
else: elif reg2 == 'zero':
instr_args += "%%imm8 {} {} {} %%signed %%imm16 {}"\ instr_args += "%%imm8 {} {} %%signed %%imm16 {}"\
.format(fmts["m_rriw"]|mlen, '$'+reg1, '$'+reg2, imm2) .format(fmts["m_rriw"]|mlen, '$'+reg1, imm2)
size += 5 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: else:
instr_args += "%%imm8 {} {} {} %%imm8 {} %%signed %%imm32 {}"\ instr_args += "%%imm8 {} {} {} %%imm8 {} %%signed %%imm32 {}"\
.format(fmts["m_rrii"]|mlen, '$'+reg1, '$'+reg2, imm1, imm2) .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) instr_args += "%%imm8 {} {}".format(fmts["m_r"]|mlen, '$'+word)
size += 2 size += 2
# [imm], converted to [zero+imm] # [imm32], converted to [zero+imm32]
else: else:
instr_args += "%%imm8 {} $zero $zero %%signed %%imm32 {}".format(fmts["m_rrid"]|mlen, word) instr_args += "%%imm8 {} $zero $zero %%signed %%imm32 {}".format(fmts["m_rrid"]|mlen, word)
size += 7 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: A function's assembly code looks like this:
label: label:
enter N enter N*8
... ...
... ...
... ...
leave leave
ret ret
'N' is the number of local variables used by the function. '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: The above code is equivalent to (and can be substitued by) the following:
label: 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. ; The OS/K Team licenses this file to you under the MIT license.
; See the LICENSE file in the project root for more information. ; See the LICENSE file in the project root for more information.
__cmdstart: cmdstart:
jmp start jmp start
include "crt/crt.k" 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: start:
mov rsp, 0x120000 mov rsp, CMDCOM_STACK
mov rbp, zero mov rbp, zero
cls
call main call main
mov rax, Sys.EnterHaltMode mov rax, Sys.EnterHaltMode
@ -20,8 +26,374 @@ start:
crash 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" 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/strtol.k"
include "crt/fmt/doprnt.k" include "crt/fmt/doprnt.k"
include "crt/fmt/printf.k" include "crt/fmt/printf.k"
exit:
mov rax, Sys.Exit
trap 0
abort: abort:
crash crash

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -15,6 +15,20 @@ Sys.Shutdown := 0x00
; ;
Sys.Exit := 0x01 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 syscalls
; ;
; Find file on disk ; Find file on disk

View File

@ -10,13 +10,17 @@ include "crt/crt.k"
; ;
; Special addresses ; Special addresses
; ;
DOSKRNL_CODE := 0x100000 ; 1MB (code) DOSKRNL_CODE := 0x100000 ; 1MB
DOSKRNL_STACK := 0x110000 ; + 64KB DOSKRNL_STACK := 0x104000 ; + 16KB
TRAP0_STACK := 0x112000 ; + 8KB TRAP0_STACK := 0x104800 ; + 18KB
INTR0_STACK := 0x114000 ; + 8KB INTR0_STACK := 0x105000 ; + 20KB
EXCT0_STACK := 0x118000 ; + 8KB 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 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 ret
RFS.LoadReg: RFS.LoadReg:
.slot := 33 iocall CPUDEV, 33
iocall CPUDEV, .slot
ret ret
RFS.StoreReg: RFS.StoreReg:

View File

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

View File

@ -20,7 +20,7 @@ DefaultExceptionHandler:
.err_udf = "Undefined behaviour exception\0\0" .err_udf = "Undefined behaviour exception\0\0"
.err_ill = "Illformed instruction exception" .err_ill = "Illformed instruction exception"
.err_acc = "Invalid memory access 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_dbf = "Double fault exception~~~~~~~~\0"
.err_imp = "Feat. not implemented exception" .err_imp = "Feat. not implemented exception"
.err_ali = "Misalignmed address exception\0\0" .err_ali = "Misalignmed address exception\0\0"

View File

@ -40,8 +40,11 @@ DefaultTrapHandler:
call RFS.LoadReg, r14, $rax call RFS.LoadReg, r14, $rax
call RFS.LoadArgs, r14 call RFS.LoadArgs, r14
; will be optimized with a table
; when we have a "finished" consistent API
jraxz .handle_Shutdown jraxz .handle_Shutdown
beq rax, Sys.Exit, .handle_Exit beq rax, Sys.Exit, .handle_Exit
beq rax, Sys.ExecuteInFrame, .handle_EIF
beq rax, Sys.ReadFile, .handle_ReadFile beq rax, Sys.ReadFile, .handle_ReadFile
beq rax, Sys.OpenFile, .handle_OpenFile beq rax, Sys.OpenFile, .handle_OpenFile
beq rax, Sys.CloseFile, .handle_CloseFile beq rax, Sys.CloseFile, .handle_CloseFile
@ -51,8 +54,12 @@ DefaultTrapHandler:
beq rax, Sys.FindFirst, .handle_FindFirst beq rax, Sys.FindFirst, .handle_FindFirst
beq rax, Sys.EnterHaltMode, .handle_HaltMode beq rax, Sys.EnterHaltMode, .handle_HaltMode
.sod:
call ScreenOfDeath, .badsyscall, r13 call ScreenOfDeath, .badsyscall, r13
.wrong:
call ScreenOfDeath, .badparams, r13
.fini.savecx: .fini.savecx:
mov ax2, rcx mov ax2, rcx
call RFS.StoreReg, r14, $rcx call RFS.StoreReg, r14, $rcx
@ -61,6 +68,7 @@ DefaultTrapHandler:
jmp TrapHandlers.epilog jmp TrapHandlers.epilog
.badsyscall = "Invalid syscall number in RAX" .badsyscall = "Invalid syscall number in RAX"
.badparams = "Invalid syscall parameters"
;------------------------------------------------; ;------------------------------------------------;
; Syscall implementations ; ; Syscall implementations ;
@ -70,48 +78,91 @@ DefaultTrapHandler:
; Pass control to COMMAND.COM in frame 0 ; Pass control to COMMAND.COM in frame 0
; ;
.handle_Exit: .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 call DISK.OpenFile, .cmdcom
; Crash on failure ; crash on failure
bltz rax, abort bltz rax, abort
; Load at CMDCOM_LOADP ; load at CMDCOM_LOADP
mov ax1, CMDCOM_LOADP mov ax1, CMDCOM_LOADP
mov ax2, CMDCOM_MAXSZ mov ax2, CMDCOM_MAXSZ
call DISK.ReadFile, rax call DISK.ReadFile, rax
; Assume that COMMAND.COM being ; assume that COMMAND.COM being
; less then 4KB means something ; less then 4KB means something
; went wrong ; went wrong
blt rax, 0x1000, abort blt rax, 0x1000, abort
; Close the handle ; close the handle
call DISK.CloseFile, rax call DISK.CloseFile, rax
; Code address ; code address
mov ax2, 0x100000 mov ax2, 0x100000
call RFS.StoreReg, zero, $rip call RFS.StoreReg, zero, $rip
; Usermode ; usermode
mov ax2, 3 mov ax2, 3
call RFS.StoreReg, zero, $cr0 call RFS.StoreReg, zero, $cr0
mov rcx, CMDCOM_LOADP mov rcx, CMDCOM_LOADP
dec rcx, 0x100000 sub rcx, 0x100000
; Code offset ; code offset
mov ax2, rcx mov ax2, rcx
call RFS.StoreReg, zero, $cr1 call RFS.StoreReg, zero, $cr1
; Return frame ; return frame
nul r14 nul r14
jmp .fini jmp .fini
.cmdcom = "command.com" .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 ; Disk API
; ;
@ -154,7 +205,6 @@ DefaultTrapHandler:
; ;
.handle_Shutdown: .handle_Shutdown:
call IDT.DelHandler, zero call IDT.DelHandler, zero
stop stop
.handle_HaltMode: .handle_HaltMode:

View File

@ -3,16 +3,16 @@
N := 11 N := 11
builtins.dir: .handle_DIR:
push rbp push rbp
mov rbp, rsp mov rbp, rsp
push r12, r13 push r12, r13
push r14, r15 push r14, r15
nul r12 # no. of files found nul r12 ; no. of files found
nul r13 # no. of directories found nul r13 ; no. of directories found
nul r14 # total amount of bytes found nul r14 ; total amount of bytes found
call print, .dirmsg call print, .dirmsg
@ -40,7 +40,7 @@ builtins.dir:
bnz rdx, .is_dir bnz rdx, .is_dir
; found a file ; found a file
inc r12, 1 inc r12
; separate extension from file name ; separate extension from file name
mov rcx, FNAME_MAX mov rcx, FNAME_MAX
@ -50,37 +50,37 @@ builtins.dir:
; print file name ; print file name
sub ax1, rsi, rdi sub ax1, rsi, rdi
dec ax1, 1 dec ax1
call nprint, rdi call nprint, rdi
; calculate where to put extension ; calculate where to put extension
sub rdi, rsi, .buf sub rdi, rsi, .buf
dec rdi, 1 dec rdi
.ext_pad: .ext_pad:
; print at least N non-space characters before extension ; print at least N non-space characters before extension
blte N, rdi, .print_ext blte N, rdi, .print_ext
prn ' ' prn ' '
inc rdi, 1 inc rdi
jmp .ext_pad jmp .ext_pad
.print_ext: .print_ext:
prn ' '
; here we print at least 4 characters excluding '.' ; here we print at least 4 characters excluding '.'
mov rcx, 4 mov rcx, 4
prn ' '
bne b[rsi], '.', .print_ext.1 bne b[rsi], '.', .print_ext.1
inc rsi, 1 inc rsi
.print_ext.1: .print_ext.1:
bzr b[rsi], .print_ext.2 bzr b[rsi], .print_ext.2
; print and decrease rcx, unless it's already 0 ; print and decrease rcx, unless it's already 0
prn b[rsi] prn b[rsi]
inc rsi, 1 inc rsi
jrcxz .print_ext.1 jrcxz .print_ext.1
dec rcx, 1 dec rcx
jmp .print_ext.1 jmp .print_ext.1
.print_ext.2: .print_ext.2:
@ -127,11 +127,11 @@ builtins.dir:
pop r13, r12 pop r13, r12
leave leave
ret jmp .print_prompt
; special case: direcory ; special case: direcory
.is_dir: .is_dir:
inc r13, 1 inc r13
; use printf instead of print ; use printf instead of print
; because it returns # of printed ; because it returns # of printed
@ -140,7 +140,7 @@ builtins.dir:
blte N, rax, .dir_no_pad blte N, rax, .dir_no_pad
sub rcx, N, rax sub rcx, N, rax
dec rcx, 1 dec rcx
.dir.l: .dir.l:
prn ' ' 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); \ CHK_INDEX(idx); \
if (rfs[idx] == NULL) \ if (rfs[idx] == NULL) \
_except(E_UDF, \ _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) 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(RCX) = -1;
R(RDX) = -1; R(RDX) = -1;
} }
@ -102,7 +102,7 @@ long diskdev_open(dev_t *dev)
if (tmp < 0) if (tmp < 0)
{ {
perror("diskdev: open"); //perror("diskdev: open");
return -1; return -1;
} }

View File

@ -44,6 +44,7 @@ negv 1
negv 2 negv 2
# Addition # Addition
inc 1
add 2 add 2
add 3 add 3
@ -52,6 +53,7 @@ addv 2
addv 3 addv 3
# Substraction # Substraction
dec 1
sub 2 sub 2
sub 3 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, 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; } 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, 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; } 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) (for memory accesses, xxxxx = access size)
001xxxxx [reg] 001xxxxx [reg]
010xxxxx [reg+reg] 010xxxxx [reg+reg]
011xxxxx [reg+reg+imm16] 011xxxxx [reg+imm16]
100xxxxx [reg+reg+imm32] 100xxxxx [reg+reg+imm32]
101xxxxx [reg+reg*imm8+imm32] 101xxxxx [reg+reg*imm8+imm32]
110xxxxx [reg+imm64] 110xxxxx [reg+imm64]

View File

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

View File

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