From f1b3bf129b02abc23241e3951a96d2b1e77be6c5 Mon Sep 17 00:00:00 2001 From: julianb0 Date: Wed, 21 Aug 2019 16:57:32 +0200 Subject: [PATCH] exec --- as/k-as.py | 23 +- ka/ABI | 3 +- ka/FIXME | 2 + ka/command.k | 386 +++++++++++++++++++++++++++- ka/crt/crt.k | 5 + ka/crt/fmt/doprnt.k | 10 +- ka/crt/fmt/ltostr.k | 4 +- ka/crt/fmt/printf.k | 4 +- ka/crt/fmt/strtol.k | 24 +- ka/crt/mem.k | 2 +- ka/crt/str.k | 34 +-- ka/crt/sys.k | 14 ++ ka/doskrnl.k | 16 +- ka/hello.k | 18 ++ ka/sys/drv/cpudev.k | 3 +- ka/sys/intr/common.k | 3 +- ka/sys/intr/excepts.k | 2 +- ka/sys/intr/trap0.k | 72 +++++- ka/usr/{cmd/dir.k => cmd-dir.k} | 30 +-- ka/usr/cmd-exec.k | 56 +++++ ka/usr/cmd-fsmisc.k | 60 +++++ ka/usr/cmd/main.k | 430 -------------------------------- vm/dv/cpudev.c | 2 +- vm/dv/diskdev.c | 4 +- vm/in/ALU | 2 + vm/in/alu.c | 2 + vm/pc/DECD | 2 +- vm/pc/decode.c | 2 +- vm/pc/mem.c | 11 +- 29 files changed, 698 insertions(+), 528 deletions(-) create mode 100644 ka/FIXME create mode 100644 ka/hello.k rename ka/usr/{cmd/dir.k => cmd-dir.k} (89%) create mode 100644 ka/usr/cmd-exec.k create mode 100644 ka/usr/cmd-fsmisc.k delete mode 100644 ka/usr/cmd/main.k diff --git a/as/k-as.py b/as/k-as.py index 2759334..53c5f95 100755 --- a/as/k-as.py +++ b/as/k-as.py @@ -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 diff --git a/ka/ABI b/ka/ABI index ab48b53..dca89f0 100644 --- a/ka/ABI +++ b/ka/ABI @@ -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: diff --git a/ka/FIXME b/ka/FIXME new file mode 100644 index 0000000..f494dbb --- /dev/null +++ b/ka/FIXME @@ -0,0 +1,2 @@ +Known issues: +- alignment issue... compile with _WANT_ALIGN, see &argv1pos not aligned by 8 diff --git a/ka/command.k b/ka/command.k index a596125..9809323 100644 --- a/ka/command.k +++ b/ka/command.k @@ -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" + diff --git a/ka/crt/crt.k b/ka/crt/crt.k index a6dd85b..6c7f16c 100644 --- a/ka/crt/crt.k +++ b/ka/crt/crt.k @@ -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 diff --git a/ka/crt/fmt/doprnt.k b/ka/crt/fmt/doprnt.k index 46cc890..5dfcf52 100644 --- a/ka/crt/fmt/doprnt.k +++ b/ka/crt/fmt/doprnt.k @@ -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? diff --git a/ka/crt/fmt/ltostr.k b/ka/crt/fmt/ltostr.k index dc6e3a2..1f8337a 100644 --- a/ka/crt/fmt/ltostr.k +++ b/ka/crt/fmt/ltostr.k @@ -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] diff --git a/ka/crt/fmt/printf.k b/ka/crt/fmt/printf.k index 657449b..d0d772a 100644 --- a/ka/crt/fmt/printf.k +++ b/ka/crt/fmt/printf.k @@ -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 diff --git a/ka/crt/fmt/strtol.k b/ka/crt/fmt/strtol.k index be06c57..1782346 100644 --- a/ka/crt/fmt/strtol.k +++ b/ka/crt/fmt/strtol.k @@ -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: diff --git a/ka/crt/mem.k b/ka/crt/mem.k index 196efc6..5e1f184 100644 --- a/ka/crt/mem.k +++ b/ka/crt/mem.k @@ -25,7 +25,7 @@ memzero: .l: nul b[ax0] - inc ax0, 1 + inc ax0 loop .l .r: diff --git a/ka/crt/str.k b/ka/crt/str.k index 0b72b2b..cc4a210 100644 --- a/ka/crt/str.k +++ b/ka/crt/str.k @@ -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: diff --git a/ka/crt/sys.k b/ka/crt/sys.k index 0cfb4c6..27d7da8 100644 --- a/ka/crt/sys.k +++ b/ka/crt/sys.k @@ -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 diff --git a/ka/doskrnl.k b/ka/doskrnl.k index a20e61a..025f318 100644 --- a/ka/doskrnl.k +++ b/ka/doskrnl.k @@ -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 ; diff --git a/ka/hello.k b/ka/hello.k new file mode 100644 index 0000000..c34ca45 --- /dev/null +++ b/ka/hello.k @@ -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" + diff --git a/ka/sys/drv/cpudev.k b/ka/sys/drv/cpudev.k index c278c66..c3b6d53 100644 --- a/ka/sys/drv/cpudev.k +++ b/ka/sys/drv/cpudev.k @@ -48,8 +48,7 @@ RFS.LoadArgs: ret RFS.LoadReg: -.slot := 33 - iocall CPUDEV, .slot + iocall CPUDEV, 33 ret RFS.StoreReg: diff --git a/ka/sys/intr/common.k b/ka/sys/intr/common.k index 8c6d147..b6779de 100644 --- a/ka/sys/intr/common.k +++ b/ka/sys/intr/common.k @@ -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 diff --git a/ka/sys/intr/excepts.k b/ka/sys/intr/excepts.k index 444a84d..175929c 100644 --- a/ka/sys/intr/excepts.k +++ b/ka/sys/intr/excepts.k @@ -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" diff --git a/ka/sys/intr/trap0.k b/ka/sys/intr/trap0.k index dfee844..e9e99e3 100644 --- a/ka/sys/intr/trap0.k +++ b/ka/sys/intr/trap0.k @@ -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: diff --git a/ka/usr/cmd/dir.k b/ka/usr/cmd-dir.k similarity index 89% rename from ka/usr/cmd/dir.k rename to ka/usr/cmd-dir.k index d40787a..bac4e17 100644 --- a/ka/usr/cmd/dir.k +++ b/ka/usr/cmd-dir.k @@ -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 ' ' diff --git a/ka/usr/cmd-exec.k b/ka/usr/cmd-exec.k new file mode 100644 index 0000000..696c4ab --- /dev/null +++ b/ka/usr/cmd-exec.k @@ -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 diff --git a/ka/usr/cmd-fsmisc.k b/ka/usr/cmd-fsmisc.k new file mode 100644 index 0000000..95c605e --- /dev/null +++ b/ka/usr/cmd-fsmisc.k @@ -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 + diff --git a/ka/usr/cmd/main.k b/ka/usr/cmd/main.k deleted file mode 100644 index 4c5fb87..0000000 --- a/ka/usr/cmd/main.k +++ /dev/null @@ -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" - diff --git a/vm/dv/cpudev.c b/vm/dv/cpudev.c index 2c2887d..0940da7 100644 --- a/vm/dv/cpudev.c +++ b/vm/dv/cpudev.c @@ -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); //----------------------------------------------------------------------------// diff --git a/vm/dv/diskdev.c b/vm/dv/diskdev.c index 5fe7e44..c659087 100644 --- a/vm/dv/diskdev.c +++ b/vm/dv/diskdev.c @@ -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; } diff --git a/vm/in/ALU b/vm/in/ALU index 9538961..5dc17ff 100644 --- a/vm/in/ALU +++ b/vm/in/ALU @@ -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 diff --git a/vm/in/alu.c b/vm/in/alu.c index 04ead26..9829d86 100644 --- a/vm/in/alu.c +++ b/vm/in/alu.c @@ -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; } diff --git a/vm/pc/DECD b/vm/pc/DECD index 6d684fd..01dc1fe 100644 --- a/vm/pc/DECD +++ b/vm/pc/DECD @@ -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] diff --git a/vm/pc/decode.c b/vm/pc/decode.c index bdca68f..f97baf1 100644 --- a/vm/pc/decode.c +++ b/vm/pc/decode.c @@ -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; diff --git a/vm/pc/mem.c b/vm/pc/mem.c index b7779f0..a53f587 100644 --- a/vm/pc/mem.c +++ b/vm/pc/mem.c @@ -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)