Nero
1981a8efba
We now set BP once at the start to point to the beginning of the BPB. Encoding an direct address access can then be done relative to BP, which saves an immediate byte per access.
239 lines
3.4 KiB
NASM
239 lines
3.4 KiB
NASM
; Bootsector for FAT32 filesystems
|
|
org 0x0800
|
|
cpu 8086
|
|
jmp short init
|
|
nop
|
|
|
|
%include "inc/bpb.asm"
|
|
|
|
bpb: equ 0x080B
|
|
|
|
; Area for BPB
|
|
times ( 0x5A - ($-$$) ) db 0
|
|
|
|
init: xor ax, ax
|
|
mov ss, ax
|
|
mov sp, 0x7C00
|
|
|
|
; save potential partition table entry
|
|
push ds
|
|
push si
|
|
|
|
mov ds, ax
|
|
mov es, ax
|
|
|
|
mov si, 0x7C00
|
|
mov di, 0x0800
|
|
mov cx, 0x0100
|
|
rep movsw
|
|
jmp 0x0:main
|
|
|
|
msg: pop si
|
|
mloop: lodsb
|
|
test al, al
|
|
jz mend
|
|
mov ah, 0x0e
|
|
mov bx, 7
|
|
int 0x10
|
|
jmp mloop
|
|
mend: push si
|
|
ret
|
|
|
|
dskerr: call msg
|
|
db "DISK", 0
|
|
err: call msg
|
|
db "ERR", 0x0A, 0x0D, 0
|
|
hlt: hlt
|
|
jmp hlt
|
|
|
|
; offsets relative to FS
|
|
readd: ; add offset of cluster data area to DX:AX
|
|
push cx
|
|
mov di, [bp+bpb_rde]
|
|
mov cl, 4
|
|
shr di, cl ; 32 bytes per entry
|
|
add ax, di
|
|
adc dx, 0
|
|
pop cx
|
|
readr: ; add offset to rootdir to DX:AX (FAT12/FAT16 only)
|
|
push cx
|
|
xor ch, ch
|
|
mov cl, byte [bp+bpb_fn]
|
|
fatlp: add ax, [bp+bpb7_lsf]
|
|
adc dx, [bp+bpb7_lsf+2]
|
|
loop fatlp
|
|
pop cx
|
|
readf: ; add offset to FAT table to DX:AX
|
|
add ax, word [bp+bpb_rsc]
|
|
adc dx, 0
|
|
readp: ; read sector DX:AX from partition
|
|
add ax, word [bp+bpb_po]
|
|
adc dx, word [bp+bpb_po+2]
|
|
jc err
|
|
read_: ; read sector DX:AX from disk
|
|
; qword sector number DX:AX
|
|
push cs
|
|
push cs
|
|
push dx
|
|
push ax
|
|
|
|
; dword target buffer: BX:0
|
|
push bx
|
|
push cs
|
|
|
|
; word sector number
|
|
push cx
|
|
|
|
; size & passing
|
|
mov di, 0x10
|
|
push di
|
|
|
|
mov si, sp
|
|
mov ah, 0x42
|
|
mov dl, [bp+bpb7_dn]
|
|
stc
|
|
int 0x13
|
|
jc dskerr
|
|
|
|
add sp, di
|
|
|
|
ret
|
|
|
|
next: ; Advances DX:AX to next FAT entry
|
|
push ax
|
|
push bx
|
|
|
|
; shift 2 left for dword-sized FAT entries
|
|
; shift 9 right for sector size
|
|
mov cl, 7
|
|
shftl: clc
|
|
rcr dx, 1
|
|
rcr ax, 1
|
|
loop shftl
|
|
|
|
mov bx, 0xA0
|
|
mov cx, 1
|
|
call readf
|
|
|
|
pop bx
|
|
|
|
; get lower part of cluster number
|
|
pop si
|
|
; multiply with 4
|
|
sal si, 1
|
|
sal si, 1
|
|
; make sure its within sector range
|
|
and si, 0x1FF
|
|
add si, buf
|
|
; load dword from FAT
|
|
lodsw
|
|
mov dx, [si]
|
|
|
|
ret
|
|
|
|
; reads current cluster into [dest]
|
|
readc: ; load cluster number
|
|
push ax
|
|
push dx
|
|
|
|
; subtract the two dummy entries from FAT start
|
|
sub ax, 2
|
|
sbb dx, 0
|
|
|
|
; convert cluster number to sector number
|
|
; this is some cheapo multiplication with 2^n
|
|
mov cl, [bp+bpb_sc]
|
|
l02: shr cl, 1
|
|
jz l02e
|
|
clc
|
|
rcl ax, 1
|
|
rcl dx, 1
|
|
jmp l02
|
|
l02e:
|
|
; dx:ax is now sector num in data area
|
|
mov cx, [bp+bpb_sc]
|
|
xor ch, ch
|
|
|
|
call readd
|
|
|
|
xchg di, cx
|
|
mov cl, 5
|
|
sal di, cl
|
|
add bx, di
|
|
|
|
pop dx
|
|
pop ax
|
|
|
|
ret
|
|
|
|
; load cluster chain DX:AX to [dest]:0
|
|
load: mov bx, 0x07C0
|
|
lloop: call readc
|
|
call next
|
|
cmp word dx, 0x0FFF
|
|
jne lloop
|
|
ret
|
|
|
|
; Search for first entry with matching fsattr
|
|
search: mov si, (0x7C00-0x20)
|
|
loop: add si, 0x20
|
|
; check if entry is valid
|
|
mov al, [si]
|
|
; unallocated direntry
|
|
test al, al
|
|
jz end
|
|
; deleted files
|
|
cmp al, 0xE2
|
|
je loop
|
|
; check attr
|
|
mov al, [si+11]
|
|
and al, 0x5C
|
|
cmp al, ah
|
|
jne loop
|
|
ret
|
|
|
|
loadr: mov ax, 2
|
|
xor dx, dx
|
|
jmp load
|
|
|
|
loadf: call search
|
|
jne end
|
|
mov ax, [si+0x1A]
|
|
mov dx, [si+0x14]
|
|
jmp load
|
|
|
|
main: mov bp, bpb
|
|
mov [bp+bpb7_dn], dl
|
|
; load root directory
|
|
call loadr
|
|
; search for first system directory
|
|
mov ah, 0x14
|
|
call loadf
|
|
; search for first system file
|
|
mov ah, 0x04
|
|
call loadf
|
|
; jump
|
|
xor ax, ax
|
|
xor cx, cx
|
|
xor dx, dx
|
|
xor bx, bx
|
|
xor di, di
|
|
|
|
; restore drive number
|
|
mov dl, [bp+bpb7_dn]
|
|
|
|
; restore potential partition table
|
|
pop si
|
|
pop ds
|
|
|
|
jmp 0:0x7C00
|
|
|
|
end: call msg
|
|
db "DIR", 0
|
|
jmp err
|
|
|
|
; Padding and signature
|
|
times (0x1FE - ($-$$)) db 0
|
|
dw 0xAA55
|
|
buf:
|