You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Int 0x13在真实硬件无报错失效,QEMU中正常的内核加载问题

真实硬件与QEMU下引导加载程序磁盘加载差异问题

问题现象

编写的16位引导加载程序在QEMU中运行正常,能正确加载内核数据;但在真实硬件上执行时,内核加载逻辑未写入预期数据到0x2000地址,即使注释掉call load_disk,该地址仍显示固定值0x519B,最终导致call KERNEL_OFFSET执行失败。

QEMU运行输出

Kernel Successfully Loaded
0x2000 (the Kernel offset)
0xC6BB (what is stored at 0x2000)
0x0080 (the drive)

真实硬件运行输出

Kernel Successfully Loaded
0x2000 (the Kernel offset)
0x519B (what is stored at 0x2000)
0x0080 (the drive)

引导加载程序主代码

; Set offsets
[org 0x7c00]
KERNEL_OFFSET equ 0x2000

[bits 16]

; Setup Stack
mov bp, 0x1000
mov sp, bp

mov bx, RM_BOOT_MSG
call print_rm
call nl_rm

; Load kernel
mov bx, KERNEL_OFFSET  ; Read from disk and store in KERNEL_OFFSET
mov dh, 10             ; Read X sectors
call load_disk

mov bx, KERNEL_LOAD_MSG
call print_rm
call nl_rm

mov bx, KERNEL_OFFSET
call print_rm_hex
call nl_rm

mov bx, [KERNEL_OFFSET]
call print_rm_hex
call nl_rm

mov bh, 0
mov bl, dl
call print_rm_hex
call nl_rm

call KERNEL_OFFSET    ; Begin entering kernel

jmp $

%include "boot/disk.asm"
%include "boot/32b_gdt.asm"

RM_BOOT_MSG: dw "16-bit RM", 0
KERNEL_LOAD_MSG: dw "Kernel Successfully Loaded", 0

; Padding
times 510 - ($ - $$) db 0
dw 0xaa55

磁盘加载函数代码

; Disk
; INT 0x13 0x02 功能说明
; AH = 02
; AL = 读取扇区数 (1-128 十进制)
; CH = 磁道/柱面号 (0-1023 十进制)
; CL = 扇区号 (1-17 十进制)
; DH = 磁头号 (0-15 十进制)
; DL = 驱动器号 (0=A盘, 1=第二个软盘, 80h=主硬盘, 81h=从硬盘)
; ES:BX = 缓冲区指针

; 返回值:
;   AH = 状态码
;   AL = 实际读取扇区数
;   CF = 0表示成功, 1表示错误

; 注: 0x01是引导扇区, 0x02是第一个可用扇区

[bits 16]

; 将驱动器dl上的dh个扇区读取到es:bx指向的位置
load_disk:
    pusha
    push dx

    mov ah, 0x02

    mov al, dh

    mov ch, 0x00

    mov cl, 0x02

    mov dh, 0x00

    int 0x13
    jc .disk_error

    pop dx
    cmp al, dh
    jne .sector_error
    
    popa
    ret

    .disk_error:
        mov bx, DISK_ERR_MSG
        call print_rm

        mov dh, ah
        call print_rm_hex
        call nl_rm

        jmp .fail_loop

    .sector_error:
        mov bx, SECTOR_ERR_MSG
        call print_rm
        call nl_rm

    .fail_loop:
        jmp $

DISK_ERR_MSG: dw "Error loading from disk: ", 0
SECTOR_ERR_MSG: dw "Incorrect number of sectors read", 0

%include "boot/print_rm.asm"

QEMU运行命令

qemu-system-i386 -s -usb -drive format=raw, file=\\.\PHYSICALDRIVE2

解决建议

  • 显式设置ES寄存器:当前代码仅指定BX为KERNEL_OFFSET,但ES默认值在真实硬件与QEMU中可能不同,导致实际写入地址不是预期的0x0000:0x2000。调用load_disk前添加:
    mov ax, 0x0000
    mov es, ax
    
  • 添加磁盘读取重试逻辑:真实硬件磁盘读取可能出现偶发错误,INT 0x13返回错误时可重试3-5次,而非直接进入死循环。
  • 调整内核加载地址:0x2000地址在真实硬件中可能被BIOS初始化或占用,尝试将KERNEL_OFFSET改为更高地址(如0x10000)。
  • 验证磁盘镜像写入完整性:确保写入到物理磁盘的镜像包含正确内核数据,真实硬件对磁盘扇区对齐、写入方式要求更严格,可重新写入并校验。
  • 减少单次读取扇区数:部分真实硬件不支持CHS模式下一次性读取10个扇区,先尝试读取1个扇区测试,确认正常后再逐步增加。

内容的提问来源于stack exchange,提问作者MichaelT572

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 18:35:21