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 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 drvpos: dd 0 buffer: times 512 db 0 ; Select active drive ; IN dl drive number A=0, B=1, C=2, ... select: mov [drvnum], 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, [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 xor dh, dh call dnconv call select xor ax, ax xor dx, dx call seek call read mov ax, [buffer+0x1FE] 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