Bochs中第二阶段Bootloader无法加载问题排查(Brokenthorn教程)
搞定Bochs里FAT12软盘加载第二阶段Bootloader挂起的问题
嘿,我之前跟着Brokenthorn做OS开发时也踩过Bochs和VirtualBox兼容的坑,毕竟Bochs对细节的模拟可比VirtualBox严格多了。结合你的情况,我整理了几个大概率的故障点和排查步骤:
先从最可能的地方入手:磁盘读取的BIOS调用细节
VirtualBox可能会宽容一些小错误,但Bochs会把这些错误放大成挂起。你得检查:
- 有没有检查BIOS调用的返回错误? 调用
int 0x13读取扇区后,一定要看CF标志有没有置位。我之前就是没加错误处理,Bochs里读取失败直接跑飞了,VirtualBox却蒙混过去了。给你段参考代码:mov ah, 0x02 ; 读扇区功能 mov al, 0x05 ; 读5个扇区(根据你的第二阶段大小调整) ; ... 其他参数设置(CH=柱面号, CL=扇区号, DH=磁头号, DL=驱动器号, BX=缓冲区地址) int 0x13 jc disk_read_fail ; CF置位说明读取失败 disk_read_fail: mov si, err_msg call print_str hlt - FAT12簇转扇区的计算对不对? 比如你有没有正确读取引导扇区里的
BPB_SecPerClus、BPB_ResvdSecCnt这些参数?数据区的起始扇区计算是不是reserved_sectors + (num_fats * sectors_per_fat) + ((root_entries * 32) / bytes_per_sector)?Bochs对磁盘几何结构的模拟丝毫不差,算错一个扇区就会读垃圾数据。
然后看内存和跳转的问题
你把第二阶段加载到0x500,得确认:
- 跳转的时候有没有用远跳转? 实模式下如果CS寄存器不是0,近跳转
jmp 0x500实际会跳到CS*16 + 0x500的地址,这肯定不对!一定要用jmp 0x0000:0x0500这种远跳转,强制把CS设为0,IP设为0x500。我之前就是省了这一步,Bochs直接挂了,VirtualBox却神奇地跑起来了。 - 0x500地址有没有被第一阶段占用? 第一阶段从0x7c00开始,但执行过程中会不会往0x500写数据?比如你有没有把栈设到0x500以上?如果栈指针在0x500附近,执行第一阶段时可能会覆盖刚加载的第二阶段代码。
再检查Bochs配置和软盘镜像
- Bochs里的软盘设置对不对? 看你的配置文件,是不是把软盘类型设成了
1.44MB?镜像文件大小是不是刚好1474560字节(2880*512)?如果镜像大小不对,Bochs会读不到后面的扇区。 - 软盘镜像的创建步骤有没有错? 重新走一遍创建流程:
dd if=/dev/zero of=floppy.img bs=512 count=2880创建空镜像mkfs.fat -F 12 floppy.img格式化成FAT12(Ubuntu16.04的mkfs.fat支持这个参数,别记错了)- 挂载镜像,把第二阶段文件复制进去,然后正常卸载(直接拔挂载会损坏文件系统)
另外,Brokenthorn的第一阶段可能只支持读取连续簇的文件,你可以用fatls floppy.img看看第二阶段文件是不是连续的,如果是零散的,第一阶段读不全代码也会挂。
最后用Bochs调试器实锤问题
这是最有效的办法:
- 在Bochs配置里加
debugger: enabled=1,启动时进入调试器 - 在跳转指令前设断点:
b 0x7cXX(XX是你打印“跳转到第二阶段”之后的指令地址) - 执行到断点后,用
x /200x 0x500查看0x500开始的内存,如果是全0或者乱码,说明磁盘读取失败;如果是正确的机器码,那就是第二阶段代码本身的问题(比如没初始化栈、用了32位指令) - 看Bochs日志里的
int 0x13调用记录,找AH=0x02的条目,看返回的CF是0还是1,直接知道读取成功没。
如果排查完这些还是有问题,把你第一阶段里读取第二阶段的代码片段贴出来,我帮你抠细节~
内容的提问来源于stack exchange,提问作者snehm
相关产品推荐
相关产品推荐

