0

I have been working on a small (real mode) boot code recently and I have been running into some problems with int 0x13. At first I was trying to use 'int 0x13, ah= 0x02' to simply load more code into RAM just after the boot sector. That output error code ah=0x01 (invalid command), so I tried 'int 0x13, ah= 0x41' to try to find out whether int 0x13 was even working. I tried this on qemu, my dell latitude E7240, my ancient desktop with an Intel DQ965GF motherboard and a Q6600 CPU, and an assortment of other more modern x86 computers. Of course qemu worked, but the only real computer that worked was the DQ965GF desktop, all the other computers output error code ah=0x01 (invalid command). Any help would be greatly appreciated! Thanks! Here is the code that errors:

Yes I did remember to define a partition table and the magic boot number, and yes I'm positive that 'printHex' works. I used that for debugging.

      [org 0x7c00]
      [bits 16]

      jmp start

      bootDrive db 0


      start:

            mov [bootDrive], dl     ; Stores the drive # in bootDrive

            ; Inits all relevant registers------------------------------------------
            xor si, si
            xor di, di

            mov ax, 0x7c00
            mov bp, ax              ; Set bp (base pointer) for our stack
            mov sp, ax              ; Set sp (stack pointer) equal to the bp

            mov ax, 0x0000
            mov ss, ax              ; Set ss (stack segment) to zero
            mov ds, ax              ; Set ds (data segment) to zero
            mov es, ax
            ; Inits all relevant registers------------------------------------------


            ; Boot code goes here---------------------------------------------------
            mov ax, 0x0000          ; int 10/ah= 0x00 -> set video mode (clear screen)
            int 0x10

            mov ah, 0x41
            mov dl, [bootDrive]
            mov bx, 0x55AA
            int 0x13                ; Check extentions present
            jc .errMain             ; If theres an error

            mov dx, cx              ; Print Extensions
            call printHex
            jmp .done

            .errMain:
              mov dx, ax            ; Print Error Code
              call printHex
            .done:

      jmp $
1201ProgramAlarm
  • 32,384
  • 7
  • 42
  • 56
  • 2
    One immediate problem that may or may not be the cause is that you did `mov [bootDrive], dl` **before** you set up `ds`. – Jester May 04 '19 at 00:02
  • It would help if you show your complete code. You suggest you had a partition table, and I'm unsure if you have other code you aren't showing. Maybe print_hex has a problem but you haven't noticed the bug? @Jester is right about bootDrive, but if you are booting on real hardware and using USB with FDD emulation you may actually need a BPB. https://stackoverflow.com/a/47320115/3857942 . You really should set SP right after you set SS or at least turn off interrupts around the code to set up the segment registers and SP. – Michael Petch May 04 '19 at 01:52
  • Knowing how you are booting on the different equipment may give some clues. – Michael Petch May 04 '19 at 01:55
  • Function `ah=0x41` is not supported for all drives but typically only for hard disks. Older BIOSs don't support functions `0x41` and above at all. If `dl` contains the drive number of a drive not supporting function `0x41`, an output of `ah=1` is normal. And in your case `dl` seems to be 0, which is a floppy drive and not a hard disk. Function `ah=0x41` not working is **not** an indication that `int 0x13` does not work correctly. – Martin Rosenau May 04 '19 at 04:46
  • 1
    Interrupts are disabled for the instruction immediately following a `mov ss,` instruction, so you should put your `mov sp` instruction right after the `mov ss` one. Otherwise you'll need to disable interrupts before you start changing the stack, and enable them at some point after the stack is fully set up. (Or you can use the `LSS` instruction.) – 1201ProgramAlarm May 04 '19 at 18:14
  • @1201ProgramAlarm : Although hat you say is generally true there are some exceptions. If there is any chance the bootloader is going to run on ancient CPUs there is a chance of running into a defective 8088 that didn't disable interrupts after changing SS until the end of the enxt instruction (old bootloaders would surround updating SS and SP with CLI/HLT as a precaution. If there is no chance of running into those chips then setting SS followed by setting SP in the next instruction is preferred (I actually brought up SS:SP above in my earlier comment) – Michael Petch May 04 '19 at 18:34
  • 1
    LSS is probably a bad idea on universal bootloaders. LSS (and LGS/LFS) were instructions that didn't show up until the 80386. I'd say using an 80386 instructions early on in a bootloader is probably not the best idea unless you are coding something where the minimum requirement is a 80386+ – Michael Petch May 04 '19 at 18:36
  • @MichaelPetch It's been so long since I've worked with those I forget about those early problems. – 1201ProgramAlarm May 04 '19 at 18:45
  • Where I said CLI/HLT I meant CLI/STI lol – Michael Petch May 04 '19 at 18:46
  • Wow, that was very helpful, turns out it was just an issue that I didn't set the segments before 'mov [bootDrive], dl', but thanks for all the additional suggestions. The code now works on all of my real computers. – Clay Kress May 04 '19 at 22:15
  • @ClayKress: Note that if this is for partitioned disks; then your boot loader belongs in a partition and not in the MBR (code in the MBR chain-loads the selected/active operating system's boot sector). MBR code will also give you an extra parameter (address of your partition's entry in partition table in `DS:SI`) to help. See https://en.wikipedia.org/wiki/Master_boot_record#MBR_to_VBR_interface for more info. – Brendan May 05 '19 at 02:23

0 Answers0