Master the fundamental concepts of boot sector development through this focused micro-challenge.
Three hints are available for this task, revealed one at a time inside the code workspace so you can struggle productively before seeing them.
Every task includes starter code, theory, and hidden tests so you can implement and verify locally in the browser.
How it worksA single boot sector cannot hold a full loader. INT 0x13 extended read (AH=0x42) loads contiguous LBAs into memory above 0x7E00 so your stage-one code stays put. For example, a DAP requesting 32 sectors from LBA 1 fills 0x7E00-0xBE00 with stage-two code you then jump to.
nasmLoading…
DL to the BIOS boot drive number (often passed in DL at entry)int 0x13; reset disk with AH=0x00 on failureLoading to 0x7E00 places 512 bytes immediately above the boot sector, minimizing overlap risk. Larger reads must not stomp the stack you placed near 0x90000. The BIOS returns the number of sectors actually read in AH on success for CHS reads; for DAP, check the updated count field. Reset disk on error 0xAA before retrying on real hardware.
You will extend your boot sector to load additional sectors via a DAP. This exercise requires constructing the packet layout and branching to the loaded code at the buffer address.
A boot sector has 512 bytes, so it loads the rest of the system with BIOS INT 13h, AH=02h (read sectors). The call uses CHS (cylinder/head/sector) addressing packed into registers, and real BIOSes add two constraints: a call should not run past the end of a track, and the buffer must not cross a 64 KiB DMA boundary. Write the planner a stage-1 loader needs: convert between LBA and CHS, and split a multi-sector read into the exact sequence of INT 13h calls.
cLoading…
LBA = (C × H_total + h) × S_total + (s − 1), and the reverse: c = LBA / (H×S), h = (LBA / S) mod H, s = LBA mod S + 1.
Registers: CH = c & 0xFF, CL = (s & 0x3F) | ((c >> 2) & 0xC0) (the top two cylinder bits ride in CL), and DH = h.
Plan a read by repeatedly issuing one call for the next unread LBA, with AL = the smallest of:
S − s + 1);(0x10000 − (linear & 0xFFFF)) / 512, rounded down, where linear = SEG × 16 + OFF.If (3) is 0, the next sector would straddle the boundary: print the error and stop. After each call, advance ES by AL × 0x20 (BX stays), so that offsets never wrap.
Before planning, reject a range that ends past the disk, and a buffer whose end passes 0x100000 (the real-mode 1 MiB limit).
cLoading…
(LBA n). Use sector / call when the count is 1.read line:
error: LBA range ends past the disk (N sectors); error: buffer passes the 1 MiB real-mode limit; error: DMA boundary: the sector at 0xLLLLL would cross a 64 KiB boundary (calls already printed stay, and there is no done line).error: geometry is C 1..1024, H 1..255, S 1..63;error: drive is a hex byte;error: no geometry;error: CHS out of range;error: LBA out of range;error: usage: read LBA COUNT SEG:OFF;error: bad command.Input:
cLoading…
Output:
cLoading…
Hidden tests cover the largest CHS geometry (1024/255/63), reads crossing a 64 KiB boundary (split and impossible), floppy multi-track reads, the 1 MiB limit, and malformed commands.