rdos/boot/kernel.asm

236 lines
3.2 KiB
NASM

cpu 8086
org 0
jmp 0x07C0:init
%include "inc/bpb.asm"
banner: db "rdos", 0xA, 0xD, 0
; syscalls push a register set to stack
; this is for accessing it
rsdssi: equ 0x08
rsesdi: equ 0x0C
rsbp: equ 0x10
rslpad: equ 0x12
rscsip: equ 0x14
rsflag: equ 0x18
lpads: times 0x30 call entry
entry: push bp
; BX+0C: ES:DI
push es
push di
; BX+08: DS:SI
push ds
push si
; BX+00: AX,CX,DX,BX
push bx
push dx
push cx
push ax
mov ax, ss
mov es, ax
mov bx, sp
; This needs to be done when coming from userspace
mov ax, cs
mov ss, ax
xor sp, sp
int 3
; Jump back to userspace
ujump: cli
mov ax, es
mov ss, ax
mov sp, bx
; Pop whole registerset
; base registers
pop ax
pop cx
pop dx
pop bx
; string ptrs
pop si
pop ds
pop di
pop es
; BP is special
pop bp
; skip landing pad number
add sp, 2
; pop IP, CS and flags
iret
; Processes register set DS:BX as syscall
scall: ; Clear status flags
and byte [bx+rsflag], 0
ret
; No such subfunction
sferr: ; set carry
or byte [bx+rsflag], 1
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
bpb: times bpb_len db 0
drvnum: db 0
align 4
drvpos: dd 0
buffer: times 512 db 0
; Select active drive
; IN dl drive number A=0, B=1, C=2, ...
select: mov [drvnum], dl
ret
; Set sector number
seek: mov [drvpos], ax
mov [drvpos+2], dx
ret
; Read sector from disk
read: ; this uses the EBIOS extensions
; qword sector number
xor ax, ax
push ax
push ax
mov ax, [drvpos+2]
push ax
mov ax, [drvpos]
push ax
; dword target buffer
mov ax, buffer
push cs
push ax
; word number of sectors
mov ax, 1
push ax
; size & passing
mov di, 0x10
push di
mov si, sp
mov ah, 0x42
mov dl, [drvnum]
call dnconv
stc
int 0x13
add sp, di
ret
; Convert between drive number and BIOS dl
; Bidirectional mapping
; 0 <-> 0, 1 <-> 1, 2 <-> 0x80, 3 <-> 0x81
dnconv: mov cx, 7
ror dx, 1
rol dl, 1
dncl: rcl dl, 1
rcr dh, 1
loop dncl
xchg dh, dl
ret
init: cli
mov ax, cs
mov ds, ax
mov es, ax
mov ss, ax
xor sp, sp
xor dh, dh
call dnconv
call select
xor ax, ax
xor dx, dx
call seek
call read
mov ax, [buffer+0x1FE]
int 3
main: push cs
pop ds
mov si, banner
mov ah, 0x0e
xor bx, bx
loop: lodsb
test al, al
jz end
int 0x10
jmp loop
end: hlt
jmp end