04 主載入程式的擴充套件-上
一.主載入程式上
從之前的幾章可以知道,主載入程式的程式碼量不能超過512位元組,但是在實際中我們需要突破512位元組的限制
突破限制的思路-主載入程式
1.完成最基本的初始化工作
2.從儲存介質中載入程式到記憶體中
3.將控制權交由新載入的程式執行
但是在這會出現問題-主載入程式如何載入儲存介質中的其它程式?
檔案系統--儲存介質上組織檔案資料的方法-主要包含資料區、根目錄、FAT2、FAT1、引導扇區如圖所示
A.檔案系統示例(用到的虛擬網盤時F12)
1.FAT12是DOS時代的早期檔案系統
2.FAT12結構非常簡單,一直沿用於軟盤
3.FAT12的基本組織單位-位元組:基本資料單位、扇區:磁碟中的最小資料單元、簇:一個或者多個扇區
通過之前的介紹,可以得出解決方案
1.使用FAT12對軟盤(data..img自定義的)進行格式化
2.編寫可執行程式(Loader),並將其拷貝到軟盤中
3.主載入程式(Boot)在檔案系統中查詢Loader
4.將Loader複製到記憶體中,並跳轉到入口處執行
實驗-往虛擬軟盤中寫入檔案,在這裡我們需要一些準備的基本bochs、FreeDos、bximage,主要步驟是建立虛擬軟盤然後在FreeDos中進行格式化,最後將data.img掛載Linux中,並寫入檔案
通過bximage命令生成data.img,並在配置中將其併入到freeDos.img上
通過執行之後生成,然後通過format B命令對B盤進行格式化,B盤就是虛擬軟碟機,將其格式化虛擬軟盤data.img就有了檔案系統就是Fata12檔案系統,然後通過終端以及命令生成之前提到的原材料並將其拷貝至軟盤中
最後通過命令進行檢視虛擬軟盤下的檔案,以及檔案內的內容
B.對FAT12進行深入的理解
FAT12檔案系統由引導區,FAT表,根目錄項表和檔案資料區組成
FAT12的主引導區--主引導區儲存的比較重要的資訊是檔案系統的型別,檔案系統邏輯扇區總數,每簇包含的扇區數,等。主引導區最後以0x55AA兩個位元組作為結束,共佔用一個扇區
怎麼來驗證一下我們格式化後的a.img虛擬軟盤中就是這些資訊呢?我們可以將a.img當成一個普通的檔案,然後寫一個程式進行讀取,讀取程式使用Qt creater來寫,因為Qt中提供了很多好用的工具類,方便我們來驗證程式如下
#include <QtCore/QCoreApplication> #include <QFile> #include <QDataStream> #include <QDebug> #pragma pack(push) #pragma pack(1) struct Fat12Header { char BS_OEMName[8]; ushort BPB_BytsPerSec; uchar BPB_SecPerClus; ushort BPB_RsvdSecCnt; uchar BPB_NumFATs; ushort BPB_RootEntCnt; ushort BPB_TotSec16; uchar BPB_Media; ushort BPB_FATSz16; ushort BPB_SecPerTrk; ushort BPB_NumHeads; uint BPB_HiddSec; uint BPB_TotSec32; uchar BS_DrvNum; uchar BS_Reserved1; uchar BS_BootSig; uint BS_VolID; char BS_VolLab[11]; char BS_FileSysType[8]; }; #pragma pack(pop) void PrintHeader(Fat12Header& rf, QString p) { QFile file(p); if( file.open(QIODevice::ReadOnly) ) { QDataStream in(&file); file.seek(3); in.readRawData(reinterpret_cast<char*>(&rf), sizeof(rf)); rf.BS_OEMName[7] = 0; rf.BS_VolLab[10] = 0; rf.BS_FileSysType[7] = 0; qDebug() << "BS_OEMName: " << rf.BS_OEMName; qDebug() << "BPB_BytsPerSec: " << hex << rf.BPB_BytsPerSec; qDebug() << "BPB_SecPerClus: " << hex << rf.BPB_SecPerClus; qDebug() << "BPB_RsvdSecCnt: " << hex << rf.BPB_RsvdSecCnt; qDebug() << "BPB_NumFATs: " << hex << rf.BPB_NumFATs; qDebug() << "BPB_RootEntCnt: " << hex << rf.BPB_RootEntCnt; qDebug() << "BPB_TotSec16: " << hex << rf.BPB_TotSec16; qDebug() << "BPB_Media: " << hex << rf.BPB_Media; qDebug() << "BPB_FATSz16: " << hex << rf.BPB_FATSz16; qDebug() << "BPB_SecPerTrk: " << hex << rf.BPB_SecPerTrk; qDebug() << "BPB_NumHeads: " << hex << rf.BPB_NumHeads; qDebug() << "BPB_HiddSec: " << hex << rf.BPB_HiddSec; qDebug() << "BPB_TotSec32: " << hex << rf.BPB_TotSec32; qDebug() << "BS_DrvNum: " << hex << rf.BS_DrvNum; qDebug() << "BS_Reserved1: " << hex << rf.BS_Reserved1; qDebug() << "BS_BootSig: " << hex << rf.BS_BootSig; qDebug() << "BS_VolID: " << hex << rf.BS_VolID; qDebug() << "BS_VolLab: " << rf.BS_VolLab; qDebug() << "BS_FileSysType: " << rf.BS_FileSysType; file.seek(510); uchar b510 = 0; uchar b511 = 0; in.readRawData(reinterpret_cast<char*>(&b510), sizeof(b510)); in.readRawData(reinterpret_cast<char*>(&b511), sizeof(b511)); qDebug() << "Byte 510: " << hex << b510; qDebug() << "Byte 511: " << hex << b511; } else { qDebug() << "file not found"; } file.close(); } int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); Fat12Header f12; PrintHeader(f12, "data.img"); return a.exec(); }
我們定義的Fat12Header結構體是和主載入程式一一對應的,執行以上程式碼,輸出如下所示:
可以看到,我們讀出的資訊和FAT檔案系統引導區的詳細資訊完全對應了。