I ended up coming across this repo after seeing it linked elsewhere, and after taking a brief look found some bugs in boot.asm which will likely cause the bootloader to fail to boot on real hardware. These bugs appear to be common ones inherited from cfenollosa/os-tutorial and the infamous University of Birmingham PDF it's inspired by.
The first problematic segment of boot.asm is this section of code that initializes the stack:
; Initialize the base pointer and the stack pointer
; The initial values should be fine for what we've done so far,
; but it's better to do it explicitly
mov bp, 0x0500
mov sp, bp
This code is problematic for a few reasons, firstly it repeats the same misconception that these other tutorials do and act like bp is necessary for the stack, bp never gets used so we don't need to worry about setting it. bp isn't the "bottom of the stack" like these tutorials seem to imply, in most ABI's it's used as the bottom of the current stack frame, since in the bootloader we don't have stack frames, we don't need to worry about it and can just load sp directly.
Not only is this write to bp completely unnecessary, it disregards segmentation. sp and bp both use ss as the base of their effective addresses, and ss is not guaranteed to be any value until its deliberately set by the programmer. This works fine in a VM like QEMU which will nicely have ss (and all segment registers) set to 0 on boot, but on real hardware these can be essentially any random 8-bit value. Since interrupts use the stack, we must have a valid ss:sp at all times, so we need to update ss and sp atomically, which we currently are not doing. x86 shadows interrupts immediately after writing to ss to enable us to safely update sp without risking an interrupt occurring, so we should update sp immediately after updating ss. A better way to initialize the stack would be:
xor ax, ax
mov ss, ax
mov sp, some_constant
Initializing the stack to such a small memory value (the current tutorial loads it to 0x0500) seems smelly to me, but I can't think of any problems off the top of my head.
The next segment of code is also problematic
; Before we do anything else, we want to save the ID of the boot
; drive, which the BIOS stores in register dl. We can offload this
; to a specific location in memory
mov byte[boot_drive], dl
This code implicitly uses the value of ds, without ds being known, resulting in UB.
There's potentially some other bugs as well, but these are two that immediately jump out, as they've sort of become "canary in the coal mine"s when trying to diagnose hobbyist OS issues.
I ended up coming across this repo after seeing it linked elsewhere, and after taking a brief look found some bugs in
boot.asmwhich will likely cause the bootloader to fail to boot on real hardware. These bugs appear to be common ones inherited from cfenollosa/os-tutorial and the infamous University of Birmingham PDF it's inspired by.The first problematic segment of
boot.asmis this section of code that initializes the stack:This code is problematic for a few reasons, firstly it repeats the same misconception that these other tutorials do and act like
bpis necessary for the stack,bpnever gets used so we don't need to worry about setting it.bpisn't the "bottom of the stack" like these tutorials seem to imply, in most ABI's it's used as the bottom of the current stack frame, since in the bootloader we don't have stack frames, we don't need to worry about it and can just loadspdirectly.Not only is this write to
bpcompletely unnecessary, it disregards segmentation.spandbpboth usessas the base of their effective addresses, andssis not guaranteed to be any value until its deliberately set by the programmer. This works fine in a VM like QEMU which will nicely havess(and all segment registers) set to 0 on boot, but on real hardware these can be essentially any random 8-bit value. Since interrupts use the stack, we must have a validss:spat all times, so we need to updatessandspatomically, which we currently are not doing. x86 shadows interrupts immediately after writing tossto enable us to safely updatespwithout risking an interrupt occurring, so we should updatespimmediately after updatingss. A better way to initialize the stack would be:Initializing the stack to such a small memory value (the current tutorial loads it to 0x0500) seems smelly to me, but I can't think of any problems off the top of my head.
The next segment of code is also problematic
This code implicitly uses the value of
ds, withoutdsbeing known, resulting in UB.There's potentially some other bugs as well, but these are two that immediately jump out, as they've sort of become "canary in the coal mine"s when trying to diagnose hobbyist OS issues.