2020-04-10 17:00:26 +02:00
|
|
|
cpu 8086
|
2020-04-18 22:59:46 +02:00
|
|
|
org 0x500
|
2020-04-19 15:14:10 +02:00
|
|
|
jmp 0:(init+0x7C00-$$)
|
2020-04-15 00:17:58 +02:00
|
|
|
|
|
|
|
%include "inc/bpb.asm"
|
|
|
|
|
2020-04-26 23:14:34 +02:00
|
|
|
; Far call via interrupt vector
|
|
|
|
%macro intcall 1
|
|
|
|
call far [cs:%1*4]
|
|
|
|
%endmacro
|
|
|
|
|
|
|
|
; Far jump via interrupt vector
|
|
|
|
%macro intjump 1
|
|
|
|
jump far [cs:%1*4]
|
|
|
|
%endmacro
|
|
|
|
|
|
|
|
; stack size
|
|
|
|
%define stacks 512
|
|
|
|
|
2020-04-19 00:35:31 +02:00
|
|
|
banner: db "rdos", 0xA, 0xD, '$'
|
2020-04-15 00:17:58 +02:00
|
|
|
|
2020-04-20 19:13:06 +02:00
|
|
|
; Alias for Int 21h,AH=0h
|
2020-04-19 00:35:31 +02:00
|
|
|
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)]
|
|
|
|
|
2020-04-19 00:35:31 +02:00
|
|
|
int21h: ; inside of kernel, direction always goes up
|
|
|
|
; the iret will restore it to the user value later
|
|
|
|
cld
|
|
|
|
; set sfptr from ah
|
2020-04-15 00:17:58 +02:00
|
|
|
push bx
|
2020-04-19 00:35:31 +02:00
|
|
|
xor bx, bx
|
|
|
|
mov bl, ah
|
|
|
|
add bl, bl
|
|
|
|
add bx, sftab
|
|
|
|
mov bx, [cs:bx]
|
|
|
|
mov [cs:sfptr], bx
|
2020-04-15 00:17:58 +02:00
|
|
|
pop bx
|
2020-04-19 00:35:31 +02:00
|
|
|
; do the actual subfunction call
|
|
|
|
call [cs:sfptr]
|
|
|
|
; inherit the lower 8 flag bits to userspace
|
2020-04-26 23:14:34 +02:00
|
|
|
iretfl: push ax
|
2020-04-19 00:35:31 +02:00
|
|
|
push bp
|
|
|
|
mov bp, sp
|
|
|
|
lahf
|
|
|
|
mov [bp+8], ah
|
2020-04-10 17:00:26 +02:00
|
|
|
pop bp
|
2020-04-19 00:35:31 +02:00
|
|
|
pop ax
|
|
|
|
; iret frame: IP CS FLAGS
|
2020-04-20 19:13:06 +02:00
|
|
|
iret: iret
|
2020-04-10 17:00:26 +02:00
|
|
|
|
2020-04-19 00:35:31 +02:00
|
|
|
; Subfunction ptr
|
|
|
|
; this is used as extra register in int21h
|
|
|
|
sfptr: dw 0
|
2020-04-13 15:53:21 +02:00
|
|
|
|
|
|
|
; Subfunction table
|
2020-04-23 21:35:28 +02:00
|
|
|
sftab: dw sferr, getc, putc, sferr
|
|
|
|
dw sferr, sferr, conout, conin
|
2020-04-19 00:35:31 +02:00
|
|
|
dw sferr, puts, sferr, sferr
|
2020-04-13 15:53:21 +02:00
|
|
|
dw sferr, sferr, sferr, sferr
|
2020-04-13 18:03:54 +02:00
|
|
|
; 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
|
2020-04-13 18:03:54 +02:00
|
|
|
; 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
|
2020-04-13 18:03:54 +02:00
|
|
|
; 30
|
2020-04-13 15:53:21 +02:00
|
|
|
dw sferr, sferr, sferr, sferr
|
2020-04-13 18:03:54 +02:00
|
|
|
dw sferr, getint, sferr, sferr
|
2020-04-13 15:53:21 +02:00
|
|
|
dw sferr, sferr, sferr, sferr
|
|
|
|
dw sferr, sferr, sferr, sferr
|
|
|
|
|
2020-04-23 21:35:28 +02:00
|
|
|
; OUT al character read
|
|
|
|
getc: xor ax, ax
|
|
|
|
int 0x16
|
|
|
|
push ax
|
|
|
|
jmp putc.2
|
|
|
|
|
2020-04-19 00:35:31 +02:00
|
|
|
; IN dl character to write
|
|
|
|
putc: push ax
|
|
|
|
mov al, dl
|
2020-04-23 21:35:28 +02:00
|
|
|
.2: int 0x29
|
2020-04-19 00:35:31 +02:00
|
|
|
pop ax
|
2020-04-13 18:03:54 +02:00
|
|
|
ret
|
|
|
|
|
2020-04-23 21:35:28 +02:00
|
|
|
; 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
|
2020-04-25 21:54:15 +02:00
|
|
|
test al, al
|
|
|
|
jz conine
|
2020-04-23 21:35:28 +02:00
|
|
|
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
|
2020-04-25 21:54:15 +02:00
|
|
|
test al, al
|
|
|
|
jz conin
|
2020-04-23 21:35:28 +02:00
|
|
|
test ax, ax
|
|
|
|
ret
|
|
|
|
|
2020-04-19 00:35:31 +02:00
|
|
|
; 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
|
2020-04-19 00:35:31 +02:00
|
|
|
jmp .loop
|
|
|
|
.end: pop si
|
|
|
|
ret
|
|
|
|
|
|
|
|
; DOS 1+ 25h - SET INTERRUPT VECTOR
|
2020-04-13 18:03:54 +02:00
|
|
|
; IN al interrupt number
|
|
|
|
; ds:dx entry point
|
2020-04-18 23:44:16 +02:00
|
|
|
setint: push bx
|
2020-04-13 18:03:54 +02:00
|
|
|
xor bx, bx
|
|
|
|
; BX=AL*4
|
2020-04-18 23:44:16 +02:00
|
|
|
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
|
2020-04-10 17:00:26 +02:00
|
|
|
ret
|
|
|
|
|
2020-04-19 00:35:31 +02:00
|
|
|
; 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
|
|
|
|
|
2020-04-16 23:04:06 +02:00
|
|
|
; 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
|
2020-04-15 00:17:58 +02:00
|
|
|
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
|
2020-04-16 23:04:06 +02:00
|
|
|
mov ax, [cs:drvpos+2]
|
2020-04-15 00:17:58 +02:00
|
|
|
push ax
|
2020-04-16 23:04:06 +02:00
|
|
|
mov ax, [cs:drvpos]
|
2020-04-15 00:17:58 +02:00
|
|
|
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
|
2020-04-16 23:04:06 +02:00
|
|
|
mov dl, [cs:drvnum]
|
2020-04-15 00:17:58 +02:00
|
|
|
call dnconv
|
|
|
|
stc
|
|
|
|
int 0x13
|
|
|
|
|
|
|
|
add sp, di
|
|
|
|
ret
|
|
|
|
|
2020-04-16 23:04:06 +02:00
|
|
|
; 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
|
2020-04-15 00:17:58 +02:00
|
|
|
ret
|
2020-04-10 17:00:26 +02:00
|
|
|
|
2020-04-26 23:14:34 +02:00
|
|
|
|
|
|
|
; defines for CHS table
|
|
|
|
chs_spt: equ 0 ; word sectors per track
|
|
|
|
chs_nos: equ 2 ; word number of sides
|
|
|
|
chs_po: equ 4 ; dword partition offset
|
|
|
|
chs_siz: equ 8
|
|
|
|
|
|
|
|
|
|
|
|
fndchs: ; find CHS table entry
|
|
|
|
; IN dl DOS drive number (A=0, B=1, ...)
|
|
|
|
; OUT cs:si ptr to chs table entry
|
|
|
|
push ax
|
|
|
|
mov ax, chs_siz
|
|
|
|
mul dl
|
|
|
|
add ax, chstab
|
|
|
|
mov si, ax
|
|
|
|
pop ax
|
|
|
|
ret
|
|
|
|
|
|
|
|
; compare sector number in disk access packet with zero
|
|
|
|
; sets zero flag accordingly
|
|
|
|
iszero: push ax
|
|
|
|
mov ax, [bx]
|
|
|
|
or ax, [bx+2]
|
|
|
|
pop ax
|
|
|
|
ret
|
|
|
|
|
|
|
|
; calculate CHS from dap and CHS table entry
|
|
|
|
; IN ds:bx disk access packet
|
|
|
|
; cs:si chstab table entry
|
|
|
|
; OUT cx,dh chs data for int 13h
|
|
|
|
calchs: push ax
|
|
|
|
; load linear sector number
|
|
|
|
mov dx, [bx+2]
|
|
|
|
mov ax, [bx]
|
|
|
|
; if any word of it is non-zero, we need to do calculation
|
|
|
|
call iszero
|
|
|
|
jz .zero
|
|
|
|
; ax is track number (lba / spt)
|
|
|
|
; dx is sector (lba % spt) + 1
|
|
|
|
div word [cs:si+chs_spt]
|
|
|
|
inc dx
|
|
|
|
; sector number
|
|
|
|
mov cl, dl
|
|
|
|
; ax is cylinder (track / heads)
|
|
|
|
; dx is head (track % heads)
|
|
|
|
xor dx, dx
|
|
|
|
div word [cs:si+chs_nos]
|
|
|
|
; set up cylinder and head number
|
|
|
|
mov ch, al
|
|
|
|
mov dh, dl
|
|
|
|
pop ax
|
|
|
|
ret
|
|
|
|
; set up CHS data for int 13h for reading sector zero
|
|
|
|
.zero: mov cx, 1 ; C=0, S=1
|
|
|
|
mov dh, 0 ; H=0
|
|
|
|
pop ax
|
|
|
|
ret
|
|
|
|
|
|
|
|
; ABSOLUTE DISK READ / DISK WRITE
|
|
|
|
int25h: mov ah, 2
|
|
|
|
jmp adisk
|
|
|
|
int26h: mov ah, 3
|
|
|
|
adisk: push bp
|
|
|
|
push ds
|
|
|
|
push es
|
|
|
|
mov bp, sp
|
|
|
|
cmp cx, 0xFFFF
|
|
|
|
je .islrg
|
|
|
|
|
|
|
|
; build a disk access packet on the stack
|
|
|
|
push ds ; dword transfer buffer
|
|
|
|
push bx
|
|
|
|
push cx ; word number of sectors
|
|
|
|
push cs ; dword starting sector number (CS always 0)
|
|
|
|
push dx
|
|
|
|
|
|
|
|
; set our freshly created dap as DS:BX
|
|
|
|
mov bx, sp
|
|
|
|
push ss
|
|
|
|
pop ds
|
|
|
|
|
|
|
|
.islrg: mov dl, al
|
|
|
|
call fndchs
|
|
|
|
call calchs
|
|
|
|
mov dl, al
|
|
|
|
mov al, [bx+4]
|
|
|
|
mov es, [bx+8]
|
|
|
|
mov bx, [bx+6]
|
|
|
|
int 0x13
|
|
|
|
jc .ret
|
|
|
|
|
|
|
|
.ret: mov sp, bp
|
|
|
|
pop es
|
|
|
|
pop ds
|
|
|
|
pop bp
|
|
|
|
retf: retf
|
|
|
|
|
|
|
|
; DOS IDLE INTERRUPT
|
2020-04-20 19:19:14 +02:00
|
|
|
; Usually hooked by TSRs
|
|
|
|
idle: sti
|
|
|
|
; sti takes one instruction to take effect
|
|
|
|
nop
|
|
|
|
; Wait until next interrupt
|
|
|
|
hlt
|
|
|
|
iret
|
|
|
|
|
2020-04-26 23:14:34 +02:00
|
|
|
; FAST CONSOLE OUTPUT
|
2020-04-20 19:13:06 +02:00
|
|
|
; 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-26 23:14:34 +02:00
|
|
|
vects: dw int20h, int21h, retf, retf
|
|
|
|
dw retf, int25h, int26h, int20h
|
|
|
|
dw idle, fputc
|
2020-04-23 21:49:10 +02:00
|
|
|
|
2020-04-26 23:14:34 +02:00
|
|
|
main: ; zero out first 64kb except our code
|
|
|
|
; bss and boot sector area gets cleared by this
|
|
|
|
mov di, init
|
|
|
|
mov cx, di
|
|
|
|
neg cx
|
|
|
|
xor ax, ax
|
|
|
|
rep movsb
|
2020-04-23 21:49:10 +02:00
|
|
|
|
2020-04-26 23:14:34 +02:00
|
|
|
; install interrupt vectors
|
|
|
|
mov si, vects
|
2020-04-23 21:49:10 +02:00
|
|
|
mov di, (0x20*4)
|
2020-04-26 23:14:34 +02:00
|
|
|
mov cx, 0x0A
|
|
|
|
intlp: movsw
|
|
|
|
mov ax, cs
|
|
|
|
stosw
|
|
|
|
loop intlp
|
2020-04-23 21:49:10 +02:00
|
|
|
|
2020-04-26 23:14:34 +02:00
|
|
|
; print banner to indicate we are booted
|
2020-04-23 21:49:10 +02:00
|
|
|
mov si, banner
|
|
|
|
mov ah, 9
|
|
|
|
int 0x21
|
|
|
|
|
2020-04-26 23:14:34 +02:00
|
|
|
call dnconv
|
|
|
|
mov al, dl
|
|
|
|
mov cx, 1
|
|
|
|
mov dx, 0
|
|
|
|
mov bx, buffer
|
|
|
|
int 3
|
|
|
|
intcall 0x25
|
|
|
|
int 3
|
|
|
|
|
2020-04-23 21:49:10 +02:00
|
|
|
loop: int 0x28
|
|
|
|
jmp loop
|
2020-03-25 21:56:00 +01:00
|
|
|
|
2020-04-18 22:59:46 +02:00
|
|
|
init: cli
|
|
|
|
xor ax, ax
|
|
|
|
mov ds, ax
|
|
|
|
mov es, ax
|
|
|
|
mov ss, ax
|
2020-04-26 23:14:34 +02:00
|
|
|
mov sp, ( stack+stacks )
|
2020-04-18 22:59:46 +02:00
|
|
|
|
2020-04-23 21:49:10 +02:00
|
|
|
; relocate
|
2020-04-18 22:59:46 +02:00
|
|
|
mov si, 0x7C00
|
|
|
|
mov di, $$
|
|
|
|
mov cx, (init-$$)
|
|
|
|
rep movsb
|
|
|
|
|
|
|
|
jmp 0:main
|
2020-04-20 19:13:06 +02:00
|
|
|
|
2020-04-23 21:36:20 +02:00
|
|
|
section .bss
|
2020-04-26 23:14:34 +02:00
|
|
|
; stack to be used during init and disk i/o
|
|
|
|
stack: resw stacks
|
|
|
|
; default int 25h/26h handler use a cache to keep geometry for
|
|
|
|
; the first 4 drives
|
|
|
|
chstab: resw (4*chs_siz)
|
|
|
|
|
2020-04-23 21:49:10 +02:00
|
|
|
bpb: resb bpb_len
|
|
|
|
drvnum: resb 1
|
2020-04-23 21:36:20 +02:00
|
|
|
align 4
|
2020-04-23 21:49:10 +02:00
|
|
|
drvoff: resd 1; partition offset
|
|
|
|
drvpos: resd 1; absolute physical sector number
|
|
|
|
buffer: resb 512
|