rdos/boot/kernel.asm

254 lines
3.5 KiB
NASM
Raw Normal View History

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
2020-04-13 15:53:21 +02:00
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
2020-04-13 15:53:21 +02:00
dw sferr, sferr, sferr, sferr
dw sferr, sferr, sferr, sferr
dw sferr, sferr, sferr, sferr
dw sferr, sferr, sferr, sferr
; 20
2020-04-13 15:53:21 +02:00
dw sferr, sferr, sferr, sferr
dw sferr, setint, sferr, sferr
dw sferr, sferr, sferr, sferr
dw sferr, sferr, sferr, sferr
; 30
2020-04-13 15:53:21 +02:00
dw sferr, sferr, sferr, sferr
dw sferr, getint, sferr, sferr
2020-04-13 15:53:21 +02:00
dw sferr, sferr, sferr, sferr
dw sferr, sferr, sferr, sferr
; IN al number
; OUT bx al * 4
times4: push ax
2020-04-13 15:53:21 +02:00
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
2020-04-13 15:53:21 +02:00
mov ax, ds
mov [es:bx+2], ds
2020-04-13 15:53:21 +02:00
pop bx
pop es
ret
bpb: times bpb_len db 0
drvnum: db 0
align 4
2020-04-15 23:51:07 +02:00
drvoff: dd 0 ; partition offset
drvpos: dd 0 ; absolute physical sector number
buffer: times 512 db 0
; Select active drive
; IN dl drive number A=0, B=1, C=2, ...
select: mov [drvnum], dl
2020-04-15 23:51:07 +02:00
push es
xor ax, ax
push cs
pop es
stosw
stosw
stosw
stosw
pop es
call read
call ldbpb
ret
; load bpb from buffer to bpb
ldbpb: push ds
push es
mov ax, cs
mov si, buffer+0x0B
mov di, bpb
mov cx, bpb_len
rep movsb
pop es
pop ds
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
call dnconv
2020-04-15 23:51:07 +02:00
int 3
call select
2020-04-15 23:51:07 +02:00
int 3
mov ax, [cs:bpb+bpb_ss]
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