rdos/boot/kernel.asm

188 lines
2.9 KiB
NASM

cpu 8086
org 0x7C00
stack: equ 0x7C00
framsz: equ 0x300
jmp init
; Data on user stack while in kernel (5 words):
; AX BP IP CS flags
; Kernel stack:
; [frame] SP SS
; BP-^
; The start of the frame is available via BP.
; The frame is followed by a long ptr to the user stack.
; Main entry point
int20h: xor ah, ah
int21h: push bp
push ax
; Test if SS=0, if it is, we assume we are already on kernel stack
mov ax, ss
test ax, ax
jz rentry
; Save user stack
mov ax, ss
mov [cs:stack-2], ax
mov [cs:stack-4], sp
; Set up kernel stack
xor ax, ax
mov ss, ax
mov sp, (stack-4)
jmp scall
; This is like the above, except that it doesnt switch stacks.
; The 'user' stack data is after (below on stack) the kernel frame.
; [frame] SP SS AX BP IP CS flags
; \-\--^
rentry: mov ax, sp
push ss
push ax
scall: sub sp, framsz
mov bp, sp
call getax
call jmptab
; Restore user stack
mov sp, [bp+framsz]
mov ax, [bp+framsz+2]
mov ss, ax
pop ax
pop bp
iret
; Lookup address of subfunction
; Mesh up the stack so we return to subfunction
; and subfunction later returns to scall
jmptab: push ax
push bx
xor bx, bx
add bl, ah
add bl, ah
mov bx, [cs:bx+sftab]
mov [bp-4], bx
pop bx
ret
; Get AX from the user stack
getax: push ds
push si
lds si, [bp+framsz]
lodsw
pop ds
pop si
ret
; No such subfunction - set carry and exit
sferr: stc
ret
; Subfunction table
sftab: dw sferr, sferr, sferr, sferr
dw sferr, sferr, sferr, sferr
dw sferr, sferr, sferr, sferr
dw sferr, sferr, sferr, sferr
; 10
dw sferr, sferr, sferr, sferr
dw sferr, sferr, sferr, sferr
dw sferr, sferr, sferr, sferr
dw sferr, sferr, sferr, sferr
; 20
dw sferr, sferr, sferr, sferr
dw sferr, setint, sferr, sferr
dw sferr, sferr, sferr, sferr
dw sferr, sferr, sferr, sferr
; 30
dw sferr, sferr, sferr, sferr
dw sferr, getint, sferr, sferr
dw sferr, sferr, sferr, sferr
dw sferr, sferr, sferr, sferr
; IN al number
; OUT bx al * 4
times4: push ax
xor ah, ah
add al, al
add al, al
mov bx, ax
pop ax
ret
; DOS 2+ - GET INTERRUPT VECTOR
; IN al interrupt number
; OUT es:bx current interrupt handler
getint: push ds
; DS=0
xor bx, bx
mov ds, bx
; BX=AL*4
call times4
les bx, [bx]
pop ds
ret
; DOS 25h: Set interrupt vector
; IN al interrupt number
; ds:dx entry point
setint: push es
push bx
; ES=0
xor bx, bx
mov es, bx
; BX=AL*4
call times4
mov [es:bx], dx
mov ax, ds
mov [es:bx+2], ds
pop bx
pop es
ret
; ===== end of resident, begin of transient startup code
init: xor ax, ax
mov ds, ax
mov es, ax
mov ax, 0x1000
mov ss, ax
xor sp, sp
mov al, 0x21
mov dx, int21h
call setint
mov ax, 0x2520
mov dx, int20h
int 0x21
mov ax, 0x3520
int 0x21
mov ah, 0x3f
int 3
int 0x21
int 3
main: push cs
pop ds
mov si, msg
mov ah, 0x0e
xor bx, bx
loop: lodsb
test al, al
jz end
int 0x10
jmp loop
end: hlt
jmp end
msg: db "rdos kernel stub", 0x0A, 0x0D, 0