# 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 ecx, ax1 scasb ax0, zero sub eax, ax1, ecx ret ; ; int strlen(char *) ; strlen: mov ecx, 0x7AFFFFFF mov edx, ecx scasb ax0, zero sub eax, edx, ecx ret ; ; void strcpy(char *, const char *) ; strcpy: .l: mov ecx, b[ax1] mov b[ax0], ecx jecxz .r inc ax0 inc ax1 jmp .l .r: ret ; ; void strncpy(char *, const char *, int) ; strncpy: mov ecx, ax2 jecxz .r .l: mov b[ax0], b[ax1] inc ax0 inc ax1 loop .l .r: ret ; ; void strnzcpy(char *, const char *, int) ; strnzcpy: mov ecx, ax2 jecxz .r .l: mov eax, b[ax1] mov b[ax0], eax jeaxz .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 esi .l: movzx eax, b[ax0+esi] movzx edx, b[ax1+esi] bne eax, edx, .r ; both zero? add ecx, eax, edx jecxz .r inc esi jmp .l .r: sub eax, edx ret ; ; int strncmp(const char *str1, const char *str2, int maxn) ; strncmp: mov ecx, ax2 jecxz .r .l: movzx eax, b[ax0] movzx edx, b[ax1] bne eax, edx, .r inc ax0 inc ax1 loop .l .r: sub eax, edx ret ; ; char *strchrnul(const char *str, int ch) ; strchrnul: mov ecx, 0x7AFFFFFF scasb ax0, ax1 mov eax, ax0 ret ; ; char *strchr(const char *str, int ch) ; strchr: mov ecx, 0x7AFFFFFF scasb ax0, ax1 bnz b[ax0], .r nul eax ret .r: mov eax, 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 esi, ax1 ; go to str's end, just before ; the null terminator mov ecx, 0x7AFFFFFF scasb ax1, zero dec ax1 .l: ; copy, going backward though str ; and forward through buf mov b[ax0], b[ax1] beq ax1, esi, .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 ecx, 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 ecx, ax2 jecxz .r .l: sub edx, ax2, ecx mov b[ax0+edx], b[ax1+edx] loop .l .r: ret ; ; void memzero(void *, int) ; memzero: mov ecx, ax1 jecxz .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 eax, 365 ; divisible by 4? rem ecx, ax0, 4 jecxnz .end ; divisible by 100? rem ecx, ax0, 100 jecxnz .leap ; divisible by 400? rem ecx, ax0, 400 jecxnz .end .leap: inc eax .end: ret ; ; TIME *GetTimeUTC(void) ; GetTimeUTC: ytime mov edi, .buf ; seconds rem esi, eax, 60 mov b[edi], esi ; minutes div esi, eax, 60 rem esi, 60 mov b[edi+1], esi ; hours div esi, eax, 3600 rem esi, 24 mov b[edi+2], esi ; month days div esi, eax, 3600*24 mov b[edi+3], esi ; month mov b[edi+4], rbx ; years mov w[edi+6], ecx ; ; ydays (TODO) ; mov eax, .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 eax, ax0 nul ecx ; 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 ecx, ax1, 63 ; extract ax1 sign jecxz .conv neg ax1 ; NEG if negative ; main loop .conv: bzr ax1, .fini rem edx, ax1, ax2 ; ax1 % base blt 9, edx, .nondec ; edx > 9 ? add edx, '0' jmp .next .nondec: add edx, 55 ; 'A' - 10 .next: mov b[ax0], edx inc ax0 div ax1, ax2 jmp .conv ; add minus flag, null-terminate and reverse .fini: jecxz .cxz mov b[ax0], '-' inc ax0 .cxz: nul b[ax0] call strrev2, eax 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) ; ; eax = integer extracted from str ; edx = pointer to first invalid byte ; strtol: mov ax2, 1 jmp strtoq ; ; int strtoul(const char *str, int base) ; ; eax = integer extracted from str ; edx = 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 eax, esi mov edx, ax0 ; make sure base is in [2, 32] beq ax1, 1, .bad bltu 36, ax1, .bad ; empty string? bzr b[edx], .done .skip_spc: bne b[edx], ' ', .no_spc inc edx jmp .skip_spc .no_spc: ; skip + bne b[edx], '+', .no_plus inc edx .no_plus: ; unsigned? bzr ax2, .unsigned ; parse '-' bne b[edx], '-', .unsigned inc edx mov esi, 1 .unsigned: ; base 0 bzr ax1, .base_0 ; base prefix? bne b[edx], '0', .main_loop inc edx movzx ecx, b[edx] ; "0x"/"0b" prefix jecxz .done ; "0" beq ecx, 'x', .parsed_0x beq ecx, '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 eax = 0 and *edx = 'x' bne ax1, 16, .done ; else inc edx jmp .main_loop .parsed_0b: ; are we in base 2? ; if not, leave eax = 0 and *edx = 'b' bne ax1, 2, .done ; else inc edx jmp .main_loop .base_0: ; guess base beq b[edx], '0', .b0_not10 ; must be base 10 mov ax1, 10 jmp .main_loop .b0_not10: inc edx bne b[edx], 'x', .b0_not16 inc edx mov ax1, 16 jmp .main_loop .b0_not16: bne b[edx], 'b', .b0_not2 inc edx mov ax1, 2 jmp .main_loop .b0_not2: ; take octal by default mov ax1, 8 .main_loop: movzx ecx, b[edx] inc edx ; between 0 and 9? bltu ecx, '0', .done bltu '9', ecx, .not_digit10 ; yes sub ecx, '0' jmp .next .not_digit10: bltu ecx, 'A', .done bltu 'Z', ecx, .not_digitAZ sub ecx, 55 ; 'A' - 10 jmp .next .not_digitAZ: bltu ecx, 'a', .done bltu 'z', ecx, .done sub ecx, 87 ; 'a' - 10 jmp .next .next: ; too large for base? blteu ax1, ecx, .done mul eax, ax1 add eax, ecx jmp .main_loop .done: ; negative? bzr esi, .r ; yes neg eax .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 ebp mov ebp, esp push nx0, nx1, nx2 push nx3, nx4, nx5 mov nx0, ax2 ; fmt mov nx2, ax3 ; va_list mov nx3, ax1 ; n mov nx5, ax0 ; putc nul nx4 ; return value .main_loop: ; find '%' or null-terminator mov ecx, 0x7AFFFFFF mov nx1, nx0 scasb nx1, '%' ; everything below nx1 is a regular character; print it .print_regular: beq nx0, nx1, .check_modf call .doput, b[nx0] inc nx0 jmp .print_regular .check_modf: ; did we find a '%' ? ; if not, then we found fmt's null-terminator; we're done bne b[nx0], '%', .epilogue ; we did find a modifier / '%' mov eax, b[nx0+1] add nx0, 2 beq eax, 's', .modf_s beq eax, 'c', .modf_c beq eax, 'p', .modf_p beq eax, 'x', .modf_x beq eax, 'd', .modf_d beq eax, 'o', .modf_o beq eax, 'b', .modf_b beq eax, '%', .modf_percent ; unrecognized jmp .bad_modifier .modf_s: ; get string address mov nx1, q[nx2] add nx2, 8 bzr nx1, .nullstring .print_string: movzx ax0, b[nx1] bzr ax0, .main_loop inc nx1 call .doput jmp .print_string .modf_c: call .doput, q[nx2] add nx2, 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 esp, 80 mov nx1, esp ; assume modifier already set up ax2 call itoa, esp, q[nx2] add nx2, 8 .print_itoa_buf: movzx ax0, b[nx1] bzr ax0, .pib_end_loop inc nx1 call .doput jmp .print_itoa_buf .pib_end_loop: add esp, 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 eax, nx4 pop nx5, nx4 pop nx3, nx2 pop nx1, nx0 leave ret ; ; prints ax0 ; .doput: ; update print count inc nx4 ; 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 nx3, .r ; decrement n and print dec nx3 call nx5 ; did putc fail? jeaxz .r ; yes, so artificially set n=0 nul nx3 .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 eax ret ; ; int printf(const char *fmt, ...) ; printf: mov ax2, ax0 mov ax0, putc mov ax1, 0x7AFFFFFF add ax3, esp, 8 jmp doprnt ; ; int nprintf(const char *fmt, int n, ...) ; nprintf: mov ax2, ax0 mov ax0, putc add ax3, esp, 8 jmp doprnt ; ; Print a string ; Guaranteed to only affect ecx and ax0 ; print: .l: movzx eax, b[ax0] jeaxz .r prn eax inc ax0 jmp .l .r: ret ; ; Print exactly ax1 characters ; nprint: mov ecx, ax1 jecxz .r .l: prn b[ax0] inc ax0 loop .l .r: ret # 51 "crt/crt.k" 2 exit: mov eax, 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 esp, 0x104000 mov ebp, 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 esp, 0x105800 mov ax1, nx0 bzr nx0, DefaultTrapHandler.handle_Shutdown bltu 11, nx0, .unknown mov esi, .err_ukn lea ax0, b[esi + nx0 * 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 nx0 mov nx0, ax0 prn 10 prn 0x8BF00001 prn 0x8BF00002 push ax1 call printf, .scr1 pop bnz nx2, .not_con push .scr2_con jmp .do_print .not_con: ; rframes #2-#3-#4 belong to kernel blt 4, nx2, .not_krn push .scr2_krn jmp .do_print .not_krn: push .scr2_usr .do_print: push nx2, nx0 call printf, .scr2 add esp, 24 call dumprf, nx2 prn 10 call print, .scr3 .loop: pause pause scan eax jeaxz .loop beq eax, 0x0A, DefaultTrapHandler.handle_Exit beq eax, 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 ebp ; eax = caller's cr1 call RFS.LoadReg, nx2, $cr1 ; we don't preserve the nx0 we got mov nx0, eax nul edx jmp ecx TrapHandlers.epilog: ; TRAP return values: eax-edx mov ax2, eax call RFS.StoreReg, nx2, $eax mov ax2, edx call RFS.StoreReg, nx2, $edx call IDT.DoneHandling, nx1 iret ; ; TRAP #0 handler ; DefaultTrapHandler: .init: mov ecx, .text mov esp, 0x104800 jmp TrapHandlers.prolog .text: call RFS.LoadReg, nx2, $eax call RFS.LoadArgs, nx2 ; will be optimized with a table ; when we have a "finished" consistent API jeaxz .handle_Shutdown beq eax, Sys.Exit, .handle_Exit beq eax, Sys.ExecuteInFrame, .handle_EIF beq eax, Sys.ReadFile, .handle_ReadFile beq eax, Sys.OpenFile, .handle_OpenFile beq eax, Sys.CloseFile, .handle_CloseFile beq eax, Sys.CreateFile, .handle_CreateFile beq eax, Sys.RemoveFile, .handle_RemoveFile beq eax, Sys.FindNext, .handle_FindNext beq eax, Sys.FindFirst, .handle_FindFirst beq eax, Sys.EnterHaltMode, .handle_HaltMode .sod: call ScreenOfDeath, .badsyscall, nx1 .wrong: call ScreenOfDeath, .badparams, nx1 .fini.savecx: mov ax2, ecx call RFS.StoreReg, nx2, $ecx .fini: jmp TrapHandlers.epilog .badsyscall = "Invalid syscall number in eax" .badparams = "Invalid syscall parameters" ;------------------------------------------------; ; Syscall implementations ; ;------------------------------------------------; ; ; Pass control to COMMAND.COM in frame 0 ; .handle_Exit: ; deactivate current rframe bzr nx2, .hE_nz ; unless it's 0... call RFS.DeactivateFrame, nx2 .hE_nz: ; open COMMAND.COM call DISK.OpenFile, .cmdcom ; crash on failure bltz eax, abort ; load at 0x108000 mov ax1, 0x108000 mov ax2, 0x80000 call DISK.ReadFile, eax ; assume that COMMAND.COM being ; less then 4KB means something ; went wrong blt eax, 0x1000, abort ; close the handle call DISK.CloseFile, eax ; code address mov ax2, 0x100000 call RFS.StoreReg, zero, $eip ; usermode mov ax2, 3 call RFS.StoreReg, zero, $cr0 mov ecx, 0x108000 sub ecx, 0x100000 ; code offset mov ax2, ecx call RFS.StoreReg, zero, $cr1 ; return frame nul nx2 jmp .fini .cmdcom = "command.com" .handle_EIF: blt ax1, 5, .wrong ; eip can't be <1MB mov ecx, 0x100000 blt ax0, ecx, .wrong ; add old CR1 add ax0, nx0 ; real eip can't be <1MB+32KB either ; (kernel + cmdcom personal space) add edx, ecx, 0x8000 blt ax0, ecx, .wrong ; save rframe and compute new CR1 mov ebx, ax1 sub edi, ax0, ecx ; activate rframe call RFS.ActivateFrame, ebx ; save new CR1 mov ax2, edi call RFS.StoreReg, ebx, $cr1 ; interruptible user mode mov ax2, 3 call RFS.StoreReg, ebx, $cr0 ; set eip = 1MB mov ax2, ecx call RFS.StoreReg, ebx, $eip ; change return frame mov nx2, ebx jmp .fini ; ; Disk API ; .handle_FindFirst: add ax0, nx0 call DISK.FindFirst jmp .fini.savecx .handle_FindNext: add ax0, nx0 call DISK.FindNext jmp .fini.savecx .handle_OpenFile: add ax0, nx0 call DISK.OpenFile jmp .fini .handle_CreateFile: add ax0, nx0 call DISK.CreateFile jmp .fini .handle_RemoveFile: add ax0, nx0 call DISK.RemoveFile jmp .fini .handle_CloseFile: call DISK.CloseFile jmp .fini .handle_ReadFile: add ax1, nx0 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 ebp mov ebp, esp push nx0, nx1 mov nx0, ax0 mov nx1, esp call RFS.LoadReg, nx0, $cr1 push eax call RFS.LoadReg, nx0, $cr0 push eax call RFS.LoadReg, nx0, $eip push eax push nx0 call printf, .dmp1 call RFS.LoadReg, nx0, $srp push eax call RFS.LoadReg, nx0, $trp push eax push zero # fixme call RFS.LoadReg, nx0, $ebp push eax call RFS.LoadReg, nx0, $esp push eax call printf, .dmp2 call RFS.LoadReg, nx0, $ax5 push eax call RFS.LoadReg, nx0, $ax4 push eax call RFS.LoadReg, nx0, $ax3 push eax call RFS.LoadReg, nx0, $ax2 push eax call RFS.LoadReg, nx0, $ax1 push eax call RFS.LoadReg, nx0, $ax0 push eax call printf, .dmp3 call RFS.LoadReg, nx0, $edi push eax call RFS.LoadReg, nx0, $esi push eax call RFS.LoadReg, nx0, $edx push eax call RFS.LoadReg, nx0, $ecx push eax call RFS.LoadReg, nx0, $ebx push eax call RFS.LoadReg, nx0, $eax push eax call printf, .dmp4 call RFS.LoadReg, nx0, $nx5 push eax call RFS.LoadReg, nx0, $nx4 push eax call RFS.LoadReg, nx0, $nx3 push eax call RFS.LoadReg, nx0, $nx2 push eax call RFS.LoadReg, nx0, $nx1 push eax call RFS.LoadReg, nx0, $nx0 push eax call printf, .dmp5 call RFS.LoadReg, nx0, $nx8 push eax call RFS.LoadReg, nx0, $nx7 push eax call RFS.LoadReg, nx0, $nx6 push eax call printf, .dmp6 mov esp, nx1 pop nx1, nx0 leave ret .dmp1 = "Environ #1:\nfrm=0d%d eip=0x%x\ncr0=0x%x cr1=0x%x\n\n" .dmp2 = "Environ #2:\nesp=0x%x ebp=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:\neax=0x%x ebx=0x%x ecx=0x%x\nrdx=0x%x esi=0x%x edi=0x%x\n\n" .dmp5 = "Persistent:\nnx0=0x%x nx1=0x%x nx2=0x%x\nr15=0x%x nx4=0x%x nx5=0x%x\n" .dmp6 = "nx6=0x%x nx7=0x%x nx8=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, $eip mov ax2, DefaultTrapHandler call RFS.StoreReg mov ax0, 256 mov ax1, 1 call IDT.AddHandler ret InitExcepts: call RFS.ActivateFrame, 2 mov ax1, $eip mov ax2, DefaultExceptionHandler call RFS.StoreReg call IDT.AddHandler, zero, 2 SwitchToCMD: mov eax, Sys.Exit trap 0 ; ; Main function ; main: call PrintBootMsg call InitSyscalls call InitExcepts call SwitchToCMD ret # 52 "doskrnl.k" 2