; Bootsector for FAT32 filesystems org 0x0800 jmp short init nop ; WORD reserved sector count rsc: equ ( $$ + 0x00E ) ; BYTE number of sectors per cluster sc: equ ( $$ + 0x00D ) ; BYTE number of FATs fn: equ ( $$ + 0x010 ) ; WORD number of root directory entries rde: equ ( $$ + 0x011 ) ; DWORD hidden sector count (partition offset) po: equ ( $$ + 0x01C ) ; DWORD sectors per FAT sf: equ ( $$ + 0x024 ) ; BYTE drive number (we set it from dl) dn: equ ( $$ + 0x040 ) ; Area for BPB times (0x5A - ($-$$)) db 0 init: xor ax, ax mov ds, ax mov es, ax mov ss, ax mov sp, 0x7C00 mov si, sp 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 err: call msg db "ERR", 0x0A, 0x0D, 0 hlt: hlt jmp hlt ; offsets relative to FS offd: ; add offset of cluster data area to DX:AX push cx mov di, [rde] mov cl, 4 shr di, cl ; 32 bytes per entry add ax, di adc dx, 0 pop cx offr: ; add offset to rootdir to DX:AX (FAT12/FAT16 only) push cx xor ch, ch mov cl, byte [fn] fatlp: add ax, [sf] adc dx, [sf+2] loop fatlp pop cx offf: ; add offset to FAT table to DX:AX add ax, word [rsc] adc dx, 0 ret readp: ; read sector DX:AX from partition add ax, word [po] adc dx, word [po+2] jc err readd: ; 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 bp, 0x10 push bp mov si, sp mov ah, 0x42 mov dl, 0x80 stc int 0x13 jc err add sp, bp ret next: ; Advances [clus] to next FAT entry ; get current cluster number mov ax, [clus] mov dx, [clus+2] ; 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 call offf mov bx, 0xA0 mov cx, 1 call readp ; get lower part of cluster number mov si, [clus] ; multiply with 4 sal si, 1 sal si, 1 ; make sure its within sector range and si, 0x1FF add si, buf mov di, clus ; copy dword from FAT to [clus] movsw movsw ret ; reads current cluster into [dest] readc: ; load cluster number mov ax, [clus] mov dx, [clus+2] ; 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 ch, [sc] l02: shr cl, 1 jz l02e clc rcl dx, 1 rcl ax, 1 jmp l02 l02e: ; dx:ax is now sector num in data area call offd mov bx, [dest] mov cx, [sc] xor ch, ch call readp xchg bx, cx mov cl, 5 sal bx, cl add [dest], bx ret loadf: call readc call next cmp word [clus+2], 0x0FFF jne loadf ret main: call loadf mov ax, [0x7C00] mov cx, [0x7C02] int 3 xor ah,ah int 0x16 int 0x19 jmp hlt ; current cluster number clus: dd 2 ; segment register for data dest: dw 0x07c0 ; Padding and signature times (0x1FE - ($-$$)) db 0 dw 0xAA55 buf: