一、 FAT12
FAT12是DOS時代就開始使用的檔案系統(File System),直到現在仍然在磁碟片上使用,FAT12磁碟片的被格式化後為:有兩個磁頭,每個磁頭80個柱面(磁軌),每個柱面有18個扇區,每個扇區512個位元組空間。所以標準磁碟片的總空間為:
2 * 80 *18 * 512=1474560B=1440K=1.44M
下面是FAT12的結構圖:
1、開機磁區
作業系統之所以認識FAT12格式的磁碟,其秘密就在於邏輯0扇區這512B上。如果這512位元組的最後兩個位元組的內容分別是55和AA(0xAA55低位元組在前,高位元組在後)的話,BIOS在啟動時會將這個扇區讀取到0:7C00h-0:7DFFh處,然後跳轉到0:7C00h處繼續執行指令,作業系統即用此來達到引導系統的目的,而這個磁碟就稱為引導磁碟。
作業系統標識FAT12檔案系統是因為在邏輯0扇區(即開機磁區)處還儲存著一個特定的資料結構,此結構有固定的格式,在作業系統將此磁碟格式化時自動產生,具體資料結構如下表所示:
名稱 |
開始位元組 |
長度 |
內容 |
參考值 |
BS_jmpBOOT |
0 |
3 |
一個短跳轉指令 |
jmp short LABEL_START nop |
BS_OEMName |
3 |
8 |
廠商名 |
'ZGH' |
BPB_BytesPerSec |
11 |
2 |
每扇區位元組數(Bytes/Sector) |
0x200 |
BPB_SecPerClus |
13 |
1 |
每簇扇區數(Sector/Cluster) |
0x1 |
BPB_ResvdSecCnt |
14 |
2 |
Boot記錄佔用多少扇區 |
ox1 |
BPB_NumFATs |
16 |
1 |
共有多少FAT表 |
0x2 |
BPB_RootEntCnt |
17 |
2 |
根目錄區檔案最大數 |
0xE0 |
BPB_TotSec16 |
19 |
2 |
扇區總數 |
0xB40 |
BPB_Media |
21 |
1 |
介質描述符 |
0xF0 |
BPB_FATSz16 |
22 |
2 |
每個FAT表所佔扇區數 |
0x9 |
BPB_SecPerTrk |
24 |
2 |
每磁軌扇區數(Sector/track) |
0x12 |
BPB_NumHeads |
26 |
2 |
磁頭數(面數) |
0x2 |
BPB_HiddSec |
28 |
4 |
隱藏扇區數 |
0 |
BPB_TotSec32 |
32 |
4 |
如果BPB_TotSec16=0,則由這裡給出扇區數 |
0 |
BS_DrvNum |
36 |
1 |
INT 13H的磁碟機代號 |
0 |
BS_Reserved1 |
37 |
1 |
保留,未使用 |
0 |
BS_BootSig |
38 |
1 |
擴充引導標記(29h) |
0x29 |
BS_VolID |
39 |
4 |
卷序號 |
0 |
BS_VolLab |
43 |
11 |
卷標 |
'ZGH' |
BS_FileSysType |
54 |
8 |
檔案系統類型 |
'FAT12' |
引導代碼及其他內容 |
62 |
448 |
引導代碼及其他資料 |
引導代碼(剩餘空間用0填充) |
結束標誌0xAA55 |
510 |
2 |
第510位元組為0x55,第511位元組為0xAA |
0xAA55 |
下面我們介紹其中的一些變數的含義:
BS_jmpBoot:是跳轉指令,位移0處的跳轉指令必須是合法的可執行檔基於x86的CPU指令,如:jmp start,這樣可以產生3位元組長的指令,(加關鍵字short的短跳轉指令的長度是2位元組),指向作業系統引導代碼部分。Windows和MS-DOS產生的FAT12開機磁區中的跳轉指令是短跳轉,如:jmp
short LABEL_START,然後加一個nop的空指令來保持3位元組的長度。
BPB_BytsPerSec:每扇區的位元組數,類型是雙位元組長,標準分區上的每扇區位元組數一般是512B, FAT12的格式下設定為512(0x200h)。
BPB_SecPerClus:每簇扇區數,位移13處,類型是位元組,簇是資料存放區的最小單位,在FAT12格式下一般為1,即每簇只有1個扇區(512位元組)。
BPB_RsvdSecCnt:Boot記錄佔用多少扇區,即在FAT1之前的 開機磁區,一般情況下,開機磁區佔用1個扇區。
BPB_NumFATs:共有多少個FAT表,預設情況下此欄位的值為2,也就是有兩個FAT表,FAT1和FAT2的內容相同,當FAT1表出錯的時候可以使用FAT2來恢複檔案配置表。
BPB_RootEntCnt:根目錄檔案數最大值,預設為224,每個目錄條目佔用32B的空間,因此根目錄的大小為:224*32/512=14,即佔用14個扇區。
BPB_TotSec16:扇區總數=0xB40=2880
BPB_FATSz16:每個FAT佔用的扇區數=0x9=9,即FAT1佔用1—9邏輯扇區,FAT2佔用10—18邏輯扇區。
BPB_SecPerTrk:每磁軌扇區數=0x12=18,即標準FAT12檔案系統中,每個磁軌的扇區數就是為18。
BPB_NumHeads:磁頭數=0x2=2,該磁碟包括2個磁頭,也就是面數是2。
2、FAT表
FAT1和FAT2是兩個完全相同的FAT表,每個FAT佔用9個扇區。其中FAT1佔用1—9扇區,FAT2佔用10—18扇區。具體詳細介紹看下面4。
3、根目錄區
根目錄區的開始扇區號是19,它是由若干個目錄條目(Directory Entry)組成,條目最多有BPB_RootEntCnt個,由於根目錄區的大小是依賴於BPB_RootEntCnt的,所以長度不固定。
在本FAT12中,因為BPB_RootEntCnt=0xE0=14*16+0=244,即條目最多為244個,又因為每個條目佔用32個位元組,故244*32/512=14,即該根目錄區佔14個扇區,即19—32。
根目錄區中的每個條目佔用32位元組,它的格式如:
這裡主要定義了檔案的名字,屬性,最後寫入的時間和日期,檔案的開始簇數以及檔案大小。
下面我們通過執行個體來認識這些內容,
1、 首先建立一個虛擬磁碟,在這裡我們使用WinImage,具體在我的下載資源中。
開啟WinImage:
選擇檔案—》建立
建立一個虛擬磁碟之後,需要向裡面添加檔案,我們需要提前寫好下面幾個檔案
RIVER.TXT,內容為riverriverriver
FLOWER.TXT,內容為flowerflower………flower,至少要100個flower,使得資料空間大於512個位元組,這樣該檔案將佔用兩個連續的扇區。
TREE.TXT,內容為treetreetree
再添加一個HOUSE目錄,然後在目錄\HOUSE下添加兩個文字檔:
CAT.TXT,內容為catcatcat
DOG.TXT,內容為dogdogdog
選擇映像—》加入,依次加入RIVER.TXT,FLOWER.TXT,TREE.TXT三個檔案
映像—》建立檔案夾 HOUSE
添加HOUSE目錄
雙擊house,進入house的檔案夾內,然後添加CAT.TXT,DOG.TXT兩個檔案
添加檔案完成,然後儲存,其中注意事項,檔案類型為:虛擬磁碟映像(*.vfd),我不知道這個類型與IMG有什麼區別,但是我知道這個類型得到的結果是對的。呵呵!檔案名稱為FLOOPY,這樣我們就建立了一個虛擬磁碟FLOOPY.vfd
然後使用UltraEdit開啟FLOOPY.vfd,由於根目錄區是從第19扇區開始的,每個扇區512個位元組,所以其第一個位元組位於位移19*512=9278=0x2600處,好的,現在就讓我們去定位到0x2600處看看到底Directory Entry為何物?
RIVER.TXT的各項值:
在這裡,我們只需要關心RIVER.TXT的DIR_FstClus,即檔案的開始簇號,由於本FAT12中的BPB_SecPerClus=1,故一個簇為一個扇區,DIR_FstClus=2,意味著該檔案的在資料區的起始扇區號為2。在這裡需要注意的是,資料區的第一個簇的簇號是2,而不是0或者1,故該檔案的資料開始於資料區的第一個簇,也就是第一個扇區。
那麼資料區的第一個扇區在哪裡呢?
首先計算根目錄區所佔有的扇區數:
RootDirSectors =((BPB_RootEntCnt*32)+(BPB_BytsPerSec-1))/BPB_BytsPerSec。
之所以分子要加上(BPB_BytsPerSec-1),是為了保證此公式在根目錄區無法填滿整數扇區時仍然成立。
在本例中,因為BPB_RootEntCnt=224,計算得到根目錄區所佔有的扇區為14個。所以
資料區開始的扇區號=根目錄區開始的扇區號+14=19+14=33。
現在就讓我們跳入到第33扇區的位移量是512*33=16896=0x00004200,讓我們看看這裡的內容:
果然是riverriverriver。
4、FAT表
在這裡,由於RIVER.TXT小於512位元組,所以我們不需要FAT表就在資料區中找到了RIVER.TXT的內容,但是對於大於512位元組的檔案來說,就沒有這麼簡單了,需要使用FAT表來尋找到該檔案佔用的所有資料區扇區。
下面讓我們跳入FAT1的內容,FAT1的開始扇區號是1,故位移為1*512=512=0x200。
一堆看不懂的符號,好像很多F。其實並不複雜,它有點像是一個位元影像,其中,每12位成為一個FAT項(FAT Entry),代表一個資料區中的簇。第0個和第1個FAT項始終不使用,第2個FAT項開始表示資料區的每一個簇,也就是說,第2個FAT項表示資料區第一個簇,依次類推。前文說過,資料區的第一個簇的簇號是2,和這裡相呼應。
要注意,由於每一個FAT項佔12位,包含一個位元組和另一個位元組的一般,所以覺得特別彆扭。具體情況是這樣的,假設連續3個位元組分別是:
通常,FAT項的值代表的是檔案的下一個簇號,但如果值大於或等於0xFF8,則表示當前簇已經是檔案的最後一個簇了。如果值為0xFF7,表示它是一個壞簇。
檔案RIVER.TXT的開始簇號為2,對應的FAT表中的值為0xFFF,表示這個簇已經是最後一個。
檔案FLOWER.TXT的開始簇號為3,對應的FAT表中的值為0x004,表示檔案還沒有結束,下一個簇號是0x004,然後我們再看FAT表中第4個簇相對應的FAT值為0xFFF,則表示該是最後一個簇,則檔案FLOWER.TXT佔用第3、4簇。
如果想使檔案內容分存在不連續的扇區內,有一個方法可以做到,就是先將該檔案加入到磁碟片驅動中,然後在進行添加相同的檔案,進行覆蓋。當然該檔案的大小必須大於512個位元組。
《自己動手寫作業系統》讀後感 http://blog.csdn.net/zgh1988/article/details/7059936
全面剖析《自己動手寫作業系統》第一章 http://blog.csdn.net/zgh1988/article/details/7060032
全面剖析《自己動手寫作業系統》第二章 http://blog.csdn.net/zgh1988/article/details/7062065
全面剖析《自己動手寫作業系統》第三章1 http://blog.csdn.net/zgh1988/article/details/7098981
全面剖析《自己動手寫作業系統》--“實模式--保護模式--實模式” http://write.blog.csdn.net/postedit/7256254
全面剖析《自己動手寫作業系統》--堆棧段的工作方式 http://blog.csdn.net/zgh1988/article/details/7256254
全面剖析《自己動手寫作業系統》---特權級 以及 不同特權級程式碼片段之間的跳轉規則 http://blog.csdn.net/zgh1988/article/details/7262901
全面剖析《自己動手寫作業系統》--分頁機制 http://blog.csdn.net/zgh1988/article/details/7270748
全面剖析《自己動手寫作業系統》--中斷機制 http://blog.csdn.net/zgh1988/article/details/7276259