【发布时间】:2019-09-20 16:42:29
【问题描述】:
我有一些代码可以在实模式下从软盘加载第二个扇区,但是 int 0x13 失败并出现错误“找不到媒体类型”。这是为什么呢?
我尝试将柱面、磁头和扇区从 0、0 和 2 分别更改为 1、1 和 1,但无济于事(我不知道 CHS 寻址是使用 0 还是 1 开始)。我也多次重做这段代码以更好地组织它的功能,但无济于事。它失败但不打印我的错误字符串,这让我很困惑。它似乎总是因同样的错误而失败。
代码如下:
bits 16
org 0x7c00
start:
mov ax, cs
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0x7c00
mov si, msg
mov ah, 0x00
mov al, 0x03
int 0x10
call reset_disk
mov si, suc_reset
call puts
call load_stage2
mov si, suc_load
call puts
hlt
; routine to reset disk state
reset_disk:
xor ah, ah ; int 0x13 ah = 0x00
xor dl, dl ; drive 0
int 0x13
jc .error ; error if carry flag is set
ret
.error:
mov si, err_reset
call puts
hlt
; routine to load stage 2
load_stage2:
mov ah, 0x02 ; int 0x13 ah = 0x02 (read sectors)
mov al, 0x01 ; number of sectors to read
mov ch, 0x01 ; cylinder 0
mov cl, 0x02 ; sector 2
xor dh, dh ; head 0
xor dl, dl ; drive 0
mov bx, 0x9c00 ; address 9c00
mov es, bx
xor bx, bx ; 0x9c00:0x0000
int 0x13
or ah, ah
jnz .error
ret
.error:
mov si, err_load
call puts
hlt
; routine to print a string
puts:
mov ah, 0x0e ; int 0x10 ah = 0x0e (putchar)
.loop:
lodsb ; load string byte from si
or al, al ; check if al is zero
jz .end ; if zero jump to end (null terminator)
int 0x10 ; print character
jmp .loop ; loop
.end:
ret
err_reset: db "Failed to reset disk", 0x0a, 0x0d, 0
err_load: db "Failed to load stage 2", 0x0a, 0x0d, 0
suc_reset: db "Successfully reset disk 0...", 0x0a, 0x0d, 0
suc_load: db "Successfully loaded stage 2...", 0x0a, 0x0d, 0
msg: db "Test", 0
times 510-($-$$) db 0
dw 0xaa55
我希望输出是成功消息,但 EAX 也是零(表示成功)。
【问题讨论】:
-
如果跳过重置磁盘命令会发生什么?在流行操作系统的引导扇区代码中也没有重置磁盘调用。
-
@E.vanPutten 也不行。
-
你在什么样的模拟器(或真实硬件)上运行它?如果您是从 USB 启动,驱动器号可能不是 0,而是其他值。
-
@E.vanPutten 我在 macOS mojave 上使用 qemu-system-i386
-
如果你还在 qemu 中配置了一个硬盘,你可以从那个设备中读取一个扇区吗(DL 必须设置为 80 hex 而不是 00 hex 我想)?
标签: assembly x86 bootloader bios osdev