将内核加载到0x8000时Bochs报错set_diskette_current_cyl(): drive>1求解答
问题
我正在开发一款32位操作系统,刚完成分页功能的实现。此前遇到GDT被覆盖的问题,通过将内核加载地址从0x1000改为0x8000解决了该问题,但现在Bochs出现报错:set_diskette_current_cyl(): drive > 1。我确认在调用int 0x13前已将dl寄存器设为0,希望有人解释该报错的原因。
完整Bochs日志如下:
00014693525i[BIOS ] Booting from 0000:7c00 00015876408i[FLOPPY] partial read() on floppy image returns 7/512 00015920854i[FLOPPY] read() on floppy image returns 0 00015965299i[FLOPPY] read() on floppy image returns 0 00016009745i[FLOPPY] read() on floppy image returns 0 00016054189i[FLOPPY] read() on floppy image returns 0 00016098634i[FLOPPY] read() on floppy image returns 0 00016166924p[BIOS ] >>PANIC<< set_diskette_current_cyl(): drive > 1 00016166924i[CPU0 ] CPU is in real mode (active) 00016166924i[CPU0 ] CS.mode = 16 bit 00016166924i[CPU0 ] SS.mode = 16 bit 00016166924i[CPU0 ] EFER = 0x00000000 00016166924i[CPU0 ] | EAX=0000040a EBX=0000cd4b ECX=00090200 EDX=00000402 00016166924i[CPU0 ] | ESP=00008f70 EBP=00008f74 ESI=000e0000 EDI=0000ffac 00016166924i[CPU0 ] | IOPL=0 id vip vif ac vm rf nt of df if tf sf ZF af PF cf 00016166924i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D 00016166924i[CPU0 ] | CS:f000( 0004| 0| 0) 000f0000 0000ffff 0 0 00016166924i[CPU0 ] | DS:f000( 0005| 0| 0) 000f0000 0000ffff 0 0 00016166924i[CPU0 ] | SS:0000( 0005| 0| 0) 00000000 0000ffff 0 0 00016166924i[CPU0 ] | ES:0000( 0005| 0| 0) 00000000 0000ffff 0 0 00016166924i[CPU0 ] | FS:0000( 0005| 0| 0) 00000000 0000ffff 0 0 00016166924i[CPU0 ] | GS:0000( 0005| 0| 0) 00000000 0000ffff 0 0 00016166924i[CPU0 ] | EIP=0000054b (0000054a) 00016166924i[CPU0 ] | CR0=0x60000010 CR2=0x00000000 00016166924i[CPU0 ] | CR3=0x00000000 CR4=0x00000000 00016166924i[CPU0 ] 0x000000000000054a>> out dx, al : EE 00016166924i[CMOS ] Last time is 1684823363 (Tue May 23 11:59:23 2023) 00016166924i[ ] restoring default signal behavior ======================================================================== Bochs is exiting with the following message: [BIOS ] set_diskette_current_cyl(): drive > 1 ======================================================================== 00016166924i[SIM ] quit_sim called with exit code 1
分析与解决思路
从Bochs日志的寄存器快照能明确看到,报错时EDX=00000402,dl作为EDX的低8位,实际值是0x02——这和你说的“设为0”不符,这就是报错的核心原因:BIOS软盘驱动仅支持驱动器编号0和1,当传递的驱动器号为0x02时,就触发了drive > 1的panic。
接下来需要排查dl值被修改的原因:
- 检查从设置dl到调用
int 0x13之间的所有代码,确认是否存在直接修改dl的指令(比如mov dl, xx、pop dx),或是调用了会破坏dl的函数/BIOS中断(部分BIOS中断会修改通用寄存器,包括dl); - 利用Bochs调试功能,在你设置dl的代码处加断点,单步执行每一条指令,观察dl值的变化节点,定位到修改它的代码;
- 考虑内核加载地址从0x1000改为0x8000后,内存布局变化导致的代码偏移错误——比如某些绝对地址引用的代码因加载地址改变,误操作了dl寄存器;
- 建议不要硬设dl为0,而是保留BIOS启动时传递的驱动器号(开机后BIOS会把启动介质的驱动器号存在dl里),硬设可能和实际启动环境不匹配,同时也可能在后续代码中被覆盖。
内容的提问来源于stack exchange,提问作者modlegend
相关产品推荐
相关产品推荐

