x86的啓動
進入BIOS
x86在上電啓動後,和所有處理器一樣,執行一條固定位置的指令。其位置是CS=FFFF000H,EIP=0000FFF0H。此時運行在實模式下,因此CS:EIP得到的即爲物理地址(詳見80386實模式)。該合成的地址爲FFFFFFF0H,即EPROM所在的地址。該位置通常是一條jmp長跳轉指令,跳轉到BIOS中運行。
x86架構下各型號CPU上電後寄存器初始值
進入BootLoader
CPU進入BIOS執行後,BIOS負責加載存儲設備(如硬盤,或U盤)上的第一個扇區,即通常說的啓動引導扇區MBR。MBR中存儲了操作系統的Bootloader代碼。這段代碼會被加載到內存的0x7c00處,隨後CPU跳轉到這個地址開始執行。
BootLoader做的事
BootLoader中的代碼負責使能CPU的段機制,並使CPU進入保護模式。然後從指定的硬盤扇區(不一定是第一扇區)讀取操作系統kernel到內存,跳轉到kernel的入口位置,將CPU交給操作系統。
這樣做的目的
從啓動到操作系統開始運行,進行了兩次跳轉,經過了BIOS和BootLoader。這樣做的目的,對BIOS來說是根據CPU來進行系統的初始化,使操作系統不需要專門適配每個型號的CPU。對於BootLoader來說,能夠從不同的扇區加載操作系統。
/***************************************************/
x86的段機制
Intel CPU保護模式和實模式的不同,很重要的一點就是段機制的引入。在實模式中, CS:IP兩個寄存器,就指定了程序代碼的物理地址,CPU直接跳轉到那裏執行。在保護模式中, 雖然最終地址的合成是一樣的(但x86地址位數爲32位),但是合成之前,需要經過全局描述符表GDT。GDT事實上是一個段表,即一系列基地址組成的列表。GDT的每一項稱爲段描述符,其中存放着一個段的索引,段起始地址和段大小信息。在這種情況下,CS中存放的不再是基址,而是13位索引,又稱段選擇子。根據這個索引,找到相應的段描述符,取出段起始地址作爲基址,再加上EIP寄存器中的偏移量,合成線性地址。在沒有頁機制的情況下,該線性地址就成爲尋址的物理地址。
GDT由操作系統建立,其表頭地址保存在GDTR寄存器中。
/**************************************************/
x86的中斷
x86對於突發事件有三種定義:中斷,異常和系統調用。三種事件的發生條件和處理不同,但中間的傳遞機制大同小異。
與簡單微控制器的中斷方式一樣,x86中斷也通過中斷號和中斷向量表,來查詢對應的中斷服務例程。但x86在得到中斷向量後,需要查詢的是中斷描述符表IDT。IDT的每一項中存放了一個段選擇子和一個偏移量。通過中斷向量從IDT中找出該向量對應的段選擇子,再跳轉到GDT裏查得對應的基址,和上述IDT裏的偏移量組成該中斷向量對應的中斷服務例程入口地址。
進入中斷服務例程前,CPU要先將重要的寄存器壓棧。對於內核請求的中斷,主要是CS,EIP,EFLAG(中斷標誌),ERRORCODE(異常代碼)。對於用戶應用程序請求的中斷,還需壓入SS和ESP,因爲此時涉及堆棧上下文的切換(內核是不會與用戶應用使用同一個堆棧的)。
執行完中斷服務例程後,使用iret指令彈出上述寄存器的值。