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 0x7C00bits 16%define endl 0x0D, 0x0A%define dirEntrySize 32%define fatLocation 0x7E00%define rootdirLocation 0x9000%define kernelLocation 0x9E00%define filenameLength 11jmp short mainnop; BPB and EBR data hererootdirStart: dw 0dataStart: dw 0main: 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 functionslbaToChs: 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 retreadSectors: 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 functionreadFile: 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 hltkernelFilename: db "KERNEL BIN"msg_loading: db "Loading...", endl, 0msg_findFailed: db "Cannot find kernel", 0msg_loadFailed: db "Cannot load kernel", 0msg_diskError: db "Disk error", 0times 510+$$-$ db 0dw 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 33ecx 0x10 16edx 0x100 256ebx 0x9e00 40448esp 0x7be6 0x7be6ebp 0x0 0x0esi 0x7d98 32152edi 0x0 0eip 0x7ce6 0x7ce6eflags 0x202 [ IOPL=0 IF ]cs 0x0 0ss 0x0 0ds 0x0 0es 0x0 0fs 0x0 0gs 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 0x000x7e08: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00...
Loaded root directory:
0x9000: 0x4b 0x45 0x52 0x4e 0x45 0x4c 0x20 0x200x9008: 0x42 0x49 0x4e 0x20 0x18 0x00 0x28 0x610x9010: 0xaa 0x58 0xaa 0x58 0x00 0x00 0x28 0x610x9018: 0xaa 0x58 0x02 0x00 0x25 0x01 0x00 0x000x9020: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x000x9028: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x000x9030: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x000x9038: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00...
*Loaded* kernel:
0x9e00: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x000x9e08: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x000x9e10: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x000x9e18: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00...