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

自制Bootloader遇qemu-system-i386 CPU概率性复位,Bochs无此问题原因

问题

自行编写Bootloader时,在qemu-system-i386中CPU会出现概率性复位,但Bochs模拟器无此问题,请问原因是什么?

相关代码如下:

mbr.s

%include "boot.inc"

SECTION MBR vstart=0x7c00         
   ...
   call rd_disk_m_16 ; rd_disk_m_16 工作正常
  
   jmp LOADER_BASE_ADDR
   ...
   db 0x55,0xaa

loader.s

%include "boot.inc"
section loader vstart=LOADER_BASE_ADDR
LOADER_STACK_TOP equ LOADER_BASE_ADDR
jmp loader_start
...
loader_start:

   cli
   lgdt [gdt_ptr]

   mov eax, cr0
   or eax, 0x00000001
   mov cr0, eax

   jmp  0x08:p_mode_start

[bits 32]
p_mode_start:
   jmp $

操作步骤:

# 创建硬盘镜像
bximage -func=create -hd=16M -imgmode="flat" -sectsize=512 -q hd.img
# 编译并写入MBR
nasm -I include/ -o mbr.bin mbr.s && dd if=mbr.bin of=./hd.img bs=512 count=1  conv=notrunc
# 编译并写入Loader
nasm -I include/ -o loader.bin loader.s && dd if=loader.bin of=./hd.img bs=512 count=4 seek=2 conv=notrunc
# 启动QEMU并调试复位与中断
qemu-system-i386 -hda hd.img -d cpu_reset,int -no-reboot
原因分析与解决思路

这种跨模拟器的差异,核心原因是QEMU对x86硬件规范的校验更严格,而Bochs的兼容性容错性更强。结合你的代码和操作流程,可能的触发点有这些:

  • GDT配置不规范
    lgdt [gdt_ptr] 加载的全局描述符表如果存在对齐错误(比如GDT基地址未按8字节对齐),或者表项的段权限、属性位不符合x86标准,QEMU会直接触发CPU复位,而Bochs会忽略这类非致命错误。检查gdt_ptr对应的GDT结构,确保基地址是8字节对齐,段限长、类型位等参数配置正确。

  • 保护模式切换前状态未清理彻底
    切换保护模式时,除了执行cli关闭可屏蔽中断,还需要:

    1. 禁用NMI(不可屏蔽中断):部分场景下NMI会干扰模式切换,QEMU会严格模拟这种触发复位的情况,而Bochs不会。可在cli后添加代码:in al, 0x70; or al, 0x80; out 0x70, al来禁用NMI。
    2. 确保段寄存器有效性:切换保护模式后,DS、ES等段寄存器仍保留实模式下的段值,QEMU会因非法段状态触发复位,Bochs则会容错。建议在远跳转前先将段寄存器设置为合法的保护模式选择子。
  • Loader加载不完整
    你用dd写入Loader时指定count=4(即4个扇区2048字节),如果loader.bin实际编译后大小超过这个值,会导致部分代码未被加载到内存,QEMU执行到非法内存区域时触发复位;而Bochs会将未初始化的内存填充0,刚好不会触发错误。可以用ls -l loader.bin查看实际大小,调整dd的count参数。

  • 磁盘读取时序不规范
    rd_disk_m_16函数如果没有严格等待磁盘就绪就发送命令,QEMU的磁盘模拟会返回错误状态,导致加载的Loader代码损坏,概率性触发复位;Bochs的磁盘模拟对时序要求宽松,不会出现这类问题。建议在磁盘操作的每一步添加等待逻辑:

    wait_disk_ready:
        in al, 0x1f7
        test al, 0x80
        jnz wait_disk_ready
    
  • 模式切换的指令时序问题
    修改CR0开启保护模式后,紧接着的远跳转是必须的,但如果指令预取存在一致性问题,QEMU会触发复位。可以在mov cr0, eax后添加一到两个nop指令,再执行远跳转,避免时序冲突。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 09:47:03