I am writing a MBR and using QEMU for testing.
When using read sectors into memory (int 0x13, ah=0x02
), the int
instruction seems to block execution of my program, and it proceeds to hang. I have tested this with various print statements to confirm that it is this particular instruction blocking.
What could make the interrupt block? I thought this could only be done with the cli
instruction, and even then it does not block int
instructions.
For context, this is the code leading up to the blocking interrupt in read_sectors_16
:
[bits 16]
[ORG 0x7C00]
jmp 0x000:start_16 ; ensure cs == 0x0000
reset_failure_str db 'error: boot disk reset', 13, 10, 0
read_failure_str db 'error: boot disk read', 13, 10, 0
boot_segaddr dw 0x7E00
read_attempt_str db 'read attempt', 13, 10, 0
end_read_attempt_str db 'end read attempt', 13, 10, 0
start_16:
;; Initialize segment registers
mov ax, cs
mov ds, ax
mov es, ax
jmp load_bootsector_2
load_bootsector_2: ; Read program from disk
;; dl set by BIOS to the drive number MBR was loaded from
mov cx, 0x0002 ; cylinder 0, sector 2
xor dh, dh ; head 0
mov al, 0x01 ; load 1 sector
mov bx, boot_segaddr ; destination - load right after the boot loader
call read_sectors_16
jnc .success
mov si, read_failure_str
call print_string_16
jmp halt ; halt
.success:
jmp boot_segaddr:0000 ; jump to program
And here is the function with the blocking interrupt:
;;; read_sectors_16
;;;
;;; Read sectors from disk in memory using BIOS services
;;;
;;; input: dl = drive
;;; ch = cylinder[7:0]
;;; cl[7:6] = cylinder[9:8]
;;; dh = head
;;; cl[5:0] = sector (1-63)
;;; es:bx -> destination
;;; al = number of sectors
;;;
;;; output: cf (0 = success, 1 = failure)
read_sectors_16:
pusha
mov di, 0x02 ; set attempts (max attempts - 1)
.attempt:
mov ah, 0x02 ; read sectors into memory (int 0x13, ah = 0x02)
int 0x13 ; TODO: this call is not returning!
jnc .end ; exit if read succeeded
dec di ; record attempt
test di, di
jz .end ; end if no more attempts
xor ah, ah ; reset disk (int 0x13, ah = 0x00)
int 0x13
jnc .attempt ; retry if reset succeeded, otherwise exit
jmp .end
.end:
popa
ret