rdos/boot/kernel.asm

277 lines
4.4 KiB
NASM

cpu 8086
org 0x500
%include "inc/bpb.asm"
%include "inc/dpt.asm"
; drive table entry
struc drive
.biosnum: resb 1
.flag: resb 1
.spc: resw 1
.cylinders: resw 1
.dpt: resb dpt_size
.type: resb 1 ; 12 or 16, depending on FAT type
.fat_offset: resd 1 ; offset of fat table
.fat_num: resw 1 ; number of fat tables
.fat_size: resw 1 ; sectors per fat table
.dir_offset: resd 1 ; offset of root directory
.dir_size: resw 1 ; size of root directory in sectors
.clus_offset: resd 1 ; offset of clusters
.clus_num: resw 1 ; number of clusters
.clus_size: resw 1 ; sectors per cluster
endstruc
; kernel stack size in words
%define stacksize 512
init: cli
xor ax, ax
mov ds, ax
mov es, ax
mov ss, ax
mov sp, ( stack+stacksize )
; relocate
mov si, 0x7C00
mov di, $$
mov cx, (_end-$$)
rep movsb
jmp 0:main
main: ; zero out first 64kb except our code
; bss and boot sector area gets cleared by this
mov cx, di
neg cx
xor ax, ax
rep stosb
; install interrupt vectors
mov si, vects
mov di, (0x20*4)
mov cx, 0x0A
intlp: movsw
mov ax, cs
stosw
loop intlp
mov dx, banner
call puts
call drives_init
mov dl, 0
call drive_select
xor ax, ax
xor dx, dx
call drive_seek
call drive_read
mov ax, [diskbuf+0x1FE]
int 3
loop: int 0x28
jmp loop
section .data
banner: db "rdos loaded", 0xA, 0xD, '$'
section .text
; Alias for Int 21h,AH=0h
int20h: xor ah, ah
jmp far [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
iretfl: push ax
push bp
mov bp, sp
lahf
mov [bp+8], ah
pop bp
pop ax
; iret frame: IP CS FLAGS
iret: iret
retf: retf
section .data
; Subfunction ptr
; this is used as extra register in int21h
sfptr: dw 0
; Subfunction table
sftab: dw sferr, getc, putc, sferr
dw sferr, sferr, conout, conin
dw sferr, puts, 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
section .text
; OUT al character read
getc: xor ax, ax
int 0x16
push ax
jmp putc.2
; IN dl character to write
putc: push ax
mov al, dl
.2: int 0x29
pop ax
ret
; console output
; IN dl character
conout: cmp dl, 0xFF
je conine
push ax
mov al, dl
int 0x29
pop ax
ret
; console input with echo
; OUT al character
; zf clear when character available
conine: mov ah, 1
int 0x16
jnz .has
xor al, al
ret
.has: xor ax, ax
int 0x16
test al, al
jz conine
int 0x29
test ax, ax
ret
; console input without echo
; OUT al character
; zf clear when character available
conin: mov ah, 1
int 0x16
jnz .has
xor al, al
ret
.has: xor ax, ax
int 0x16
test al, al
jz conin
test ax, ax
ret
; DOS 1+ 9h - WRITE STRING TO STANDARD OUTPUT
; IN ds:dx '$'-terminated string
puts: push si
mov si, dx
.loop: lodsb
cmp al, '$'
je .end
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
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
; DOS IDLE INTERRUPT
; Usually hooked by TSRs
idle: sti
; sti takes one instruction to take effect
nop
; Wait until next interrupt
hlt
iret
; 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
%include "kernel/drive.asm"
%include "kernel/fat.asm"
zero: dw 0
section .data
vects: dw int20h, int21h, retf, retf
dw retf, retf, retf, int20h
dw idle, fputc
_end: dw 0x55AA, 0x55AA
section .bss
; stack to be used during init and disk i/o
stack: resw stacksize