; 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: jmp start #include "crt/crt.k" #define CMDCOM_CODE 0x100000 // 1MB #define 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 veesions as well #define FILE_LOADP 0x108000 // + 32KB start: mov esp, CMDCOM_STACK mov ebp, zero call main mov eax, Sys.EnterHaltMode trap 0 crash cmd.veesionstr = "COMMAND.COM, veesion 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 esi, prompt mov b[esi+0], 'C' mov b[esi+1], ':' mov b[esi+2], '\' mov b[esi+3], '>' mov b[esi+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 ecx .input_loop: pause pause pause ; Fill .buf with user input scan eax jeaxz .input_loop ; ESC key pressed? beq eax, 0x1B, .handle_EXIT ; backspace character? bne eax, 8, .handle_input ; anything to delete? jecxz .input_loop ; no ; yes, delete it dec ecx add edx, ecx, argbuf nul b[edx] ; update screen bzr b[stdin_echoing], .input_loop prn 8 jmp .input_loop .handle_input: bzr b[stdin_echoing], .se.z prn eax .se.z: beq eax, 10, .extract_argv0 ; when max line length is reached, ; force a newline beq ecx, argbuf.size, .extract_argv0 ; add character to buffer and increase iterator (ecx) add edx, ecx, argbuf mov b[edx], eax inc ecx ; another one jmp .input_loop .extract_argv0: ; did we read anything at all? ; if not, just go back to waiting input jecxz .print_prompt ; find first whitespace or null-terminator mov ecx, argbuf.size mov edx, argbuf scasb edx, ' ' ; argv1 exists? if so, save its position mov esi, edx .next_space: mov ecx, b[esi] jecxz .do_extract ; skip spaces bne ecx, ' ', .not_a_space inc esi jmp .next_space .not_a_space: ; if we're here, we found a ; non-zero non-space character mov q[argv1pos], esi ; fallthrough .do_extract: ; how much do we copy? sub ecx, edx, argbuf jecxz .detect_builtin dec ecx mov edi, argbuf mov esi, argv0 .copy_loop: mov b[esi], b[edi] inc edi inc esi loop .copy_loop .detect_builtin: .builtin_cls = "cls" call strcmp, argv0, .builtin_cls jeaxz .handle_CLS .builtin_crash = "crash" call strcmp, argv0, .builtin_crash jeaxz .handle_CRASH .builtin_date = "date" call strcmp, argv0, .builtin_date jeaxz .handle_DATE .builtin_dir = "dir" call strcmp, argv0, .builtin_dir jeaxz .handle_DIR .builtin_dump = "dump" call strcmp, argv0, .builtin_dump jeaxz .handle_DUMP .builtin_echo = "echo" call strcmp, argv0, .builtin_echo jeaxz .handle_ECHO .builtin_erase = "erase" call strcmp, argv0, .builtin_erase jeaxz .handle_ERASE .builtin_exit = "exit" call strcmp, argv0, .builtin_exit jeaxz .handle_EXIT .builtin_help = "help" call strcmp, argv0, .builtin_help jeaxz .handle_HELP .builtin_halt = "halt" call strcmp, argv0, .builtin_halt jeaxz .handle_HALT .builtin_make = "make" call strcmp, argv0, .builtin_make jeaxz .handle_MAKE .builtin_print = "print" call strcmp, argv0, .builtin_print jeaxz .handle_PRINT .builtin_prompt = "prompt" call strcmp, argv0, .builtin_prompt jeaxz .handle_PROMPT .builtin_remove = "remove" call strcmp, argv0, .builtin_remove jeaxz .handle_REMOVE .builtin_time = "time" call strcmp, argv0, .builtin_time jeaxz .handle_TIME .builtin_vers = "vers" call strcmp, argv0, .builtin_vers jeaxz .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 ecx, b[eax+4] inc ecx push b[eax+3], ecx, w[eax+6] call printf, .datefmt add esp, 40 jmp .print_prompt .datefmt = "%d/%d/%d\n" .handle_DUMP: dump jmp .print_prompt .handle_ECHO: mov eax, q[argv1pos] jeaxz .echo.end call print, eax .echo.end: prn 10 jmp .print_prompt .handle_EXIT: mov eax, Sys.Shutdown trap 0 jmp .print_prompt .handle_HALT: mov eax, 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[eax], b[eax+1], b[eax+2] call printf, .timefmt add esp, 24 jmp .print_prompt .timefmt = "%d:%d:%d\n" .handle_VERS: call print, cmd.veesionstr 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 veesion\n" .exec_not_found: push argv0 call printf, .enf_errmsg add esp, 8 jmp .print_prompt .enf_errmsg = "%s: file not found\n" .file_not_found: push q[argv1pos], argv0 call printf, .fnf_errmsg add esp, 16 jmp .print_prompt .fnf_errmsg = "%s: %s: file not found\n" .empty_file: push q[argv1pos], argv0 call printf, .ef_errmsg add esp, 16 jmp .print_prompt .ef_errmsg = "%s: %s: file was empty\n" .couldnt_open: push q[argv1pos], argv0 call printf, .cno_errmsg add esp, 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 add esp, 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 add esp, 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"