![4fc94fd95b911a88e020180b5c0c9faa.png](https://img-blog.csdnimg.cn/img_convert/4fc94fd95b911a88e020180b5c0c9faa.png)
一、Fat12 文件格式
1. 格式简要说明
- Fat12是DOS支持的软盘格式。
- FAT全称是文件分配表(File Allocation Table),用来记录存放文件名、起始扇区等文件信息。
- 除了文件分配表,还有目录表(File Directory Table)。
- 软盘有两个磁头,每个磁头80个柱面(磁道),每个柱面有18个扇区,每个扇区512个字节空间
软盘结构:
![500d54fe4c3ff469c877a83298c2895b.png](https://img-blog.csdnimg.cn/img_convert/500d54fe4c3ff469c877a83298c2895b.png)
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每个表项的值指出文件存放的下一个扇区号
![cae9209f5ed403f0e33dfcb0595abf01.png](https://img-blog.csdnimg.cn/img_convert/cae9209f5ed403f0e33dfcb0595abf01.png)
![8a6c1d5d8e2ace85b9e9e695a3906ed0.png](https://img-blog.csdnimg.cn/img_convert/8a6c1d5d8e2ace85b9e9e695a3906ed0.png)
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_ org 0100h%else org 07c00h%endifCYLS EQU 10; 把软盘按Fat12格式填充 JMP init ; 跳转指令 DB 0x90 ; 空 DB,DD用来写单字节 DB "NotOneOS" ; 厂商名,8字节,DB用来写双字节 DW 512 ; 每个扇区大小512字节,DW用来写4字节 DB 1 ; 每个簇的扇区数 DW 1 ; Boot占的扇区 DB 2 ; 有2个FAT表 DW 224 ; 根目录大小224 DW 2880 ; 磁盘扇区总数 2880 DB 0xf0 ; 介质描述符,磁盘种类必须为0xf0 DW 9 ; 每个FAT扇区数 DW 18 ; 每个磁道18个扇区 DW 2 ; 2个磁头 DD 0 ; 隐藏扇区数 DD 2880 ; 同上,磁盘大小 DB 0, 0, 0x29 ; 0x29 扩展引用标记 DD 0xffffffff ; 无意义,固定这么写 DB "NotOneOS " ; 磁盘名(卷标),11字节 DB "FAT12 " ; 磁盘格式名,8字节 RESB 18 ; 空18个字节,填充0x00init: MOV AX,0 MOV SS,AX MOV SP,0x7c00 ; 堆栈空间,从0x7c00向前 MOV DS,AX MOV AX,0x0820 ; 把磁盘数据加载到内存0x0820处。 0x8000~0x81ff的512字节给启动区用的,所以从0x0820开始 MOV ES,AX ; 初始化磁盘接口 MOV CH,0 ; 柱面 0 MOV DH,0 ; 磁头 0 MOV CL,2 ; 扇区 2readloop: MOV SI,0 ; 记录失败次数retry: MOV AH,0x02 ; 0x02 读磁盘 MOV AL,1 ; 读1个扇区 MOV BX,0 MOV DL,0x00 ; A驱动器 INT 0x13 ; BIOS 读磁盘功能 JNC next ; 成功跳转 ADD SI,1 ; 失败加一次 CMP SI,5 ; 到5次就跳到error JAE error MOV AH,0x00 ; 复位磁盘功能 MOV DL,0x00 INT 0x13 ; 重置磁盘驱动器 JMP retry ; 重试 next: MOV AX,ES ; 内存地址向后移动0x0020 ADD AX,0x0020 MOV ES,AX ; 通过AX给ES加0x0020 ADD CL,1 ; 扇区+1 CMP CL,18 ; 有没有到18个扇区 JBE readloop ; CL<=18,就跳到 readloop MOV CL,1 ADD DH,1 CMP DH,2 JB readloop ; 如果 DH < 2 ,则跳到readloop MOV DH,0 ADD CH,1 CMP CH,CYLS JB readloop ; 如果CH
三、 文件读写
使用BIOS中断 int 13h,参数:
![9f78b8fec51e3eb8c0e62c66fb7adf4f.png](https://img-blog.csdnimg.cn/img_convert/9f78b8fec51e3eb8c0e62c66fb7adf4f.png)
知道扇区号的时候,要计算int 13h的参数:
设扇区号/每磁道扇区数(18) = 商 Q,余数R ,则:
- 柱面号= Q >> 1 (相当于 Q/2 无余数)
- 磁头号=Q & 1
- 起始扇区号=R+1
四、读磁盘镜像并写入文件,查看文件格式
下面使用VirtualBox读入磁盘镜像,并写入一个文件。(新建虚拟机并加虚拟磁盘的方法前面章节有提到。)
![201b1ba9c878118b6da07ef64f7803b0.png](https://img-blog.csdnimg.cn/img_convert/201b1ba9c878118b6da07ef64f7803b0.png)
使用VsCode打开磁盘镜像,可以看到存储区域已经有了变化:
![e820bef4664f2c06cebfd05f584c1c6f.png](https://img-blog.csdnimg.cn/img_convert/e820bef4664f2c06cebfd05f584c1c6f.png)
这里使用的是笨方法保存文件,也可以使用edimg.exe程序来做。
- 文件名保存到 0x002600处
- 文件的内容存在 0x40200处
后面章节来看如何让程序加载NotOneOS.sys里的代码。
本章代码与编译运行方法已放到gitee:
gitee.com/xundh/learn-os