x86-16架构下INT 13h无法正确读取FAT12格式软盘上的内核文件
我太懂你现在的糟心感受了——明明调用INT 13h读扇区时没触发错误(CF位没置位),但内核该加载到的内存区域全是0,这种“看起来成功但结果全错”的问题最磨人。结合你贴出的FAT12 MBR代码片段,我梳理了几个最可能的排查方向:
文件名匹配的细节坑
FAT12根目录里的文件名是严格的8.3大写格式,短文件名不足8位会用空格填充,扩展名固定3位。比如你的内核文件叫KERNEL.BIN,根目录项里实际存的是KERNEL BIN(注意文件名和扩展名之间的空格)。如果你的代码里查找文件名时大小写不对、格式没对齐,或者filenameLength的处理逻辑有问题,就会找到错误的目录项,读出来自然是无效的空数据。FAT/根目录的扇区计算错误
从你的宏定义看,fatLocation设为0x7E00、rootdirLocation设为0x9000,得先核对这些地址对应的扇区是否正确:- 根目录起始扇区 = 保留扇区数 + FAT数量 × 每个FAT的扇区数 = 1 + 2×9 = 19
- 根目录占用扇区数 = (根目录项数 × 单条目大小) / 每扇区字节数 = (224×32)/512 = 14扇区
- 数据区起始扇区 = 根目录起始扇区 + 根目录扇区数 = 19+14=33
如果代码里这些关键数值的计算出错,比如根目录没读到正确位置,后续找内核文件的簇号就会完全错误,读出来的内容自然全是0。
INT 13h的CHS参数转换错误
INT 13h的AH=02h读扇区功能,对CHS(柱面/磁头/扇区)参数的要求很严格,很多新手栽在逻辑扇区号(LBA)转CHS的步骤上:; 示例:把逻辑扇区号LBA转换成CHS参数 mov ax, lba_sector ; lba_sector是要读取的逻辑扇区号 xor dx, dx div word [bpb_sectorsPerTrack] ; AX=磁道号,DX=扇区号-1 inc dx ; 扇区号从1开始计数 mov cl, dl ; CL=扇区号(低6位) xor dx, dx div word [bpb_headCount] ; AX=柱面号,DX=磁头号 mov ch, al ; CH=柱面号低8位 mov dh, dl ; DH=磁头号 mov dl, [ebr_driveNumber] ; DL=驱动器号(软盘一般是0x00或0x01)如果这一步转换错了,BIOS可能不会触发CF错误(毕竟它确实读了某个扇区),但读出来的完全是无关扇区的内容,大概率就是全0。
内存地址重叠问题
你的MBR加载在0x7C00,fatLocation在0x7E00、rootdirLocation在0x9000、kernelLocation在0x9E00。要确保这些地址之间没有重叠,尤其是加载大内核时,不要因为连续读簇覆盖了之前存在内存里的FAT表或根目录数据——要是FAT表被覆盖,后续读取下一个簇时就会拿到错误的地址,读出来自然是空的。FAT簇号的链式解析错误
FAT12的簇号是12位的,读取下一个簇号时要注意字节对齐:- 簇号N对应的FAT偏移是
N×3/2 - 如果N是偶数,取16位值的低12位;如果是奇数,取16位值的高12位
要是这部分解析逻辑写错了,就会拿到错误的下一个簇地址,甚至读到空簇(内容全0)。
- 簇号N对应的FAT偏移是
另外建议你加些调试输出,比如用INT 10h的AH=0Eh功能打印关键步骤的信息——比如找到根目录项后打印“Found kernel”,读取FAT后打印簇号,这样能一步步定位到哪一步出了问题。
备注:内容来源于stack exchange,提问作者Grigaror

