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