cpu 8086 org 0x500 jmp 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 ; 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 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 main: mov si, banner mov ah, 0x0e xor bx, bx loop: lodsb test al, al jz end int 0x10 jmp loop end: hlt jmp end 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 call dnconv call select jmp 0:main