我正在编写MBR,并使用QEMU进行测试。
当使用将扇区读入内存(
什么可能会导致中断阻塞?我认为这只能通过
当使用将扇区读入内存(
int 0x13,ah = 0x02
)时,int
指令似乎会阻止程序的执行,并导致程序挂起。我已经使用各种打印语句进行了测试,以确认是这个特定的指令在阻塞。什么可能会导致中断阻塞?我认为这只能通过
cli
指令来完成,即使如此,它也不会阻止int
指令。
为了更好地理解,这是在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
这是带有阻塞中断的函数:
;;; 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
mov ax,cs mov ds,ax mov es,ax
。实际上,CS 可能没有一个零值。一些 BIOS 使用 CS=0x07C0:iP=0x0000 将控制传递给引导加载程序,这也是物理地址 0x07c00。由于您使用 ORG 0x7C00,因此您的代码假定 DS 和 ES 寄存器将为零。我会通过执行xor ax,ax mov ds,ax mov es,ax
明确地将它们设置为零。因此,我们不是将 CS 复制到 DS 和 _ES_,而是将 DS=ES=0。 - Michael Petch