目錄
- 第一部分
- 第二部分
- 第三部分
- 該源文件功能分為三部分:
- (1)源文件開始部分是通過各種中斷指令, 初始化計算機的組成硬件,獲得硬件的參數,然后保存到段空間0X9000。該空間原來是保存加載到內存的引導扇區內容。執行到此刻,引導程序已經執行完畢,所以覆蓋引導程序沒有問題。
- (2)將加載到內存0X1000:0X0000地址的 系統核心模塊System,通過串傳送指令movsw移動到內存0X0000:0X0000。也就是整體向前移動64KB的空間。
- (3) 將CPU從實模式切換到保護模式,然后用保護模式的跳轉方式,跳轉到正確的位置(就是0地址,執行System模塊)。
第一部分
????這部分就是通過各種BIOS中斷獲取組成計算機硬件的參數。參數包括:光標的位置、內存的大小、屏幕顯示的參數、硬盤的參數等。都保存在段空間0X9000處。學過《匯編語言》都能看懂,就不細說了。
第二部分
????將加載到內存0X1000:0X0000處的系統核心模塊System,移動到0地址(0X0000:0X0000)處。剛開始看這段代碼時,我很費解。為什么在引導程序bootsect.s不直接把磁盤中的System模塊加載到0地址處,非要現在到setup.s中再來移動呢? 看完整個代碼我懂了。
????每次開機,啟動操作系統時,都要獲取硬件的參數(setup.s的第一部分),獲取參數是通過中斷,處理中斷的中斷例程是BIOS提供的,中斷類型碼和中斷例程的映射要通過中斷向量表。而實模式下的中斷向量表默認保存在內存0地址處。如果bootsect.s直接把System模塊加載到0地址處,就覆蓋了中斷向量表。
那么現在的setup.s的第一部分就無法獲得硬件參數。因為就是通過“int 中斷類型碼”執行BIOS提供的中斷例程來獲取硬件參數。所以bootsect.s中只能先加載到0X1000:0X0000處,然后setup.s再移動到0X0000:0X0000處。
????之所以在setup.s的第二部分可以覆蓋掉中斷向量表,是因為后面的第三部分就是切換到保護模式了。保護模式下的中斷是通過查IDT(中斷描述符表)實現的。
第三部分
????進入保護模式后訪問的空間就不止1M了,所以要打開A20地址線。然后還要初始化可編程中斷控制器8259A。這兩段內容對硬件端口的操作復雜、繁瑣,沒有deepseek我根本看不懂。感謝deepseek,沒有它,我肯定沒信心閱讀Linux源碼了。
????將CPU從實模式切換到保護模式,只需將CR0寄存器的PE位置1就可以了。切換到保護模式后,我們就要通過Call指令跳轉到0地址處的System模塊。保護模式下的CS中保存的不是段地址,而是段選擇子。通過段選擇子查找GDT得到段描述符,段描述符中的基址加上偏移地址就是最終的地址。所以我們要 構造一個簡單的GDT表,然后通過LGDT指令把GDT的地址、界限加載到GDTR寄存器。如果你懂CPU的保護模式,這段很簡單。看不懂,只能先去看看保護模式的資料,再來看。保護模式不是一兩句話能說清的。操作系統修煉指南–保護模式