解析FAT16文件系統
引導扇區的信息例如以下:
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個字節的表示定義分別例如以下:
FAT16文件夾項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不滿一個簇,那麽僅僅能分配到一個簇的地址空間。
解析FAT16文件系統