Int 13h/ah=2h无法读取超65扇区,QEMU运行重启求助
问题分析与解决
你遇到的是BIOS磁盘中断int 0x13(ah=0x2)的固有限制问题,直接读取超过63扇区会触发异常,原因和修复方案如下:
核心问题
- 寄存器容量限制:
al是8位寄存器,大部分传统BIOS中,用ah=0x2调用时,al最多能设置为63(部分BIOS允许al=0表示读取256扇区,但兼容性极差,QEMU默认模拟的老式BIOS不支持)。你设置成65已经超出了这个寄存器能承载的有效范围。 - CHS寻址限制:你固定使用柱面0、磁头0,而一个磁道的扇区数通常是63(老式硬盘的CHS规范),超过这个数量后,需要切换磁头或柱面,不能一直用同一组CHS参数。
- 缺少错误检查:
int 0x13执行失败时会设置CF标志位,但你的代码没有检查这个状态,失败后直接继续执行,导致系统崩溃重启。
修复方案
1. 分批次读取扇区
把超过63的扇区分成多次读取,每次读取不超过63扇区,同时更新CHS参数:
KERNEL_SIZE_SECTORS equ 65 CYLINDER_IDX equ 0 HEAD_IDX equ 0 SECTOR_IDX equ 2 copy_target equ 0x7e00 ; 假设bootloader在0x7c00,内核从0x7e00开始 boot: mov ax, 0 mov ds, ax mov es, ax ; 初始化段寄存器,确保内存寻址正确 mov di, KERNEL_SIZE_SECTORS ; 剩余待读取扇区数 mov bx, copy_target ; 当前内存写入地址 mov ch, CYLINDER_IDX mov dh, HEAD_IDX mov cl, SECTOR_IDX mov dl, [disk] read_loop: mov al, di cmp al, 63 jbe set_sector_count ; 剩余扇区≤63,直接读取 mov al, 63 ; 否则每次读取63扇区 set_sector_count: mov ah, 0x2 int 0x13 jc disk_error ; 检查CF标志,读取失败则跳转错误处理 sub di, al ; 更新剩余扇区数 add bx, al*512 ; 更新内存地址(每个扇区512字节) ; 更新CHS参数(按每磁道63扇区的规范) add cl, al cmp cl, 64 jl read_loop ; 扇区号未超63,继续循环 mov cl, 1 inc dh ; 切换磁头 cmp dh, 2 ; 假设为双面磁盘,磁头仅0和1 jl read_loop mov dh, 0 inc ch ; 切换柱面 jnz read_loop ; 读取完成,跳转到内核执行 jmp copy_target disk_error: ; 可添加错误提示逻辑,比如打印字符串 hlt jmp disk_error disk: db 0x80 ; 假设目标为第一块硬盘
2. 使用LBA寻址(推荐)
如果BIOS支持int 0x13的扩展功能(ah=0x42),可以直接使用LBA逻辑块寻址,不受CHS限制,能一次性读取更多扇区。需要先检测BIOS是否支持扩展功能,再构造LBA读取参数表。
额外注意事项
- 确保
copy_target的内存地址不会超出实模式下BIOS可访问的范围(通常是0x0000到0xFFFFF)。 - 必须正确设置段寄存器
es,因为bx是相对于es的偏移地址,未初始化es可能导致内存写入错误。
内容的提问来源于stack exchange,提问作者Yomada Cheezit
相关产品推荐
相关产品推荐

