Implement some PoC of reading from disk

This commit is contained in:
Nero 2020-04-15 00:17:58 +02:00
parent 6b49a20865
commit 23ddd6b41a

View File

@ -1,88 +1,78 @@
cpu 8086 cpu 8086
org 0x7C00 org 0
jmp 0x07C0:init
stack: equ 0x7C00 %include "inc/bpb.asm"
framsz: equ 0x300
jmp init banner: db "rdos", 0xA, 0xD, 0
; Data on user stack while in kernel (5 words): ; syscalls push a register set to stack
; AX BP IP CS flags ; this is for accessing it
rsdssi: equ 0x08
rsesdi: equ 0x0C
rsbp: equ 0x10
rslpad: equ 0x12
rscsip: equ 0x14
rsflag: equ 0x18
; Kernel stack: lpads: times 0x30 call entry
; [frame] SP SS
; BP-^
; The start of the frame is available via BP.
; The frame is followed by a long ptr to the user stack.
; Main entry point entry: push bp
int20h: xor ah, ah ; BX+0C: ES:DI
int21h: push bp push es
push ax push di
; Test if SS=0, if it is, we assume we are already on kernel stack ; BX+08: DS:SI
mov ax, ss push ds
test ax, ax push si
jz rentry ; BX+00: AX,CX,DX,BX
push bx
; Save user stack push dx
mov ax, ss push cx
mov [cs:stack-2], ax
mov [cs:stack-4], sp
; Set up kernel stack
xor ax, ax
mov ss, ax
mov sp, (stack-4)
jmp scall
; This is like the above, except that it doesnt switch stacks.
; The 'user' stack data is after (below on stack) the kernel frame.
; [frame] SP SS AX BP IP CS flags
; \-\--^
rentry: mov ax, sp
push ss
push ax push ax
scall: sub sp, framsz mov ax, ss
mov bp, sp mov es, ax
mov bx, sp
call getax ; This needs to be done when coming from userspace
call jmptab mov ax, cs
; Restore user stack
mov sp, [bp+framsz]
mov ax, [bp+framsz+2]
mov ss, ax 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 ax
pop cx
pop dx
pop bx
; string ptrs
pop si
pop ds
pop di
pop es
; BP is special
pop bp pop bp
; skip landing pad number
add sp, 2
; pop IP, CS and flags
iret iret
; Lookup address of subfunction ; Processes register set DS:BX as syscall
; Mesh up the stack so we return to subfunction scall: ; Clear status flags
; and subfunction later returns to scall and byte [bx+rsflag], 0
jmptab: push ax
push bx
xor bx, bx
add bl, ah
add bl, ah
mov bx, [cs:bx+sftab]
mov [bp-4], bx
pop bx
ret ret
; Get AX from the user stack ; No such subfunction
getax: push ds sferr: ; set carry
push si or byte [bx+rsflag], 1
lds si, [bp+framsz]
lodsw
pop ds
pop si
ret
; No such subfunction - set carry and exit
sferr: stc
ret ret
; Subfunction table ; Subfunction table
@ -146,34 +136,93 @@ setint: push es
pop es pop es
ret ret
; ===== end of resident, begin of transient startup code bpb: times bpb_len db 0
drvnum: db 0
align 4
drvpos: dd 0
buffer: times 512 db 0
init: xor ax, ax ; 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 ds, ax
mov es, ax mov es, ax
mov ax, 0x1000
mov ss, ax mov ss, ax
xor sp, sp xor sp, sp
mov al, 0x21 xor dh, dh
mov dx, int21h call dnconv
call setint call select
mov ax, 0x2520 xor ax, ax
mov dx, int20h xor dx, dx
int 0x21 call seek
mov ax, 0x3520 call read
int 0x21
mov ah, 0x3f mov ax, [buffer+0x1FE]
int 3
int 0x21
int 3 int 3
main: push cs main: push cs
pop ds pop ds
mov si, msg mov si, banner
mov ah, 0x0e mov ah, 0x0e
xor bx, bx xor bx, bx
loop: lodsb loop: lodsb
@ -184,4 +233,3 @@ loop: lodsb
end: hlt end: hlt
jmp end jmp end
msg: db "rdos kernel stub", 0x0A, 0x0D, 0