最近開始接觸作業系統,在用了Linux作業系統這麼久,一直不明白他是怎麼做到在電腦上啟動並執行?首先我便開始瞭解了這一問題,即從電腦開機加電到main函數的執行幹了什嗎?
通過自己這幾日沒事看看書終於了這個過程分了三步,其目的是實現從啟動盤載入作業系統程式,完成執行main函數所需要的準備工作。
【第1步】:啟動BIOS,準備實模式下的中斷向量表和中斷服務程式;
【第2步】:從啟動盤載入作業系統程式到記憶體,載入作業系統程式的工作就是利用第1步中準備的中斷服務程式實現的;
【第3步】:為執行32位的main函數做過渡工作。
實模式(Real mode)是Intel80286和之後的80x86相容CPU的操作模式。實模式的特性是一個20位的儲存空間地址空間(2^20=1048576,即1MB的儲存空間可被定址),可以直接通過軟體的方式訪問BIOS以及周邊硬體,沒有硬體支援的分頁機制和即時多任務的概念。從80286開始,所有的80x86CPU的開機狀態都是實模式;8086等早期的CPU只有一種操作模式,類似於實模式。
電腦的運行時離不開程式的。然而,加電的一瞬間,電腦的記憶體中,準確的說是RAM中,空空如也,什麼程式也沒有。硬碟裡雖然有作業系統程式,但CPU的邏輯電路被設計為只能運行記憶體中的程式,它沒有能力直接從硬碟運行作業系統。如果要運行硬碟中的作業系統,必須將硬碟中的作業系統程式載入到記憶體(RAM)中。(RAM(Random
Access Memory):隨機存取儲存空間。常見的記憶體條就是一條RAM,它的特點是加電狀態下可任意讀、寫,斷電後資訊消失。)問題是在RAM中什麼程式也沒有的時候,誰來完成載入硬碟中作業系統的任務呢?答案便是BIOS。
下面我們說說BIOS的啟動原理
從我們使用電腦的經驗得知:要想執行一個程式,不許再視窗中雙擊它,或者在命令列介面中輸入相應的執行命令。從電腦底層機制上講,這其實是在一個已經運行起來的作業系統的可視化介面或命令列介面中執行一個程式。但是,在開機加電的一瞬間,記憶體中什麼程式也沒有,沒有任何程式在運行,不可能有作業系統,更不可能有作業系統的使用者介面。我們無法人為地執行BIOS程式,那BIOS程式又是有誰來執行的呢?從體系的角度來看,不難得出這樣的結論:既然軟體方法不可能執行BIOS,那麼就只能靠硬體方法完成了。
從硬體的角度看,Intel80x86系列的CPU可以分別在16位實模式和32位保護模式下運行。為了相容,也為瞭解決最開始的啟動問題,Intel將所有80x86系列的CPU(包括最新型號的CPU)的硬體都設計為加電即進入16位的實模式狀態運行。同時,還有一點非常關鍵,即將CPU硬體邏輯設計為加電瞬間強行將CS(程式碼片段寄存器,指向CPU當前執行代碼在記憶體中所在地區)的值置為0xFFFF,IP(指令指標寄存器,存在於CPU中,記錄將要執行的指令在程式碼片段內的位移地址。與CS結合便可以指向將要執行的指令記憶體位址。實模式為絕對位址,指令指標為16位,即IP,保護模式下為32位,即EIP)的值置為0x0000,這樣CS:IP就指向0xFFFF0這個位址範圍。
然而,上面是一個純硬體完成的動作!如果此時這個位置沒有可執行代碼,那麼電腦就此死機。反之,如果這個位置有可執行代碼,電腦將從這裡的代碼開始,沿著後續程式一直執行下去。
BOIS程式的入口地址就是0xFFFF0!也就是說,BIOS程式的第一條指令就設計在這個位置上。(各個廠商約定俗成的的東西,不存在位置不同的情況)。
BIOS在記憶體中載入中斷向量表(實模式中斷機制的重要組成部分,表中記錄了所有中斷程式對應的中斷服務的記憶體位址)和中斷服務程式(對應中斷服務表中的索引的服務程式段)
BIOS程式被固化在電腦主板上的一塊很小的ROM晶片裡。通常,不同的主機板所用的BIOS也有所不同,就啟動部分而言,各種類型的BIOS的基本原理大致相似。
當CS:IP指向0xFFFFO這個位置的時候,意味著BIOS開始啟動了。隨著BIOS程式的執行,螢幕上會顯示顯卡的資訊、記憶體的資訊......說明BIOS程式在檢測顯卡、記憶體......這期間,有一項對啟動(boot)作業系統至關重要的工作,那就是BIOS在記憶體中建立中斷向量表和中斷服務程式。
ROM(ReadOnly Memory):唯讀記憶體,現在通常用快閃記憶體晶片做ROM。雖然快閃記憶體晶片在特定的條件下是可寫的,但在談到主機板上儲存BIOS的快閃記憶體晶片時,業內人士把它看做ROM。ROM有一個特性,就是斷電之後仍能儲存信心,這一點與硬碟類似。
BIOS程式在記憶體最開始的位置(即:0x00000)用1KB的記憶體空間(0x00000--0x3FF)構建中斷向量表,並在緊挨著它的位置用256位元組的記憶體空間構建BIOS資料區(0x00400--0x004FF),在資料區後的某一位載入了與中斷向量表相應的若干中斷服務程式中斷向量表中有256個中斷向量,每個中斷向量佔4個位元組,其中兩個位元組是CS的值,兩個位元組是IP的值,每個中斷向量都指向一個具體的中斷服務程式。
執行BIOS程式後,到此,就要開始執行boot操作了,即我們需要將硬碟中的作業系統檔案載入到記憶體。在電腦完成了一系列自檢工作後,出於電腦的結構預先設計,BIOS會讓CPU接收到一個int
0x19 中斷,當CPU接收到這個中斷後,會立即在中斷向量表中找到int 0x19中斷向量,其對應的就是對應的啟動載入服務程式,載入硬碟第一扇區的內容到記憶體。在此需要說的是第一扇區中的程式是由bootsect.s(引導程式)中的組譯工具彙編而成。之後當我們已經把引導程式載入記憶體時,他的作用就是將之後的第二、三批程式陸續載入到記憶體,在此之前這個引導程式bootsect首先需要對記憶體進行規劃。這裡就需要作業系統的設計者,要全面的整體的考慮記憶體的規劃,確保無論作業系統如何運行都不會出現代碼與代碼、資料與資料、代碼與資料之間的相互覆蓋。在實模式下,定址空間最大為1MB,bootsect的代碼設計首先就需要對後續操作所涉及的記憶體位置進行設定,包括要載入的setup程式的扇區數要載入的setup程式的扇區數(SETUPLEN)、被載入到的位置(SETUPSEG)、開機磁區被BIOS載入的位置(BOOTSEG)、將要移動到的新位置(INITSEG)、核心被載入的位置(SYSSEG)、核心的末尾位置(SYSEND)、根檔案系統裝置號(ROOT_DEV)、設定這些位置就是確保將要載入記憶體的代碼和已載入記憶體的代碼以及資料區分,互不覆蓋。
記憶體規劃部分還需要複製bootsect以及將setup程式載入到記憶體。今天就先寫到這裡,之後的博文會繼續對這一問題的闡述。包括之後的載入第三部分代碼-----system模組,以及整體過程的最後一步【開始向32位元模式轉變,為mian函數的調用做準備】。
有什麼錯誤希望指正。