; This is the syscall gateway: ; - backs up the data from user space (kernel funcs trash many regs) ; - sets up the kernel stack ; - calls kernel funcs ; - exports a specified set of registers back to userspace ; ; The syscall table acts as a "export"-list for kernel near funcs. ; Kernel code can expect CS = DS section .rodata stab: ; syscall table ; cells: ptr to handler, ptr to sysret ; 0-7 dw restart, sret dw getc, sretb dw putc, sret dw err, sret ; reader input dw err, sret ; punch outout dw err, sret ; list output dw conio, sret ; direct console i/o dw err, sret ; 8-f dw err, sret dw err, sret ; print string dw err, sret ; read into buffer dw err, sret ; console status dw err, sret ; return version num dw err, sret ; reset disks dw setdd, sret ; select disk dw open, sretb ; open file .end: section .text ; WARNING: BP, SI and DI are not saved ; If kernel code uses them, they need to be saved to the stack int21: push ds ; load program PSP and save userdata mov ds, [cs:curpsp] pop word [PSPDS] mov [PSPES], es mov [PSPAX], ax mov [PSPCX], cx mov [PSPDX], dx mov [PSPBX], bx mov [PSPSS], ss mov [PSPSP], sp xor bx, bx mov ss, bx mov sp, stack ; get ptr into syscall table mov bl, [PSPAX+1] ; bh is still 0 shl bx, 1 shl bx, 1 add bx, stab ; load sysret and handler ptr push word [cs:bx+2] push word [cs:bx] ; DS is always our segment push cs pop ds ; ES:BX is syscall argument mov bx, [PSPDX] mov es, [PSPDS] ret err: mov ah, 0xFF ret ; sysret handlers ; return ES:BX to user sretd: mov ds, [cs:curpsp] jmp sret.l02 ; return BX to user sretw: mov ds, [cs:curpsp] mov es, [PSPES] jmp sret.l02 ; return carry flag in AL sretc: mov ds, [cs:curpsp] sbb al, al ; return AL to user sretb: mov ds, [cs:curpsp] mov ah, [PSPAX+1] les bx, [PSPBX] jmp sret.l03 ; return without result sret: mov ds, [cs:curpsp] les bx, [PSPBX] .l02: mov ax, [PSPAX] .l03: mov ss, [PSPSS] mov sp, [PSPSP] mov cx, [PSPCX] lds dx, [PSPDX] ; DS last iret