引导扇区的信息例如以下:
1. 偏移地址00H,长度3,内容:EB 3C 90 跳转指令。
2. 偏移地址03H,长度8。内容:4D 53 44 4F 53 35 2E 30 为厂商标志和os 版本号号,这里是MSDOS5.0。
3. 偏移地址0BH,长度2,内容:00 02。
注意这里数据的布局,高地址放高字节,低地址放低字节(数据为小端格式组织),所以数据应该是0200,即512。表示的意思是,该磁盘每一个扇区有512个字节。有的可能是1024、2048、4096。
4. 偏移地址0DH,长度1。内容:01。
表示的意思是每一个簇有1个扇区。
这个值不能为0,并且必须是2的整数次方,比方1、2、4、8、16、32、64、128。可是这个值不能使每一个簇超过32KB字节。
5. 偏移地址0EH,长度2,内容:08 00。转换一下。就是00 08,意思是保留区域中的保留扇区数为8个。
那么就能够知道以下的FAT1区的開始的地址就是:0x08*0x200(每一个扇区的字节数)=0x1000。
6. 偏移地址10H。长度1,内容:02。表示此卷中的FAT结构的份数为2,另外一个是备份的。
7. 偏移地址11H。长度2,内容:00 02。转换一下,就是0200H,表示根文件夹项数(Root Entries) 能够保存在该分区的根文件夹文件夹中的32个字节长的文件和文件夹名称项的总数。在一个典型的硬盘上,本字段的值为512。
8. 偏移量地址13H。长度2,内容:4D ED。转换一下就是ED4DH。即大约32MB的SD卡存储量。表示小扇区数(Small Sector) 。该分区上的扇区数,表示为16位(<65536)。对大于65536个扇区的分区来说,本字段的值为0,而使用大扇区数来代替它。
9. 偏移地址16H,长度2,内容:EC 00。转换一下为00EC,表示每一个FAT占用的扇区数。
那么每一个扇区占用的字节数就是0x00EC*0x200=0x1D800。依据启动区、FAT1、FAT2、根文件夹、数据区的次序,能够依次计算出它们的地址了。
(教程中给出的偏移地址为24H,可是依据实际的FAT1/FAT2地址的推算。应该是16H地址)
10. 偏移量地址20H,长度2,内容:00 00。
表示大扇区数(Large Sector) 。假设小扇区数字段的值为0,本字段就包括该FAT16分区中的总扇区数。假设小扇区数字段的值不为0,那么本字段的值为0。
11. 偏移量地址36H,长度为8,内容:46 41 54 31 36 20 20 20。对于ASCII码为“FAT16”,表示文件系统类型(File System Type) 依据该磁盘格式,该字段的值能够为FAT、FAT12或FAT16
启动区:理所当然是0x00;
FAT1:0x1000;
FAT2:0x1000 + 0x1D800 = 0x1E800;
根文件夹区:0x1E800 + 0x1D800 = 0x3C000;
数据区的地址,等等再计算。
这个仅仅是计算。能够看看是不是和实际的一致。
怎么样。是不是和计算的非常一致。
为什么要计算SD数据的读取要给出地址。并且每次读取都是一个整扇区。512个字节。
找出这些地址后,能够非常方便的找到数据。
如今分析下根文件夹区的内容:
这里使用的是FAT16短文件文件夹项,每32个字节表示一个文件(文件夹也是),32个字节的表示定义分别例如以下:
字节偏移(16进制) |
字节数 |
定义 |
|
0x0~0x7 |
8 |
文件名称 |
|
0x8~0xA |
3 |
扩展名 |
|
0xB |
1 |
属性字节 |
00000000(读写) |
00000001(仅仅读) |
|||
00000010(隐藏) |
|||
00000100(系统) |
|||
00001000(卷标) |
|||
00010000(子文件夹) |
|||
00100000(归档) |
|||
0xC~0x15 |
10 |
系统保留 |
|
0x16~0x17 |
2 |
文件的近期改动时间 |
|
0x18~0x19 |
2 |
文件的近期改动日期 |
|
0x1A~0x1B |
2 |
表示文件的首簇号 |
|
0x1C~0x1F |
4 |
表示文件的长度 |
1. 偏移地址00H。长度8,内容:驱动器的名称,8个字节。
这里的CCD8相应国标码“特”。而C8A8相应国标码“权”。即特权同学给该SD卡起的“特权”一名。
2. 偏移地址20H,长度8。内容:54 45 53 54 20 20 20 20。
表示第一个文件名称:TEST (空缺部分是空格)。
偏移地址80H,长度8。内容:4E 45 58 54 20 20 20 20。表示第二个文件名称:NEXT (空缺部分是空格)。
3. 偏移地址28H(88H也一样),长度3,内容:54 58 54。
表示文件类型,为ASCII字符表示。
4. 偏移地址2BH(8BH也一样),长度1,内容:20。表示文件属性,00000000(读写);00000001(仅仅读);00000010(隐藏)。00000100(系统)。00001000(卷标);00010000(子文件夹);00100000(归档)。
5. 偏移地址36H,长度2,内容为BA 49。表示时间=小时*2048+分钟*32+秒/2。得出的结果换算成16进制填入就可以。也就是:36H字节的0~4位是以2秒为单位的量值;36H字节的5~7位和37H字节的0~2位是分钟;37H字节的3~7位是小时。
6. 偏移地址38H,长度2,内容为A3 3A。表示日期=(年份-1980)*512+月份*32+日。得出的结果换算成16进制填入就可以。也就是:38H字节0~4位是日期数。38H字节5~7位和39H字节0位是月份;39H字节的1~7位为年号。原定义中0~119分别代表1980~2099,眼下高版本号的Windows同意取0~127,即年号最大能够到2107年。
7. 偏移地址3AH,长度2。为该文件開始簇号,这里也是用了小端格式组织。转换下为00 02,依据这个就能够找到文件TEST.txt下一个簇号在FAT1中的位置了。1000H+02H*02H(由于2个字节存一个簇号)= 1004H。
偏移地址3AH。长度2,为该文件開始簇号,这里也是用了小端格式组织。
转换下为00 62。依据这个就能够找到文件NEXT.txt下一个簇号在FAT1中的位置了。1000H+62H*02H(由于2个字节存一个簇号)= 10C4H。
8. 偏移地址3CH,长度4,内容:59 BE 00 00。
表示文件长度,转换后为00 00 BE 59就是48729字节。
偏移地址9CH,长度4,内容:32 00 00 00。
表示文件长度。转换后为00 00 00 32就是50字节。
TEST.txt占用了48KB的空间,NEXT占用了512B的空间。文件是依照整簇来存放的。不够一个簇的大小(由上面算得。一个簇为一个扇区即512B),也要给一个簇的空间。
计算出该文件放置空间。
从文件的大小能够计算出,须要占用多少个簇。依据前面的数据,每一个簇放1个扇区,每一个扇区512个字节,那么一个簇的空间就是512字节了。那么48729字节须要96个簇。这96个簇的開始的地址就能够计算出来了。
首先要提一点。这个地方也是特权同学找了非常多资料才发现的,就是根文件夹中根文件夹占有32(20H)个扇区应该是固定的(至少对于FAT16应该是这样),所以真正的用户数据存放应该是从根文件夹地址的32个扇区偏移量后開始算的。
上面已经知道TEST.txt開始簇地址存放在FAT1中的偏移量了:02H,由此能够先计算出TEST.txt的第一簇数据存放地址为:3C000H(根文件夹地址)+20H*200H(前面提到的用户数据偏移量)+(02H-02H)*01H(1个簇有1个扇区)*200H=40000H。把偏移量-02H意思是簇号在FAT1中存储都是从02H開始的。
而第一个簇地址存放在FAT1中的:1000H(FAT1起始地址)+02H*02H=1004H。而1004H地址上的数据为:03 00。转换后为0003H,那么我们能够计算出TEST.txt第二个簇的地址为:3C000H(根文件夹区地址)+20H*200H(前面提到的用户数据偏移量)+ (03H-02H)*01H(1个簇有1个扇区)*200H=40200(第一个簇開始地址)。依此类推,一直到FAT1中偏移量为C2处出现了FF FF。这表示TEST.txt文件存储结束,那么前面的0061H就是文件最后一个簇偏移量。我们能够由此算一下文件大小为:(0061H-0002H+0001H(补偿))=96个簇。和实际相符。
相同的道理能够算出NEXT.txt文件的存放地址。首先起首地址偏移量为62H,由此能够先计算出NEXT.txt的第一簇数据存放地址为:3C000H(根文件夹地址)+20H*200H(前面提到的用户数据偏移量)+(62H-02H)*01H(1个簇有1个扇区)*200H=4C000H。而第一个簇地址存放在FAT1中的:1000H(FAT1起始地址)+62H*02H=10C4H。
而10C4H地址上的数据为:FF FF,即结束了。也就是说由于NTXT.txt不满一个簇,那么仅仅能分配到一个簇的地址空间。