操作系统学习 让启动镜像支持Fat12文件格式


操作系统学习 让启动镜像支持Fat12文件格式

文章插图
 
一、Fat12 文件格式1. 格式简要说明
  • Fat12是DOS支持的软盘格式 。
  • FAT全称是文件分配表(File Allocation Table) , 用来记录存放文件名、起始扇区等文件信息 。
  • 除了文件分配表 , 还有目录表(File Directory Table) 。
  • 软盘有两个磁头 , 每个磁头80个柱面(磁道) , 每个柱面有18个扇区 , 每个扇区512个字节空间
软盘结构:
操作系统学习 让启动镜像支持Fat12文件格式

文章插图
 
2. 引导扇区简写格式
  • 面:C
  • 磁道:H
  • 扇区:S(每道18个扇区)
C0-H0-S1用来存放引导区 , 如果最后两个字节是0x55,0xaa(DW 0xAA55) , BIOS就把这512字节读出来执行 。
3. FAT
  • C0-H0-S2~C0-H0-S10(9个扇区) 存放 FAT表
  • C0-H0-S11~C1-H0-S1(9个扇区) 存放备用FAT表
  • C1-H0-S2~ C1-H0-S15(14个扇区)用于存放FDT(根目录)
4. FAT结构
  • FAT12的每个文件分配表项占12bit ,  每个表项代表一个扇区 。
  • 磁盘里所有扇区被线性索引(LBA)
  • FAT12每个表项的值指出文件存放的下一个扇区号

操作系统学习 让启动镜像支持Fat12文件格式

文章插图
 

操作系统学习 让启动镜像支持Fat12文件格式

文章插图
 
5. 根目录
  • 根目录紧跟着FAT表 , 从19分区开始 。
  • 根目录由若干个目录条目组成 , 最多有BPB_RootEntCnt个 。
  • 根目录中每个条目占32字节:
名称开始字节长度内容DIR_Name00xB文件名8字节 , 扩展名3字节DIR_Attr0xB1文件属性保留位0xC10保留DIR_WrtTime0x162最后一次写入的时间DIR_WrtDate0x182最后一次写入的日期DIR_FstClus0x1A2此文件在数据区和FAT表中的开始簇号DIR_FileSize0x1C4文件大小
6. 数据区二、Fat12格式的引导区代码:;%define _BOOT_DEBUG_; 做Boot Sector时把这行注释掉; 启用这行就用nasm Boot.asm -o Boot.com生成.com文件用于调试%ifdef _BOOT_DEBUG_org0100h%elseorg 07c00h%endifCYLS EQU 10; 把软盘按Fat12格式填充JMP init; 跳转指令DB0x90; 空 DB , DD用来写单字节DB"NotOneOS"; 厂商名 , 8字节 , DB用来写双字节DW512; 每个扇区大小512字节 , DW用来写4字节DB1; 每个簇的扇区数DW1; Boot占的扇区DB2; 有2个FAT表DW224; 根目录大小224DW2880; 磁盘扇区总数 2880DB0xf0; 介质描述符 , 磁盘种类必须为0xf0DW9; 每个FAT扇区数DW18; 每个磁道18个扇区DW2; 2个磁头DD0; 隐藏扇区数DD2880; 同上 , 磁盘大小DB0, 0, 0x29; 0x29 扩展引用标记DD0xffffffff; 无意义 , 固定这么写DB"NotOneOS"; 磁盘名(卷标) , 11字节DB"FAT12"; 磁盘格式名 , 8字节RESB18; 空18个字节 , 填充0x00init:MOV AX,0MOV SS,AXMOV SP,0x7c00; 堆栈空间 , 从0x7c00向前MOV DS,AXMOV AX,0x0820; 把磁盘数据加载到内存0x0820处 。0x8000~0x81ff的512字节给启动区用的 , 所以从0x0820开始MOV ES,AX; 初始化磁盘接口MOV CH,0; 柱面 0MOV DH,0; 磁头 0MOV CL,2; 扇区 2readloop:MOV SI,0; 记录失败次数retry:MOVAH,0x02; 0x02 读磁盘MOVAL,1; 读1个扇区MOVBX,0MOVDL,0x00; A驱动器INT0x13; BIOS 读磁盘功能JNCnext; 成功跳转ADDSI,1; 失败加一次CMPSI,5; 到5次就跳到errorJAEerrorMOVAH,0x00; 复位磁盘功能MOVDL,0x00INT0x13; 重置磁盘驱动器JMPretry; 重试next:MOVAX,ES; 内存地址向后移动0x0020ADDAX,0x0020MOVES,AX; 通过AX给ES加0x0020ADDCL,1; 扇区+1CMPCL,18; 有没有到18个扇区JBEreadloop; CL<=18,就跳到 readloopMOVCL,1ADDDH,1CMPDH,2JBreadloop; 如果 DH < 2  , 则跳到readloopMOVDH,0ADDCH,1CMPCH,CYLSJBreadloop; 如果CH<CYLS  ,  则跳到readloopJMPsuccessprint:MOVAL, [SI]ADDSI, 1CMPAL, 0JEendMOVAH, 0x0eMOVBX, 15INT0x10JMPprintend:HLTJMP end; 无限循环error:; 打印错误信息MOV SI, error_msgJMP printsuccess:MOV SI, success_msgJMP printBootMessage:DB "Hello, MY OS!"; 想要开机后在屏幕上显示的字符串DB 0success_msg:DB "Success"; 成功DB 0error_msg:DB "Error"; 失败DB 0times510-($-$$) db 0 ; 填充剩下的空间 , 使生成的二进制代码恰好为512字节 $$表示一个section的开始处汇编后地址DW0xaa55; 结束标志; 继续按Fat12填充磁盘剩余空间DB0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00RESB4600DB0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00RESB1469432三、 文件读写使用BIOS中断 int 13h , 参数:


推荐阅读