rdos/kernel/syscall.asm

103 lines
2.0 KiB
NASM

; 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