rdos/boot/kernel.asm

265 lines
4.1 KiB
NASM
Raw Normal View History

cpu 8086
2020-04-18 22:59:46 +02:00
org 0x500
jmp 0:(init+0x7C00-$$)
%include "inc/bpb.asm"
banner: db "rdos", 0xA, 0xD, '$'
2020-04-20 19:13:06 +02:00
; Alias for Int 21h,AH=0h
int20h: xor ah, ah
2020-04-20 19:13:06 +02:00
; allow extenders to get away with only hooking 21h
jmp [cs:(0x21 * 4)]
int21h: ; inside of kernel, direction always goes up
; the iret will restore it to the user value later
cld
; set sfptr from ah
push bx
xor bx, bx
mov bl, ah
add bl, bl
add bx, sftab
mov bx, [cs:bx]
mov [cs:sfptr], bx
pop bx
; do the actual subfunction call
call [cs:sfptr]
; inherit the lower 8 flag bits to userspace
push ax
push bp
mov bp, sp
lahf
mov [bp+8], ah
pop bp
pop ax
; iret frame: IP CS FLAGS
2020-04-20 19:13:06 +02:00
iret: iret
; Subfunction ptr
; this is used as extra register in int21h
sfptr: dw 0
2020-04-13 15:53:21 +02:00
; Subfunction table
sftab: dw sferr, sferr, putc, sferr
2020-04-13 15:53:21 +02:00
dw sferr, sferr, sferr, sferr
dw sferr, puts, sferr, sferr
2020-04-13 15:53:21 +02:00
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
; DOS 1+ 2h - WRITE CHARACTER TO STANDARD OUTPUT
; IN dl character to write
putc: push ax
push bx
mov ah, 0x0E
mov al, dl
xor bx, bx
int 0x10
pop bx
pop ax
ret
; DOS 1+ 9h - WRITE STRING TO STANDARD OUTPUT
; IN ds:dx '$'-terminated string
puts: push si
.loop: lodsb
cmp al, '$'
je .end
2020-04-20 19:13:06 +02:00
int 0x29
jmp .loop
.end: pop si
ret
; DOS 1+ 25h - SET INTERRUPT VECTOR
; IN al interrupt number
; ds:dx entry point
setint: push bx
xor bx, bx
; BX=AL*4
mov bl, al
add bl, bl
add bl, bl
; save DS:DX into vector
mov [cs:bx], dx
mov [cs:bx+2], ds
2020-04-13 15:53:21 +02:00
pop bx
ret
; DOS 2+ 35h - GET INTERRUPT VECTOR
; IN al interrupt number
; OUT es:bx current interrupt handler
getint: xor bx, bx
; BX=AL*4
mov bl, al
add bl, bl
add bl, bl
; load vector into ES:BX
les bx, [cs:bx]
ret
; Fallback for non-existant subfunctions
; The carry flag is inherited to user
sferr: stc
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
; 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
; 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, [cs:drvpos+2]
push ax
mov ax, [cs: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, [cs:drvnum]
call dnconv
stc
int 0x13
add sp, di
ret
; Select active drive
; IN dl drive number A=0, B=1, C=2, ...
select: mov [cs:drvnum], dl
ret
push es
xor ax, ax
push cs
pop es
mov si, drvoff
stosw
stosw
stosw
stosw
pop es
call read
; load bpb from buffer to bpb
ldbpb: push ds
push es
mov ax, cs
mov ds, ax
mov es, ax
mov si, buffer+0x0B
mov di, bpb
mov cx, bpb_len
rep movsb
pop es
pop ds
ret
2020-04-20 19:19:14 +02:00
; DOS 2+ - DOS IDLE INTERRUPT
; Usually hooked by TSRs
idle: sti
; sti takes one instruction to take effect
nop
; Wait until next interrupt
hlt
iret
2020-04-20 19:13:06 +02:00
; DOS 2+ - FAST CONSOLE OUTPUT
; IN al character to print
fputc: push ax
push bx
mov ah, 0x0E
xor bx, bx
int 0x10
pop bx
pop ax
iret
2020-04-20 19:19:14 +02:00
main: int 0x28
2020-04-20 19:13:06 +02:00
jmp main
2020-04-18 22:59:46 +02:00
init: cli
xor ax, ax
mov ds, ax
mov es, ax
mov ss, ax
xor sp, sp
mov si, 0x7C00
mov di, $$
mov cx, (init-$$)
rep movsb
2020-04-20 19:13:06 +02:00
; Set boot drive as current drive
2020-04-18 22:59:46 +02:00
call dnconv
call select
2020-04-20 19:13:06 +02:00
; Set int 0x20 to 0x2F
mov di, (0x20*4)
mov si, ivects+0x7C00-$$
2020-04-20 19:13:06 +02:00
mov cx, 0x10
.loop: movsw
mov ax, cs
stosw
2020-04-20 19:13:06 +02:00
loop .loop
mov si, banner
mov ah, 0x09
int 0x21
2020-04-18 22:59:46 +02:00
jmp 0:main
2020-04-20 19:13:06 +02:00
ivects: dw int20h, int21h, iret, iret
dw iret, iret, iret, iret
2020-04-20 19:19:14 +02:00
dw idle, fputc, iret, iret
2020-04-20 19:13:06 +02:00
dw iret, iret, iret, iret