一個操作系統的實現筆記:加載Loader進入內存

       一個操作系統從開機到開始運行,大致經歷“引導→加載內核入內存→跳入保護模式→開始執行內核”這樣一個過程。也就是說,在內核開始執行之前不但要加載內核,而且還有準備保護模式等一系列工作,如果全都交給引導扇區來做,512字節很可能是不夠用的,所以,不妨把這個過程交給另外的模塊來完成,我們把這個模塊叫做Loader。

       引導扇區負責把Loader加載入內存並且把控制權交給它,其他工作放心地交給Loader來做,因爲它沒有512字節的限制,將會靈活得多。

一、準備工作

1.FAT12各區分佈

       引導扇區和Loader肯定是存在磁盤或軟盤中,這裏我們存在軟盤中,並且使用的是FAT12文件系統,軟盤中各分區的分佈情況:
在這裏插入圖片描述
       引導扇區位於磁盤的0柱面,0磁頭,1扇區,在這個扇區中有一個很重要的數據結構叫做BPB(BIOS ParameterBlock)。關於FAT12的引導扇區和根目錄區可以參考:FAT12引導扇區格式及根目錄區條目格式其中就有對BPB各項的描述。

2.數據區位置計算

       數據區的第一個扇區的位置可以通過計算根目錄所佔的扇區數得到。具體公式是:

RootDirSector = BPB_RootEntCnt×32÷BPB_BytsPerSec

       這是餘數爲零的情況下,如果餘數不爲零,則根目錄扇區數:

RootDirSector = BPB_RootEntCnt×32÷BPB_BytsPerSec+1

       RootDirSector就是要計算的根目錄區扇區數由FAT12引導扇區格式及根目錄區條目格式中對BPB的介紹可以知道,BPB_RootEntCnt是根目錄區條目數最大值,每個條目32字節,BPB_BytsPerSec是每扇區字節數。

3.FAT表

       雖然由此可以找到文件,但是還不夠,因爲有的文件大於512字節(一個扇區512字節),超過512字節的內容我們需要根據FAT表找到。FAT表在引導扇區和根目錄區之間,FAT表有兩個,FAT2可看做是FAT1的備份,它們通常是一樣的。

其中,每12位稱爲一個FAT項(FATEntry),代表一個簇。第0個和第1個FAT項始終不使用,從第2個FAT項開始表示數據區的每一個簇,也就是說,第2個FAT項表示數據區第一個簇,以此類推。

       說到這裏好像還沒說清FAT表的具體功能,對於FAT表的具體功能後面再說,下面先來說說怎麼辨認FAT表的每一項,我第一次看的時候還真沒看懂。

       假設下面是一組FAT表的表項:
       0000200: F0 FF FF FF 8F 00 09 A0 00

       因爲FAT表的第0和第1項始終不使用,所以前三個字節不用管它。以第2、3表項爲例(FF 8F 00),3個字節包含了兩個FAT表表項,第2個表項的低8位就是第一個字節,即FF;第2個表項的高4位就是第二個字節的低4位,也就是F,所以第2個表項的值爲0xF FF。而第3個表項的低4位就是第二個字節的高4位,即8,第3個表項的高8位就是第3個字節,即00,所以第3個表項的值爲0x00 8;以此類推,第四個表項的值就是0x0 09,第五個表項的值爲0x00 0。

       然後再說說FAT表項的值的功能:FAT項的值代表的是文件下一個簇號,但如果值大於或等於0xFF8,則表示當前簇已經是本文件的最後一個簇。如果值爲0xFF7,表示它是一個壞簇。

       根目錄條目中有一項是DIR_FstClus,這個條目對應的是文件的開始簇號,即在數據區中的簇號,同時它也對應了FAT表中的項,如果FAT表項的值小於0xFF8,則此值對應的就是文件的下一個簇號和FAT表的下一個表項。舉個例子:假如一個長一點的文件FLOWER.TXT,它的DIR_FstClus值爲3,對應第3個FAT項。此FAT項值爲0x008,也就是說,這個簇不是文件的最後一個簇,下一個簇號爲8。我們再找到第8個FAT項,發現值爲0x009,接下來第9個FAT項值爲0x00A,第0xA個FAT項值爲0xFFF。所以,FLOWER.TXT佔用了第3、8、9、10,共計4個簇。

二、寫入過程

       要加載Loader肯定要先找到Loader,我們規定Loader放在根分區也就是根目錄中,所以從跟分區的第一個分區開始找,比較每個分區第一個條目(Loader的名稱)是不是“LOADER BIN”,如果找到,就將LOADER.BIN的起始扇區號加載入內存,在此之前,將此扇區在FAT表中的序號入棧。起始扇區加載完後,將其扇區在FAT表中的序號出棧,然後計算出FAT表項的值,將此值和“0FFFh”比較,相等的話說明此簇是文件的最後一個簇之前說只要fat表項值大於等於0FF8h就說明此簇是文件的最後一個簇,所以爲什麼要和0FFFh比較呢,我在網上搜了相關資料,fat12的fat表文件結束簇是0FF8h~0FFFh,所以我將代碼改了一下:

	cmp	ax, 0FFFh
	jz	LABEL_FILE_LOADED

改爲

	cmp	ax, 0FF8h
	jnb	LABEL_FILE_LOADED

運行結果都一樣,但是改爲

	cmp	ax, 0FF8h
	jz	LABEL_FILE_LOADED

就不行,所以我認爲判斷此簇是否文件最後一個簇fat表項的值應比較到0FFFh。

       本來想在解釋一下代碼的,但是代碼太多,解釋起來又麻煩,又得寫好長,就算寫好了,這麼長的文章也很難讓人耐着性子去看,所以決定關於代碼另寫幾篇博客,這裏就不在多說。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章