I tried to load kernel stored on floppy disk formatted to FAT12. When I try to read sectors where kernel is located, I don’t have any errors (carry flag is not set), but memory where I try to load the kernel has zeroes.
org 0x7C00
bits 16
%define endl 0x0D, 0x0A
%define dirEntrySize 32
%define fatLocation 0x7E00
%define rootdirLocation 0x9000
%define kernelLocation 0x9E00
%define filenameLength 11
jmp short main
nop
; BPB and EBR data here
rootdirStart: dw 0
dataStart: dw 0
main:
xor ax, ax
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0x7C00
mov [ebr_driveNumber], dl
mov si, msg_loading
call puts
; Read FAT
mov ax, [bpb_reservedSectors]
mov bx, fatLocation
mov cx, [bpb_sectorsPerFat]
call readSectors
; Read Root Directory
mov ax, [bpb_rootdirEntries]
mov bx, dirEntrySize
mul bx
div word [bpb_bytesPerSector]
mov [dataStart], ax
xchg ax, cx
mul byte [bpb_fatCount]
add ax, [bpb_reservedSectors]
mov bx, rootdirLocation
call readSectors
mov [rootdirStart], ax
add [dataStart], ax
; Find and read the kernel
mov si, kernelFilename
call findFile
mov bx, kernelLocation
call readFile
; Load kernel
mov dl, [ebr_driveNumber]
jmp kernelLocation
cli
hlt
; putc and puts functions
lbaToChs:
push ax
push dx
xor dx, dx
div word [bpb_sectorsPerTrack]
inc dx
mov cx, dx
xor dx, dx
div word [bpb_headCount]
mov dh, dl
mov ch, al
shl ah, 6
or cl, ah
pop ax
mov dl, al
pop ax
ret
readSectors:
push ax
push cx
push dx
push si
push di
push cx
call lbaToChs
pop si
mov di, 3
mov dl, [ebr_driveNumber]
.loop:
mov ah, 0x02
int 0x13
mov ah, 0x01
int 0x13
jnc .done
mov ah, 0x00
int 0x13
dec di
jz .fail
dec si
jnz .loop
.done:
pop di
pop si
pop dx
pop cx
pop ax
ret
.fail:
mov si, msg_diskError
call puts
cli
hlt
; findFile function
readFile:
push ax
push bx
push cx
push dx
.loop:
push ax
sub ax, 2
mul byte [bpb_sectorsPerCluster]
add ax, word [dataStart]
mov cx, 1
call readSectors
mov ax, [bpb_bytesPerSector]
mul byte [bpb_sectorsPerCluster]
add bx, ax
pop ax
mov cl, 3
mul cx
dec cl
div cx
mov si, fatLocation
add si, ax
mov ax, [si]
or dx, dx
jnz .odd
.even:
and ax, 0x0FFF
jmp .update
.odd:
shr ax, 4
.update:
cmp ax, 0xFF0
jnl .loop
.done:
pop dx
pop cx
pop bx
pop ax
ret
.fail:
mov si, msg_loadFailed
call puts
cli
hlt
kernelFilename: db "KERNEL BIN"
msg_loading: db "Loading...", endl, 0
msg_findFailed: db "Cannot find kernel", 0
msg_loadFailed: db "Cannot load kernel", 0
msg_diskError: db "Disk error", 0
times 510+$$-$ db 0
dw 0xAA55
I tried debugging with GDB and checked the registers, but their value was correct. I also checked the memory where I stored the FAT and the Root Directory, but this data also was correct. Only the memory where I wanted to load kernel was filled with zeroes.
Register values after lba-to-chs conversion:
eax 0x21 33
ecx 0x10 16
edx 0x100 256
ebx 0x9e00 40448
esp 0x7be6 0x7be6
ebp 0x0 0x0
esi 0x7d98 32152
edi 0x0 0
eip 0x7ce6 0x7ce6
eflags 0x202 [ IOPL=0 IF ]
cs 0x0 0
ss 0x0 0
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
AX value is correct, should be lba of start of data: reserved_sectors + sectors_per_fat * fat_count + root_dir_entries * dir_entry_size / bytes_per_sectors = 1 + 9 * 2 + 224 * 32 / 512 = 1 + 18 + 14 = 33
. In floppy image opened with hex editor, that points to start of the kernel.
Loaded file allocation table:
0x7e00: 0xf0 0xff 0xff 0xff 0x0f 0x00 0x00 0x00
0x7e08: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
...
Loaded root directory:
0x9000: 0x4b 0x45 0x52 0x4e 0x45 0x4c 0x20 0x20
0x9008: 0x42 0x49 0x4e 0x20 0x18 0x00 0x28 0x61
0x9010: 0xaa 0x58 0xaa 0x58 0x00 0x00 0x28 0x61
0x9018: 0xaa 0x58 0x02 0x00 0x25 0x01 0x00 0x00
0x9020: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x9028: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x9030: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x9038: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
...
*Loaded* kernel:
0x9e00: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x9e08: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x9e10: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x9e18: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
...
Grigaror is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.