16位操作系统开发:BIOS int 0x13(ah=2)第二次读扇区失败求助
问题分析与解决方案
核心错误:BIOS磁盘读取函数的CL寄存器参数设置错误
BIOS int 0x13 的 ah=0x2 函数对CL寄存器的格式有严格要求:
CL的低6位是扇区号(范围1-63)CL的高2位是柱面号的高2位- 柱面号的低8位存储在
CH寄存器中
你的代码中先将柱面号写入CL,随后又用扇区号覆盖了CL,完全丢失了柱面号的高2位信息(即使柱面号为0,也需要保证格式正确),这是第二次读取失败的直接原因。
错误码解读
int 0x13失败后,AH寄存器存储错误码,AL寄存器存储实际读取的扇区数。你提到的AX=0x2000对应AH=0x20、AL=0x00,错误码0x20表示磁盘控制器错误,这通常是由参数格式不正确引发的。
修正步骤
修复
CL寄存器的参数组装逻辑
替换原代码中设置CL、CH的部分,正确合并柱面号高2位与扇区号:; 原错误代码: ; mov cl, BYTE[LOADWITHLBACYLINDER] ; ; diskside ; mov dh, BYTE[LOADWITHLBAHEAD] ; ; sector ; mov cl, [LOADWITLBASECTOR] ; 修正后的代码: ; 柱面号低8位存入CH mov ch, BYTE[LOADWITHLBACYLINDER] ; 磁头号存入DH mov dh, BYTE[LOADWITHLBAHEAD] ; 扇区号存入CL低6位 mov cl, BYTE[LOADWITLBASECTOR] ; 将柱面号的高2位移入CL的高2位 mov al, BYTE[LOADWITHLBACYLINDER] shr al, 6 or cl, al移除无用的
clc指令int 0x13会根据执行结果自动设置进位标志,提前执行clc不会影响BIOS的返回结果,反而可能干扰错误判断,建议删除。验证参数一致性
确保第二次调用时,param_loadlba参数设置的是正确的LBA地址(对应CHS为柱面0、磁头0、扇区4),且param_loadlbabuffer指向的内存地址未被第一次读取的代码覆盖。
完整修正后的load_with_lba函数片段
load_with_lba: pusha mov ax, [param_loadlba] div BYTE[self_sectperside] mov BYTE[LODAWITHLBATEMP], al inc ah mov BYTE[LOADWITLBASECTOR], ah mov ah, 0 mov al, BYTE[LODAWITHLBATEMP] div BYTE[self_heads] mov BYTE[LOADWITHLBACYLINDER], al mov BYTE[LOADWITHLBAHEAD], ah ; 修正后的参数设置 mov dl, [start_drive] mov ch, BYTE[LOADWITHLBACYLINDER] mov dh, BYTE[LOADWITHLBAHEAD] mov cl, BYTE[LOADWITLBASECTOR] mov al, BYTE[LOADWITHLBACYLINDER] shr al, 6 or cl, al mov al, BYTE[param_loadlba_sectors] mov bx, 0 mov es, bx mov bx, WORD[param_loadlbabuffer] mov ah, 0x2 int 0x13 jnc NOERROR mov BYTE[error], FILEERROR NOERROR: mov BYTE[param_loadlba_sectors], 1 popa ret
额外建议
在QEMU中调试时,可以使用info registers命令查看寄存器状态,或使用x /16x 0x500检查内存加载情况,进一步验证参数和执行结果。
内容的提问来源于stack exchange,提问作者usernameisunavaible
相关产品推荐
相关产品推荐

