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

0x0000:0x7000是否为不安全内核加载地址?还是QEMU导致异常?

问题描述

我正在开发一款运行于软盘、基于FAT12分区的类DOS系统,用于加载用户程序与驱动。遇到以下异常现象:

  • 最初尝试通过int 13h, 02h将11字节测试内核加载到0x0000:0x7000时,CF标志位被置位,但AH寄存器返回无错误码;
  • 将加载地址更换为0x0000:0x0600后,磁盘读取成功;
  • 手动设置DL寄存器指定启动盘号后,又可正常将内核加载到0x0000:0x7000。

我使用qemu-system-i386进行测试,原本认为0x7000地址及附近区域是安全的,对上述现象感到困惑,寻求原因。

MBR代码
[bits 16]
org 0x7C00

; macros
%include "../include/misc.inc"

jmp 0x0000:start

; notice: perserve the boot drive in dl so the kernel can save it

start:
    cli

    xor ax, ax ; cs
    mov ds, ax
    mov es, ax

    mov ss, ax
    mov sp, 0x8000

    sti

    ; set video mode
    mov al, 0x13
    int 0x10

    ; load kernel into 0x0000:0x7000 from floppy 
    mov bx, 0x7000
    mov ah, 0x02
    
        mov al, 1
        xor ch, ch ; 0
        mov cl, 2
        xor dh, dh ; 0
        ; drive number (DL)

    int 0x13

    jc disk_error

    jmp 0x0000:0x7000

disk_error: ; error handling for int 13,2h failure

    xor ah, ah
    mov al, 0x03
    int 0x10

    mov ah, 0x0E
    mov si, disk_error_message

    mov cl, 17
    .log_error:
        mov al, [si]
        int 0x10
        inc si

    loop cl, .log_error

    hlt

; Variables

disk_error_message: db "Disk read failure"

times 510 - ($ - $$) db 0
db 0x55, 0xAA ; boot signature
软盘构建命令
make -C src/boot/
make[1]: Entering directory '/home/mekebabman/Desktop/Simple16/src/boot'
nasm -f bin mbr.nasm -o ../../build/mbr.bin
make[1]: Leaving directory '/home/mekebabman/Desktop/Simple16/src/boot'
dd if=/dev/zero of=build/img/S16-0.0-floppy.img bs=512 count=2880 conv=notrunc
2880+0 records in
2880+0 records out
1474560 bytes (1.5 MB, 1.4 MiB) copied, 0.0301179 s, 49.0 MB/s
dd if=build/mbr.bin of=build/img/S16-0.0-floppy.img bs=512 seek=0 count=1 conv=notrunc
1+0 records in
1+0 records out
512 bytes copied, 0.000161682 s, 3.2 MB/s
dd if=build/kernel/main.bin of=build/img/S16-0.0-floppy.img bs=512 seek=1 conv=notrunc
0+1 records in
0+1 records out
11 bytes copied, 0.00014582 s, 75.4 kB/s
QEMU启动命令
qemu-system-i386 -drive file=$<,format=raw,if=floppy -boot order=a
测试内核代码
[bits 16]
org 0x7000

; macros
%include "../include/misc.inc"

kstart:
    cli

    ; Segments are already 0x0000
    ; xor ax, ax
    ; mov ds, ax
    ; mov es, ax

    ; mov sp, ax
    mov sp, 0x7400 ; 1kib stack (IGNORE THIS! RANDOM POSITION I PICKED)

    mov byte [boot_drive], dl

    sti

    hlt

; variables

boot_drive: db 0
loop宏定义
dec <reg>
jnz <address>
问题原因分析
  1. DL寄存器被意外修改:BIOS启动MBR时会将启动盘号存入DL寄存器,但你的代码中调用int 10h设置视频模式(al=0x13)后,没有保存和恢复DL的值。部分BIOS的int 10h功能会修改DL寄存器,导致后续调用int 13h,02h时使用了错误的驱动器号,触发磁盘读取失败(CF置位)。而手动设置DL时,强制指定了正确的启动盘号,因此读取成功。
  2. 地址0x7000本身无问题:0x0000:0x7000位于MBR加载地址0x7C00下方,栈设置在0x8000向下生长,该区域不会被MBR或栈覆盖,是安全的内存区域。更换到0x0600能成功属于巧合,本质是此时BIOS的错误驱动器读取行为未触发CF置位(或存在BIOS兼容问题),但核心问题仍在于DL寄存器的正确性。

解决方案:在调用int 10h前保存DL的值(例如存入内存或其他寄存器),调用完成后恢复DL,确保int 13h使用正确的驱动器号。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 09:34:56