基于FAT12的自定义Bootloader无法加载第二阶段的问题排查
FAT12 Bootloader Stage2加载失败排查与修复
核心排查方向
1. Stage1磁盘读取逻辑的错误处理缺失
绝大多数加载失败的原因是忽略了int 0x13磁盘中断的返回状态,即使读取失败仍强行跳转至Stage2地址,导致执行空内存代码。
- 强制在每次
int 0x13调用后检查CF标志位:int 0x13 jc disk_read_failure ; CF置位则跳转到错误分支 - 在
disk_read_failure分支添加明确的屏幕输出(比如用int 0x10的0x0e功能打印错误字符),确认是否真的触发了读取失败:disk_read_failure: mov ah, 0x0e mov al, 'F' int 0x10 mov al, 'A' int 0x10 mov al, 'I' int 0x10 mov al, 'L' int 0x10 jmp $ ; 死循环等待
2. FAT12参数不匹配
Stage1代码中硬编码的BPB参数必须与镜像构建时的FAT12格式完全一致,否则会导致FAT表/根目录解析错误:
- 检查代码中的关键参数:
- 每扇区字节数(通常512)
- 每簇扇区数(通常1)
- FAT表个数(通常2)
- 根目录项数(通常224)
- 总扇区数(通常2880)
- 确认镜像构建时用
mkfs.fat -F 12的参数与代码一致,比如:mkfs.fat -F 12 -n "MYBOOT" -s 1 -r 224 -S 512 boot.img
3. Stage2加载地址与org伪指令不匹配
- 如果Stage2汇编代码开头用了
org 0x7e00,Stage1必须将Stage2加载到0x7e00起始的内存地址(Stage1占用0x7c00-0x7dff) - 跳转Stage2时必须确保CS:IP指向正确地址,实模式下建议用远跳转明确指定段地址:
jmp 0x0000:0x7e00 ; 假设DS=0,加载地址为0x7e00
4. 镜像构建脚本的正确性
- 确保Stage1被写入镜像的第一个扇区,且不会被后续操作覆盖:
dd if=stage1.bin of=boot.img bs=512 count=1 conv=notrunc - Stage2必须以8.3大写格式写入FAT12镜像,否则Stage1无法找到文件:
mcopy -i boot.img stage2.bin ::STAGE2.BIN - 确认镜像大小符合1.44MB软盘规格(2880个512字节扇区):
dd if=/dev/zero of=boot.img bs=512 count=2880
调试技巧
用QEMU+GDB单步调试定位问题:
- 启动QEMU并等待调试连接:
qemu-system-i386 -hda boot.img -s -S - 打开GDB连接调试端口:
gdb -ex "target remote localhost:1234" - 在Stage1的磁盘读取、FAT解析、跳转Stage2等关键位置设置断点,查看内存中是否正确加载了Stage2的机器码,以及寄存器状态是否符合预期。
内容的提问来源于stack exchange,提问作者Baptiste LEROYER
相关产品推荐
相关产品推荐

