assemblyx86bootloaderosdevfloppy

Bootloader/kernel only booting in a virtual machine


So, the past few weeks I have looked in to writing a bootloader and kernel in assembly (x86/x86_64) and while I have tried more complex solutions, before writing one myself I decided to try out some code a user named Sinned posted here. My bootloader code is:

[BITS 16]
[ORG 0x7C00]

MOV DL, 0x0 ;drive 0 = floppy 1
MOV DH, 0x0 ;head (0=base)
MOV CH, 0x0 ;track/cylinder
MOV CL, 0x02 ;sector (1=bootloader, apparently sectors starts counting at 1 instead of 0)
MOV BX, 0x1000 ;place in RAM for kernel - I suppose randomly chosen on examples
MOV ES, BX ;place BX in pointer ES
MOV BX, 0x0 ;back to zero - also has something to do with RAM position

ReadFloppy:
MOV AH, 0x02
MOV AL, 0x01
INT 0x13
JC ReadFloppy ;if it went wrong, try again

;pointers to RAM position (0x1000)
MOV AX, 0x1000
MOV DS, AX
MOV ES, AX
MOV FS, AX
MOV GS, AX
MOV SS, AX

JMP 0x1000:0x0

;assuming we get never back here again, so no further coding needed (kernel handles everything now)

TIMES 510 - ($ - $$) db 0 ;fill resting bytes with zero
DW 0xAA55 ;end of bootloader (2 bytes)

My kernel file is:

;set print-registers
MOV AH, 0x0E ;function nr
MOV BH, 0x00 ;page
MOV BL, 0x07 ;color

MOV SI, msg ;move msg to SI-pointer
CALL PrintString ;call function to print SI (msg)

JMP $ ;hang

PrintString:
.next_char:
MOV AL, [SI] ;current character
OR AL, AL
JZ .print_done ;if current char is zero, go to end
INT 0x10 ;print character
INC SI ;increase pointer to msg (next character)
JMP .next_char
.exit_char
RET

msg db 'Hello world from the kernel!', 13, 10, 0

TIMES 512 - ($ - $$) db 0 ;fill the rest

I can get everything to assemble fine, and the single binary created boots inside VirtualBox when attached to a floppy controller. While this gives me confidence to work on my own loader and kernel, I would like to have the satisfaction of booting it on bare metal.

I have attempted booting the image with USB drives to no avail, and I'm sure that I'm imaging the USB sticks correctly. I'm starting to get the feeling that I'm missing something really obvious here. I suspect that it's something to do with using 13h to read from a "floppy" where I'm actually trying to read the raw binary off a USB. Is this the case? If so, how can I rewrite the bootloader to read from a nonspecific disk instead of a floppy?


Solution

  • I've written up some General Bootloader tips that apply to this code. In particular I have this tip:

    1. When the BIOS jumps to your code you can't rely on CS,DS,ES,SS,SP registers having valid or expected values. They should be set up appropriately when your bootloader starts. You can only be guaranteed that your bootloader will be loaded and run from physical address 0x00007c00 and that the boot drive number is loaded into the DL register.

    The boot drive of the first floppy is generally 0 so your virtual machine likely worked because you booted a floppy disk image mounted as virtual drive A: . The code that is causing you problems is in your ReadFloppy code. In particular this line:

    MOV DL, 0x0 ;drive 0 = floppy 1
    

    You hard code zero where you should be using the value passed by the BIOS. On any system where you booted as anything other than floppy drive A: it would likely fail. To fix the problem, simply remove the line above.

    I recommend reviewing the other bootloader tips I provided in the link provided.