I changed my bootloader from CHS to LBA, so I replaced int 13h 02h
with int 13h 42h
. It works correctly in QEMU, however, I have troubles running it with Bochs and my laptop.
I wrote bootloader to USB flash drive with dd if=main.bin of=/dev/sdb bs=512
. Laptop loads Intel UNDI and gives me the following error: No bootable device - insert boot disk and press any key
.
So I tried to debug it with Bochs and noticed that Bochs recognizes this binary file as bootable. However, nothing had been loaded after int 13h
executed.
Then I tried to load my old PC from this flash drive, and it works! It loads program and executes it correctly. QEMU gives me the same result.
Here is the bootloader code:
org 0x7c00
bits 16
boot:
cli
; Overlap CS and DS
mov ax, cs
mov ds, ax
mov es, ax
; Setup 4K stack before this bootloader
mov ax, 0x07c0
mov ss, ax
mov sp, 4096
; Load next sectors
mov si, DAP
mov ah, 42h
; DL didn't changed
int 13h
; Start
jmp bootend
; Disk address packet
DAP:
db 10h, 0
dw %1 ; Number of sectors to be loaded
dd bootend
dq 1
; Fill the rest of bootsector with zeroes and end it
times 510 - ($ - boot) db 0
dw 0xAA55
bootend:
bochsrc:
megs: 32
romimage: file=/usr/share/bochs/BIOS-bochs-latest, address=0xfffe0000
vgaromimage: file=/usr/share/bochs/VGABIOS-lgpl-latest
floppya: 1_44=main.bin, status=inserted
boot: a
panic: action=ask
log: bochsout.txt
mouse: enabled=0
keyboard: type=mf, serial_delay=200, paste_delay=100000
display_library: x, options="gui_debug"
LBA Disk Access Availability
Not all BIOSes support the extended disk read and write functions (although on modern hardware they almost all likely will). Not all BIOSes support extended disk reads of floppies via Int 13h/AH=42h. This is true of BOCHS as well. You can test whether extended disk functions are available on a drive via Int 13/AH=41h/BX=55AAh. This does an extended disk installation check.
If you want to test your code on BOCHS using extended disk reads and LBA you will have to create a hard disk image and modify BOCHS to boot from it instead of floppy. The minimum size hard disk image size that BOCHS supports is one with CHS = 1/16/63 which is 512*16*63 = 516096 bytes or 1008 sectors of 512 bytes each.
You can modify your
bochsrc.txt
to be:I use a disk image called
disk.img
. You can create it and place the sectors you generate into it with commands like:Create an image of 516096 bytes:
Place the boot sectors into the beginning of
disk.img
without truncating the file:I have additional information on using DD to create disk images in this Stackoverflow answer.
General Code Observations
Although the disk image is part of the issue with BOCHS you do have some coding issues. You can't assume the value of CS will be set to what you think when control is transferred from the BIOS to your bootloader. See my General Bootloader Tips for more information. If you want DS and ES to be zero (which is what you'd need with
org 0x7c00
), you should modify the start of your code to be something like:To test out your code I added this after
bootend
:I'm not sure this line is a typo or you are using some type of pre-processor on your assembly files before passing them to NASM. Normally this line would be a problem with the
%
symbol before1
:NASM would only support this directly:
Real Hardware / USB / Laptop Issues
If you are attempting to use USB to boot on real hardware then you may encounter another issue even if you get it working in BOCHS with the changes above. If your BIOS is set to do USB FDD emulation (and not USB HDD or something else) you may need to add a Boot Parameter Block(BPB) to the beginning of your bootloader. You can create a fake one like this:
If you were to modify your code to have the layout above the Unix/Linux
file
command may be able to dump out the BPB data that it thinks makes up your MBR in the disk image. Run the commandfile disk.img
and you may get this output:Complete Example with Int 13h Extension Checks
The following code will check that Int 13h extensions are available in the BIOS and will also determine if the drive in DL supports Int 13h extensions. If there is a failure the code will print an appropriate error. A
print_string
function is used to display strings to the console using BIOS TTY output and aprint_hex_word
function is provided to display the boot drive number in hexadecimal.Using the information to make this a hard disk image above, when I run it in BOCHS I get this output:
If I boot this same image as a floppy disk (disk A:) in BOCHS the error message now tells me that Int 13h extensions aren't available for drive 0x0000:
If you find that you need to read a device that doesn't support Int 13h extensions you will have to fall back to the standard Int 13h disk subfunctions for reading (AH=02)/writing (AH=03).