You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

x86-16架构下INT 13h无法正确读取FAT12格式软盘上的内核文件

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)。

另外建议你加些调试输出,比如用INT 10h的AH=0Eh功能打印关键步骤的信息——比如找到根目录项后打印“Found kernel”,读取FAT后打印簇号,这样能一步步定位到哪一步出了问题。

备注:内容来源于stack exchange,提问作者Grigaror

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.17 07:37:59