简体   繁体   中英

DosBox boot MBR, wrong value in dl for int 13h

I have a custom MBR that I compile with NASM to a binary and I can boot it just fine in qemu and bochs.

I am trying to boot this MBR in DosBox using boot mbr.bin . This works fine as long as the MBR is tiny and does not call int 13h to read sectors from the disk.

If I try to read the next sector, it fails, resulting in a disk read error of some sort. I imagine this has to do with the value of dl not being set to the "boot drive". I've tried manually setting dl to 0 and to 80h, but neither work.

Does anyone know what the value of dl should be to make int 13h work in DosBox using the boot command? Or if there is perhaps some other way to obtain that value dynamically?

Edit; here is the initial code:

CPU 386
BITS 16
org 7C00h

; Calculate the full size of the code from start of segment $$ to the end label at the bottom (end - $$)
%define SECTORS_TO_LOAD ((end - $$) / 512) + ((end - $$) % 512 > 0) - 1

main:
    jmp 0x0000:setcs
    ; Some error messages
    disk_err db "Error reading disk", 0
    sector_err db "Error reading sector", 0

setcs:
    ; Base setup

    cld

    xor ax, ax      ; Set ES=DS=0 - this can be changed later for rep operations
    mov ds, ax
    mov es, ax

    mov ss, ax
    mov sp, 0x7c00

    ; Clear the screen
    mov ah, 0x07    ; Function 0x07: scroll window
    mov al, 0x00    ; Clear entire window
    mov bh, 0x07    ; White on black
    mov cx, 0x00    ; Specifies top left of screen as (0,0)
    mov dh, 0x18    ; 18h = 24 rows of chars
    mov dl, 0x4f    ; 4fh = 79 cols of chars
    int 0x10    ; Video interrupt


    ; Move cursor to position 0,0
    mov ah, 0x02    ; Function 0x02: set cursor position
    mov dh, 0x00    ; Row 0
    mov dl, 0x00    ; Col 0
    mov bh, 0x00    ; Page 0
    int 0x10    ; Video interrupt


    ; Load the calculated numbers of sector from the disk
    ; For this function call, dl should be set to the disk number to read from. The BIOS sets dl to
    ; the disk number of the MBR and dl was not changed, so we don't have to set it.

    ;mov dl, 0x80

    mov ax, SECTORS_TO_LOAD ; Number of sectors to read
    mov bx, next_sector ; The memory address to read to
    xor ch, ch      ; Cylinder 0
    mov cl, 0x02        ; Start at sector 2 (sector 1 is the first part of the MBR)
    xor dh, dh      ; Head 0
    mov ah, 0x02        ; Read mode

    int 0x13        ; Read interrupt
    jc .disk_error      ; Check carry bit for error

    cmp al, SECTORS_TO_LOAD ; The interrupt sets 'al' to the number of sectors actually read
    jne .sectors_error

    ; After a succesful load, the layout in memory will be the same as the layout in our ASM files,
    ; so we can jump to a defined label without worrying about offsets and exact addresses.
    jmp after_load

.disk_error:
    push disk_err   ; Print a disk error message
    call print
    cli     ; Halt all interrupts and operations
    hlt

.sectors_error:
    push sector_err ; Same as above, different message
    call print
    cli
    hlt


; The print function prints a string onto the screen in text mode
print:
    push bp     ; Basic stack setup
    mov bp, sp
    pusha       ; Push everything - this function doesn't
            ; return anything

    mov si, [bp+4]  ; Grab the pointer to the data
    mov bh, 0   ; Page 0
    mov bl, 0   ; Foreground color, irrelevant - in text mode
    mov ah, 0x0E    ; Function 0x0E: print character in TTY
.char:
    mov al, [si]    ; Get current char from pointer position
    inc si      ; Keep incrementing si until a null char
    or al, 0
    je .return
    int 0x10    ; Video interrupt
    jmp .char
.return:
    popa        ; Restore registers
    mov sp, bp  ; Restore stack
    pop bp
    ret 2       ; Remove param from stack on return

times 510-($-$$) db 0

; MBR signature
db 55h, 0AAh

next_sector:

After that, under next_sector, it has some incbins and some other code, including the label after_load .

The error I get is the first one; "Error reading disk", which displays fine. So it seems that es, ds, etc. are set up right.

Note the commented out mov dl, 0x80 - that was one of my attempts to get this working.

Getting error "BIOS:Disk 0 is not active" in asm program

DOSBox uses the image size to determine the disk geometry.

Pad the bin file to 1440*1024 bytes.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM