# 1 "doskrnl.k" # 1 "" # 1 "" # 31 "" # 1 "/usr/include/stdc-predef.h" 1 3 4 # 32 "" 2 # 1 "doskrnl.k" ; The OS/K Team licenses this file to you under the MIT license. ; See the LICENSE file in the project root for more information. __sysmain: jmp start # 1 "crt/crt.k" 1 ; The OS/K Team licenses this file to you under the MIT license. ; See the LICENSE file in the project root for more information. ; ; Limits ; # 31 "crt/crt.k" ; ; Magic numbers ; ; ; CRT librairies ; # 1 "./crt/sys.k" 1 ; The OS/K Team licenses this file to you under the MIT license. ; See the LICENSE file in the project root for more information. ; ; SHUTDOWN syscall ; ; End virtual machine ; Sys.Shutdown := 0x00 ; ; EXIT syscall ; ; Return to COMMAND.COM ; 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 ; ; IN ; ax0 = address of name buffer ; ax1 = size of name buffer ; ; OUT ; rax = # of bytes written in name buffer ; rdx = size of file ; ; Sys.FindFirst := 0x20 Sys.FindNext := 0x21 ; ; OPEN syscall ; ; IN ; ax0 = name string ; ; OUT ; rax = handle of file, or <0 if couldn't open ; Sys.OpenFile := 0x30 ; ; CREATE syscall ; ; IN ; ax0 = name string ; ; OUT ; rax = 0 on success, or <0 if couldn't open ; Sys.CreateFile := 0x31 ; ; REMOVE syscall ; ; IN ; ax0 = name string ; ; OUT ; rax = 0 on success, or <0 if couldn't open ; Sys.RemoveFile := 0x32 ; ; CLOSE syscall ; ; IN ; ax0 = file handle ; Sys.CloseFile := 0x35 ; ; READ syscall ; ; IN ; ax0 = file handle ; ax1 = buffer address ; ax2 = buffer size ; ; OUT ; rax = number of bytes read, <0 on error ; Sys.ReadFile := 0x38 ; Halt mode Sys.EnterHaltMode := 0x999 # 43 "crt/crt.k" 2 # 1 "./crt/str.k" 1 ; The OS/K Team licenses this file to you under the MIT license. ; See the LICENSE file in the project root for more information. ; ; int strnlen(char *, int) ; strnlen: mov rcx, ax1 scasb ax0, zero sub rax, ax1, rcx ret ; ; int strlen(char *) ; strlen: mov rcx, 0x7AFFFFFF mov rdx, rcx scasb ax0, zero sub rax, rdx, rcx ret ; ; void strcpy(char *, const char *) ; strcpy: .l: mov rcx, b[ax1] mov b[ax0], rcx jrcxz .r inc ax0 inc ax1 jmp .l .r: ret ; ; void strncpy(char *, const char *, int) ; strncpy: mov rcx, ax2 jrcxz .r .l: mov b[ax0], b[ax1] inc ax0 inc ax1 loop .l .r: ret ; ; void strnzcpy(char *, const char *, int) ; strnzcpy: mov rcx, ax2 jrcxz .r .l: mov rax, b[ax1] mov b[ax0], rax jraxz .r inc ax0 inc ax1 loop .l .z: nul b[ax0] .r: ret ; ; int strcmp(const char *str1, const char *str2) ; ; Returns: ; 0 if the contents of both strings are equal ; >0 if the first character that does not match has a greater value in str1 than in str2 ; <0 if the first character that does not match has a lower value in str1 than in str2 ; strcmp: nul rsi .l: movzx rax, b[ax0+rsi] movzx rdx, b[ax1+rsi] bne rax, rdx, .r ; both zero? add rcx, rax, rdx jrcxz .r inc rsi jmp .l .r: sub rax, rdx ret ; ; int strncmp(const char *str1, const char *str2, int maxn) ; strncmp: mov rcx, ax2 jrcxz .r .l: movzx rax, b[ax0] movzx rdx, b[ax1] bne rax, rdx, .r inc ax0 inc ax1 loop .l .r: sub rax, rdx ret ; ; char *strchrnul(const char *str, int ch) ; strchrnul: mov rcx, 0x7AFFFFFF scasb ax0, ax1 mov rax, ax0 ret ; ; char *strchr(const char *str, int ch) ; strchr: mov rcx, 0x7AFFFFFF scasb ax0, ax1 bnz b[ax0], .r nul rax ret .r: mov rax, ax0 ret ; ; void strrev(char *buf, const char *str) ; ; buf and src must NOT overlap ; strrev: bzr b[ax1], .z ; save str's location mov rsi, ax1 ; go to str's end, just before ; the null terminator mov rcx, 0x7AFFFFFF scasb ax1, zero dec ax1 .l: ; copy, going backward though str ; and forward through buf mov b[ax0], b[ax1] beq ax1, rsi, .r inc ax0 dec ax1 jmp .l .r: nul b[ax0+1] ret .z: nul b[ax0] ret ; ; void strrev2(char *str) ; ; Inverses str ; strrev2: bzr b[ax0], .r mov ax1, ax0 ; go to str's end, just before ; the null terminator mov rcx, 0x7AFFFFFF scasb ax1, zero dec ax1 ; increase ax0 while decreasing ax1, performing exchanges .l: blteu ax1, ax0, .r xchg b[ax0], b[ax1] inc ax0 dec ax1 jmp .l .r: ret # 44 "crt/crt.k" 2 # 1 "./crt/mem.k" 1 ; The OS/K Team licenses this file to you under the MIT license. ; See the LICENSE file in the project root for more information. ; ; void memcpy(void *, const void *, int) ; memcpy: mov rcx, ax2 jrcxz .r .l: sub rdx, ax2, rcx mov b[ax0+rdx], b[ax1+rdx] loop .l .r: ret ; ; void memzero(void *, int) ; memzero: mov rcx, ax1 jrcxz .r .l: nul b[ax0] inc ax0 loop .l .r: ret # 45 "crt/crt.k" 2 # 1 "./crt/time.k" 1 ; The OS/K Team licenses this file to you under the MIT license. ; See the LICENSE file in the project root for more information. ; ; struct TIME ; { ; byte sec; +0 (0-59) ; byte min; +1 (0-59) ; byte hour; +2 (0-23) ; byte mday; +3 (0-31) ; byte month; +4 (0-11) ; byte; +5 (pad) ; word year; +6 (0-65536) ; word yday; +8 (0-365) ; word; +10 (pad) ; dword; +12 (pad) ; } 16 bytes ; ; ; int DaysInYear(int year) ; DaysInYear: mov rax, 365 ; divisible by 4? rem rcx, ax0, 4 jrcxnz .end ; divisible by 100? rem rcx, ax0, 100 jrcxnz .leap ; divisible by 400? rem rcx, ax0, 400 jrcxnz .end .leap: inc rax, 1 .end: ret ; ; TIME *GetTimeUTC(void) ; GetTimeUTC: ytime mov rdi, .buf ; seconds rem rsi, rax, 60 mov b[rdi], rsi ; minutes div rsi, rax, 60 rem rsi, 60 mov b[rdi+1], rsi ; hours div rsi, rax, 3600 rem rsi, 24 mov b[rdi+2], rsi ; month days div rsi, rax, 3600*24 mov b[rdi+3], rsi ; month mov b[rdi+4], rbx ; years mov w[rdi+6], rcx ; ; ydays (TODO) ; mov rax, .buf ret .buf = [24] # 46 "crt/crt.k" 2 # 1 "./crt/fmt/ltostr.k" 1 ; The OS/K Team licenses this file to you under the MIT license. ; See the LICENSE file in the project root for more information. ; ; void itoa(char *buf, int num, int base) ; itoa: mov ax3, 1 jmp ltostr ; ; void utoa(char *buf, int num, int base) ; utoa: nul ax3 jmp ltostr ; ; void ltostr(char *buf, int num, int base, bool signed) ; ltostr: mov rax, ax0 nul rcx ; make sure base is in [2, 32] bltu ax2, 2, .bad bltu 36, ax2, .bad ; deal with zero bzr ax1, .is_zero ; deal with base 10 signedness bzr ax3, .conv bne ax2, 10, .conv ; base 10 shr rcx, ax1, 63 ; extract ax1 sign jrcxz .conv neg ax1 ; NEG if negative ; main loop .conv: bzr ax1, .fini rem rdx, ax1, ax2 ; ax1 % base blt 9, rdx, .nondec ; rdx > 9 ? inc rdx, '0' jmp .next .nondec: inc rdx, 55 ; 'A' - 10 .next: mov b[ax0], rdx inc ax0 div ax1, ax2 jmp .conv ; add minus flag, null-terminate and reverse .fini: jrcxz .cxz mov b[ax0], '-' inc ax0 .cxz: nul b[ax0] call strrev2, rax ret ; ; exceptional cases ; .bad: mov b[ax0], 0 ret .is_zero: mov b[ax0], 48 ; '0' mov b[ax0+1], 0 ret # 48 "crt/crt.k" 2 # 1 "./crt/fmt/strtol.k" 1 ; The OS/K Team licenses this file to you under the MIT license. ; See the LICENSE file in the project root for more information. ; ; int strtol(const char *str, int base) ; ; rax = integer extracted from str ; rdx = pointer to first invalid byte ; strtol: mov ax2, 1 jmp strtoq ; ; int strtoul(const char *str, int base) ; ; rax = integer extracted from str ; rdx = pointer to first invalid byte ; strtoul: nul ax2 jmp strtoq ; ; int strtoq(const char *str, int base, bool signed) ; ; guesses base when 'base'=0 ; strtoq: nul rax, rsi mov rdx, ax0 ; make sure base is in [2, 32] beq ax1, 1, .bad bltu 36, ax1, .bad ; empty string? bzr b[rdx], .done .skip_spc: bne b[rdx], ' ', .no_spc inc rdx jmp .skip_spc .no_spc: ; skip + bne b[rdx], '+', .no_plus inc rdx .no_plus: ; unsigned? bzr ax2, .unsigned ; parse '-' bne b[rdx], '-', .unsigned inc rdx mov rsi, 1 .unsigned: ; base 0 bzr ax1, .base_0 ; base prefix? bne b[rdx], '0', .main_loop inc rdx movzx rcx, b[rdx] ; "0x"/"0b" prefix jrcxz .done ; "0" beq rcx, 'x', .parsed_0x beq rcx, 'b', .parsed_0b ; may be octal, but we don't care ; we accept "0110101010" (despite base=2) for instance jmp .main_loop .parsed_0x: ; are we in base 16? ; if not, leave rax = 0 and *rdx = 'x' bne ax1, 16, .done ; else inc rdx, 1 jmp .main_loop .parsed_0b: ; are we in base 2? ; if not, leave rax = 0 and *rdx = 'b' bne ax1, 2, .done ; else inc rdx jmp .main_loop .base_0: ; guess base beq b[rdx], '0', .b0_not10 ; must be base 10 mov ax1, 10 jmp .main_loop .b0_not10: inc rdx bne b[rdx], 'x', .b0_not16 inc rdx mov ax1, 16 jmp .main_loop .b0_not16: bne b[rdx], 'b', .b0_not2 inc rdx mov ax1, 2 jmp .main_loop .b0_not2: ; take octal by default mov ax1, 8 .main_loop: movzx rcx, b[rdx] inc rdx ; between 0 and 9? bltu rcx, '0', .done bltu '9', rcx, .not_digit10 ; yes sub rcx, '0' jmp .next .not_digit10: bltu rcx, 'A', .done bltu 'Z', rcx, .not_digitAZ sub rcx, 55 ; 'A' - 10 jmp .next .not_digitAZ: bltu rcx, 'a', .done bltu 'z', rcx, .done sub rcx, 87 ; 'a' - 10 jmp .next .next: ; too large for base? blteu ax1, rcx, .done mul rax, ax1 inc rax, rcx jmp .main_loop .done: ; negative? bzr rsi, .r ; yes neg rax .r: ret .bad: ret # 49 "crt/crt.k" 2 # 1 "./crt/fmt/doprnt.k" 1 ; The OS/K Team licenses this file to you under the MIT license. ; See the LICENSE file in the project root for more information. ; ; typedef int (*PUTC)(int ch) ; int doprnt(PUTC putc, int n, const char *fmt, va_list ap) ; doprnt: push rbp mov rbp, rsp push r12, r13, r14 push r15, r16, r17 mov r12, ax2 ; fmt mov r14, ax3 ; va_list mov r15, ax1 ; n mov r17, ax0 ; putc nul r16 ; return value .main_loop: ; find '%' or null-terminator mov rcx, 0x7AFFFFFF mov r13, r12 scasb r13, '%' ; everything below r13 is a regular character; print it .print_regular: beq r12, r13, .check_modf call .doput, b[r12] inc r12, 1 jmp .print_regular .check_modf: ; did we find a '%' ? ; if not, then we found fmt's null-terminator; we're done bne b[r12], '%', .epilogue ; we did find a modifier / '%' mov rax, b[r12+1] inc r12, 2 beq rax, 's', .modf_s beq rax, 'c', .modf_c beq rax, 'p', .modf_p beq rax, 'x', .modf_x beq rax, 'd', .modf_d beq rax, 'o', .modf_o beq rax, 'b', .modf_b beq rax, '%', .modf_percent ; unrecognized jmp .bad_modifier .modf_s: ; get string address mov r13, q[r14] inc r14, 8 bzr r13, .nullstring .print_string: movzx ax0, b[r13] bzr ax0, .main_loop inc r13 call .doput jmp .print_string .modf_c: call .doput, q[r14] inc r14, 8 jmp .main_loop .modf_p: call .doput, '0' call .doput, 'x' ; Fallthrough .modf_x: mov ax2, 16 jmp .print_number .modf_d: mov ax2, 10 jmp .print_number .modf_o: mov ax2, 8 jmp .print_number .modf_b: mov ax2, 2 jmp .print_number .print_number: ; allocate itoa conversion buffer sub rsp, 80 mov r13, rsp ; assume modifier already set up ax2 call itoa, rsp, q[r14] inc r14, 8 .print_itoa_buf: movzx ax0, b[r13] bzr ax0, .pib_end_loop inc r13 call .doput jmp .print_itoa_buf .pib_end_loop: inc rsp, 80 jmp .main_loop .modf_percent: call .doput, '%' jmp .main_loop .bad_modifier: ; print "%?" to clearly indicate that something is wrong call .doput, '%' call .doput, '?' jmp .main_loop .nullstring: ; %s was passed a NULL call .doput, '(' call .doput, 'n' call .doput, 'u' call .doput, 'l' call .doput, 'l' call .doput, ')' jmp .main_loop .epilogue: mov rax, r16 pop r17, r16 pop r15, r14 pop r13, r12 leave ret ; ; prints ax0 ; .doput: ; update print count inc r16 ; if n==0, don't print ; we follow the C convention that sprintf()-like functions ; should return the number of characters that would have ; been printed/written if 'n' were big enough bzr r15, .r ; decrement n and print dec r15 call r17 ; did putc fail? jraxz .r ; yes, so artificially set n=0 nul r15 .r: ret # 50 "crt/crt.k" 2 # 1 "./crt/fmt/printf.k" 1 ; The OS/K Team licenses this file to you under the MIT license. ; See the LICENSE file in the project root for more information. ; ; int putc(int ch) ; putc: prn ax0 nul rax ret ; ; int printf(const char *fmt, ...) ; printf: mov ax2, ax0 mov ax0, putc mov ax1, 0x7AFFFFFF add ax3, rsp, 8 jmp doprnt ; ; int nprintf(const char *fmt, int n, ...) ; nprintf: mov ax2, ax0 mov ax0, putc add ax3, rsp, 8 jmp doprnt ; ; Print a string ; Guaranteed to only affect rcx and ax0 ; print: .l: movzx rax, b[ax0] jraxz .r prn rax inc ax0 jmp .l .r: ret ; ; Print exactly ax1 characters ; nprint: mov rcx, ax1 jrcxz .r .l: prn b[ax0] inc ax0 loop .l .r: ret # 51 "crt/crt.k" 2 exit: mov rax, Sys.Exit trap 0 abort: crash # 8 "doskrnl.k" 2 ; ; Special addresses ; ; 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 ; ; Entry point ; start: mov rsp, 0x104000 ; + 16KB mov rbp, zero ;dump call main crash ; ; Disk Operating System ; # 1 "sys/drv/cpudev.k" 1 ; The OS/K Team licenses this file to you under the MIT license. ; See the LICENSE file in the project root for more information. CPUDEV := 0 RFS.GetMaxIdx: iocall CPUDEV, 16 ret RFS.GetUsage: iocall CPUDEV, 17 ret RFS.GetCurIdx: iocall CPUDEV, 18 ret RFS.GetLeastAvail: iocall CPUDEV, 19 ret RFS.IsFrameActive: iocall CPUDEV, 20 ret RFS.ActivateFrame: iocall CPUDEV, 21 ret RFS.DeactivateFrame: iocall CPUDEV, 22 ret RFS.CopyFrame: iocall CPUDEV, 23 ret RFS.MoveFrame: iocall CPUDEV, 24 ret RFS.SwitchFrame: iocall CPUDEV, 25 ret RFS.LoadArgs: iocall CPUDEV, 32 ret RFS.LoadReg: iocall CPUDEV, 33 ret RFS.StoreReg: iocall CPUDEV, 48 ret IDT.AddHandler: iocall CPUDEV, 64 ret IDT.DelHandler: iocall CPUDEV, 65 ret IDT.QueryHandler: iocall CPUDEV, 66 IDT.DoneHandling: iocall CPUDEV, 67 ret # 43 "doskrnl.k" 2 # 1 "sys/drv/memdev.k" 1 ; The OS/K Team licenses this file to you under the MIT license. ; See the LICENSE file in the project root for more information. MEMDEV := 1 MEM.GetMemOff: iocall MEMDEV, 0 ret MEM.GetMemSize: iocall MEMDEV, 1 ret # 44 "doskrnl.k" 2 # 1 "sys/drv/diskdev.k" 1 ; The OS/K Team licenses this file to you under the MIT license. ; See the LICENSE file in the project root for more information. DISKDEV := 4 DISK.FindFirst: .slot := 16 iocall DISKDEV, .slot ret DISK.FindNext: .slot := 17 iocall DISKDEV, .slot ret DISK.OpenFile: iocall DISKDEV, 25 ret DISK.CloseFile: iocall DISKDEV, 26 ret DISK.CreateFile: iocall DISKDEV, 27 ret DISK.RemoveFile: iocall DISKDEV, 28 ret DISK.ReadFile: iocall DISKDEV, 32 ret DISK.WriteFile: iocall DISKDEV, 33 ret # 45 "doskrnl.k" 2 # 1 "sys/intr/excepts.k" 1 ; The OS/K Team licenses this file to you under the MIT license. ; See the LICENSE file in the project root for more information. DefaultExceptionHandler: mov rsp, 0x105800 ; + 22KB mov ax1, r12 bzr r12, DefaultTrapHandler.handle_Shutdown bltu 11, r12, .unknown mov rsi, .err_ukn lea ax0, b[rsi + r12 * 32] call ScreenOfDeath .unknown: call ScreenOfDeath, .err_ukn crash .err_ukn = "Unknown exception number\0\0\0\0\0\0\0" .err_udf = "Undefined behaviour exception\0\0" .err_ill = "Illformed instruction exception" .err_acc = "Invalid memory access exception" .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" .err_brk = "BREAK key (Ctrl+C) exception\0\0\0" .err_ovf = "Overflow flag raised exception\0" .err_div = "Division by zero exception\0\0\0\0\0" # 47 "doskrnl.k" 2 # 1 "sys/intr/common.k" 1 ; The OS/K Team licenses this file to you under the MIT license. ; See the LICENSE file in the project root for more information. ScreenOfDeath: push r12 mov r12, ax0 prn 10 prn 0x8BF00001 prn 0x8BF00002 push ax1 call printf, .scr1 pop bnz r14, .not_con push .scr2_con jmp .do_print .not_con: ; rframes #2-#3-#4 belong to kernel blt 4, r14, .not_krn push .scr2_krn jmp .do_print .not_krn: push .scr2_usr .do_print: push r14, r12 call printf, .scr2 inc rsp, 24 call dumprf, r14 prn 10 call print, .scr3 .loop: pause pause scan rax jraxz .loop beq rax, 0x0A, DefaultTrapHandler.handle_Exit beq rax, 0x1B, DefaultTrapHandler.handle_Shutdown jmp .loop crash .scr1 = "-------- Unhandled EXCEPTION, TRAP/SYSCALL or INTERRUPT (code %d)\n" .scr2 = "Description: %s\nFrame: %d (%s)\n\n" .scr3 = "Press:\n ENTER to procede to COMMAND.COM\n ESCAPE to shutdown machine\n\n" .scr2_con = "dedicated command.com frame" .scr2_usr = "userspace application frame" .scr2_krn = "exception/interrupt handler" # 48 "doskrnl.k" 2 # 1 "sys/intr/trap0.k" 1 ; The OS/K Team licenses this file to you under the MIT license. ; See the LICENSE file in the project root for more information. TrapHandlers.prolog: nul rbp ; rax = caller's cr1 call RFS.LoadReg, r14, $cr1 ; we don't preserve the r12 we got mov r12, rax nul rdx jmp rcx TrapHandlers.epilog: ; TRAP return values: RAX-RDX mov ax2, rax call RFS.StoreReg, r14, $rax mov ax2, rdx call RFS.StoreReg, r14, $rdx call IDT.DoneHandling, r13 iret ; ; TRAP #0 handler ; DefaultTrapHandler: .init: mov rcx, .text mov rsp, 0x104800 ; + 18KB jmp TrapHandlers.prolog .text: 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 beq rax, Sys.CreateFile, .handle_CreateFile beq rax, Sys.RemoveFile, .handle_RemoveFile beq rax, Sys.FindNext, .handle_FindNext 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 .fini: jmp TrapHandlers.epilog .badsyscall = "Invalid syscall number in RAX" .badparams = "Invalid syscall parameters" ;------------------------------------------------; ; Syscall implementations ; ;------------------------------------------------; ; ; 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 .hE_nz: ; open COMMAND.COM call DISK.OpenFile, .cmdcom ; crash on failure bltz rax, abort ; load at 0x108000 ; + 32KB mov ax1, 0x108000 ; + 32KB mov ax2, 0x80000 ; 512KB call DISK.ReadFile, rax ; assume that COMMAND.COM being ; less then 4KB means something ; went wrong blt rax, 0x1000, abort ; close the handle call DISK.CloseFile, rax ; code address mov ax2, 0x100000 call RFS.StoreReg, zero, $rip ; usermode mov ax2, 3 call RFS.StoreReg, zero, $cr0 mov rcx, 0x108000 ; + 32KB sub rcx, 0x100000 ; code offset mov ax2, rcx call RFS.StoreReg, zero, $cr1 ; 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 ; .handle_FindFirst: inc ax0, r12 call DISK.FindFirst jmp .fini.savecx .handle_FindNext: inc ax0, r12 call DISK.FindNext jmp .fini.savecx .handle_OpenFile: inc ax0, r12 call DISK.OpenFile jmp .fini .handle_CreateFile: inc ax0, r12 call DISK.CreateFile jmp .fini .handle_RemoveFile: inc ax0, r12 call DISK.RemoveFile jmp .fini .handle_CloseFile: call DISK.CloseFile jmp .fini .handle_ReadFile: inc ax1, r12 call DISK.ReadFile jmp .fini ; ; Misc. ; .handle_Shutdown: call IDT.DelHandler, zero stop .handle_HaltMode: pause pause hlt jmp .handle_HaltMode # 49 "doskrnl.k" 2 # 1 "sys/dumprf.k" 1 ; The OS/K Team licenses this file to you under the MIT license. ; See the LICENSE file in the project root for more information. dumprf: push rbp mov rbp, rsp push r12, r13 mov r12, ax0 mov r13, rsp call RFS.LoadReg, r12, $cr1 push rax call RFS.LoadReg, r12, $cr0 push rax call RFS.LoadReg, r12, $rip push rax push r12 call printf, .dmp1 call RFS.LoadReg, r12, $srp push rax call RFS.LoadReg, r12, $trp push rax push zero # fixme call RFS.LoadReg, r12, $rbp push rax call RFS.LoadReg, r12, $rsp push rax call printf, .dmp2 call RFS.LoadReg, r12, $ax5 push rax call RFS.LoadReg, r12, $ax4 push rax call RFS.LoadReg, r12, $ax3 push rax call RFS.LoadReg, r12, $ax2 push rax call RFS.LoadReg, r12, $ax1 push rax call RFS.LoadReg, r12, $ax0 push rax call printf, .dmp3 call RFS.LoadReg, r12, $rdi push rax call RFS.LoadReg, r12, $rsi push rax call RFS.LoadReg, r12, $rdx push rax call RFS.LoadReg, r12, $rcx push rax call RFS.LoadReg, r12, $rbx push rax call RFS.LoadReg, r12, $rax push rax call printf, .dmp4 call RFS.LoadReg, r12, $r17 push rax call RFS.LoadReg, r12, $r16 push rax call RFS.LoadReg, r12, $r15 push rax call RFS.LoadReg, r12, $r14 push rax call RFS.LoadReg, r12, $r13 push rax call RFS.LoadReg, r12, $r12 push rax call printf, .dmp5 call RFS.LoadReg, r12, $r20 push rax call RFS.LoadReg, r12, $r19 push rax call RFS.LoadReg, r12, $r18 push rax call printf, .dmp6 mov rsp, r13 pop r13, r12 leave ret .dmp1 = "Environ #1:\nfrm=0d%d rip=0x%x\ncr0=0x%x cr1=0x%x\n\n" .dmp2 = "Environ #2:\nrsp=0x%x rbp=0x%x ind=0d%d\ngrp=0x%x trp=0x%x srp=0x%x\n\n" .dmp3 = "Argument:\nax0=0x%x ax1=0x%x ax2=0x%x\nax3=0x%x ax4=0x%x ax5=0x%x\n\n" .dmp4 = "Volatile:\nrax=0x%x rbx=0x%x rcx=0x%x\nrdx=0x%x rsi=0x%x rdi=0x%x\n\n" .dmp5 = "Persistent:\nr12=0x%x r13=0x%x r14=0x%x\nr15=0x%x r16=0x%x r17=0x%x\n" .dmp6 = "r18=0x%x r19=0x%x r20=0x%x\n" # 51 "doskrnl.k" 2 # 1 "sys/main.k" 1 ; The OS/K Team licenses this file to you under the MIT license. ; See the LICENSE file in the project root for more information. PrintBootMsg: call print, .bootmsg ret .bootmsg = "Starting DOS...\n\n" ; ; Initialize TRAP handlers ; InitSyscalls: call RFS.ActivateFrame, 1 mov ax1, $rip mov ax2, DefaultTrapHandler call RFS.StoreReg mov ax0, 256 mov ax1, 1 call IDT.AddHandler ret InitExcepts: call RFS.ActivateFrame, 2 mov ax1, $rip mov ax2, DefaultExceptionHandler call RFS.StoreReg call IDT.AddHandler, zero, 2 SwitchToCMD: mov rax, Sys.Exit trap 0 ; ; Main function ; main: call PrintBootMsg call InitSyscalls call InitExcepts call SwitchToCMD ret # 52 "doskrnl.k" 2