4

I am currently writing a bootloader, and when attempting to read more than exactly 65 sectors, QEMU will restart and refuse to run my code. I assume that I have done something incorrectly with my assembly code.

My current disk reading code is this:

KERNEL_SIZE_SECTORS                     equ 65                                  ;Kernel size in sectors
CYLINDER_IDX                            equ 0
HEAD_IDX                                equ 0
SECTOR_IDX                              equ 2
boot:
    mov                                 ah, 0x2                                 ;Tell BIOS that we want to read disk
    mov                                 al, KERNEL_SIZE_SECTORS                 ;Load the kernel sector amount
    mov                                 ch, CYLINDER_IDX                        ;Load the cylinder IDX
    mov                                 dh, HEAD_IDX                            ;Load the head IDX
    mov                                 cl, SECTOR_IDX                          ;Load the sector IDX
    mov                                 dl, [disk]                              ;Load the disk IDX
    mov                                 bx, copy_target                         ;Point to the copy target
    int                                 0x13                                    ;Load the bootloader+kernel into memory
    cli                                                                         ;Clear the interrupts
Michael Petch
  • 46,082
  • 8
  • 107
  • 198
  • 1
    Where is `copy_target` located? – dimich Sep 25 '22 at 19:18
  • 3
    Increment the addresses and load one sector at a time. Some ROM-BIOS implementations do not allow reads that cross a "track" boundary. – ecm Sep 25 '22 at 19:19
  • 3
    Not all firmware support reading from multiple heads. – Margaret Bloom Sep 25 '22 at 19:19
  • 1
    You can also do LBA reads with function `0x42` (my boot code does this under QEMU just fine). That should avoid most of the C/H/S headaches. – sj95126 Sep 25 '22 at 20:08
  • 2
    Also please specify what `copy_target` is. If you're loading just after the default boot block at `0000:7c00` you may be trampling on the default stack space just below `0000:ffff`. 65 sectors would be just about the right amount to hit that spot. – sj95126 Sep 25 '22 at 20:14
  • Maybe correct the question title, bytes and sectors are different things. – SoronelHaetir Sep 25 '22 at 20:14
  • copy_target in the first thing in the second sector. The bootloader is also linked to be located at 0x7c00 – Yomada Cheezit Sep 25 '22 at 22:01
  • 3
    Margaret is correct that multitrack reads may not be supported by all BIOSes especially real hardware. On BOCHS and QEMU the limit is artificially set at 72 for floppies (I think 128 for hard drives). The limit of 65 is usually associate with another rule: that a read can't span a 64KiB boundary (related to DMA). So you shouldn't be trying to cross physical address (0x10000, 0x20000, 0x30000, 0x40000.... etc). You don't tell us what `copy_target ` is but I suspect its value is 0x7e00 (and ES = 0). 65 sectors would take you right to address 0x10000. Read one more would cross that 64KiB boundary – Michael Petch Sep 26 '22 at 06:50
  • 1
    I believe that this question is likely a duplicate of https://stackoverflow.com/questions/58564895/problem-with-bios-int-13h-read-sectors-from-drive (See Ross Ridge's answer). You may also find some useful info in this answer for a somewhat related question: https://stackoverflow.com/a/55370912/3857942 . I don't know for certainty unless I know the value of ES:BX for Int 13h/AH=2. One way to avoid most issues (albeit slower on a real floppy) is to loop 1 sector at a time and always start on a 512 byte boundary. Doing this means you won't run into a multitrack read issue, or the DMA/64KiB issue – Michael Petch Sep 26 '22 at 06:52
  • I am 100% positive that BOCHs will not read across a DMA boundary (Any of the 64KiB addresses below 1MiB) with int 13h/AH=2, I'm not sure about QEMU(it may or may not). I know that Virtual Box doesn't care. Although sj95126 suggests using Int 13h/AH=42h that is usually not available on floppy media (or floppy emulated media). sj95126 suggesting to make sure you set SS:SP somewhere out of the area you are loading your kernel into is a very good idea. If you are loading the kernel at 0x0000:0x7e00 you could set the stack to 0x0000:0x7c00 to grow down from beneath the bootloader. – Michael Petch Sep 26 '22 at 07:15
  • I also have some code here that will loop through a kernel and read the required number sectors one at a time starting at 0x7e00. It includes a routine to convert between LBA (Logical block addresses) and CHS(Cylinder/Head/Sector): https://stackoverflow.com/a/54894586/3857942 . Lastly I have some other bootloader tips in this answer: https://stackoverflow.com/a/32705076/3857942 – Michael Petch Sep 26 '22 at 07:23

0 Answers0