I created a simple bootloader that reads a value in memory and keeps running only if that value is the expected one.
For some reason, when the OS boots on QEMU x86_64 this code works (it jumps to keep_running
) but on VirtualBox and on physical hardware it doesn’t. After doing some debugging I found that the problem was with memory addressing, but I don’t know why it occurs and how to solve this problem.
; BOOT SECTOR
bits 16
[org 0x7C00]
call disk_read
jmp extended_space_start
disk_read: ; disk_read(al > Number of sectors, dl > Drive number, es:bx > Address)
push ax ; Push the number of sectors for checking later
mov ah, 0x02 ; Disk read operation
mov cl, 0x02 ; Sector (0x01 = BOOT)
mov ch, 0x00 ; Cylinder
mov dh, 0x00 ; Head
; mov dl, 0x00 ; Drive number (may be set by the BIOS) 0x00: 1st Floppy, 0x01: 2nd Floppy, 0x80: 1st Hard Disk Drive, 0x81: 2nd Hard Disk Drive
int 0x13
jc .disk_error ; If any error happens the Carry is set to 1
pop bx
cmp al, bl
jne .sector_error
ret
.disk_error:
.sector_error:
jmp $
test: db 0xFF
times 510-($-$$) db 0
db 0x55, 0xAA
extended_space_start:
cmp byte [test], 0xFF
je keep_running
jmp $
keep_running:
mov ax, 0xB800
mov es, ax
mov ax, 0x0000
mov di, ax
mov byte [es:di], 'X'
jmp $
QEMU reads 0xFF but VBox reads 0x00.
Why does the bootloader work on QEMU but not on VirtualBox / physical hardware?