1. 程式人生 > >4-計算機的啟動過程

4-計算機的啟動過程

 

現在我們思考這樣一個問題:處理器是如何執行編譯好的程式。

 

1. 如何將編譯好的程式交給處理器執行

通常程式執行必須要藉助作業系統,以我們熟悉的windows為例,當我們用滑鼠點選圖示執行一個軟體時,在我們看不到的層面上,作業系統必須給執行的程式分配空閒的記憶體空間,並在合適的時候交給處理器執行。

圖1-執行程式

作業系統對執行的程式是有嚴格要求的,例如編譯好的程式是針對哪種作業系統的,(例如在windows編譯好的程式在linux中不能執行,反之亦然),程式的版本,資料段和程式碼段從哪裡開始,有多長等等。

所以在特定的作業系統開發一個軟體並不容易,但換個角度想,作業系統也是一個軟體,通常是計算機先執行的一個程式(這裡暫時不討論BIOS),也是在處理器上執行的,現在我們想在計算機一開機的時候繞過作業系統,執行我們自己編寫的程式,對於這個問題我們就不得不討論計算機的加電啟動過程了。

 

2. 計算機的加電和復位

處理器周圍有很多引腳,,有一個RESET用於接收復位訊號,每當處理器加電,就會復位並初始化。換句話說,當你按下機箱的啟動按鈕的時候,CPU就會通過RESET引腳接收到復位訊號。

圖2-處理器的引腳

 

在8086CPU中,復位訊號將會把程式碼段的暫存器CS會初始化為:0xFFFF,其他暫存器則為:0x0000,也包括了指令暫存器IP(IP是一個很重要的暫存器,後面會多次提到)。當然8086之後的處理器並未延續這種設計,無論後來的計算機怎麼樣設計,都有其目的。

IP暫存器是一個指標暫存器,它只和CS一起使用,只有處理器才能改變它的內容,CS指向程式碼段的起始地址,而IP則指向段內的編譯,總之處理器會根據CS:IP形成的地址取出指令並執行。

總之,8086CPU收到啟動復位訊號之後,CS和IP這個時候合成的20位地址就是:0xFFFF0。大家都知道,要想執行指令,必須先把指令讀到記憶體裡,可是按照我們之前所學推理,這個時候記憶體是空的,沒有任何有意義可執行的指令。

這意味著8086CPU此時從記憶體地址0xFFFF0開始獲取指令並執行會失敗,導致的後果就是計算機可能奔潰,但實際情況真的是這樣嗎?既然我們能想到這個問題,那麼當初設計8086CPU的工程師們也能想到啊,他們是怎麼做的呢?

 

首先大家應該知道一個確定的事實,8086CPU有20根地址匯流排,地址範圍是0x00000到0xFFFFF,可以訪問1MB的記憶體空間。這麼這1MB的記憶體,是不是我們任意使用呢?出於各種考慮,當初設計計算機的工程師把這1MB的記憶體從物理上和邏輯上分為幾個部分。

圖3-8086CPU的1MB記憶體分佈

 

我們從上圖可以看到8086CPU的1IMB記憶體空間的分佈,其中0x00500 — 0x07BFF區域和0x7E00 — 0x9FBFF區域是程式的可用區域。其他區域則是其他程式使用的固定區域,每一個區域都有其獨特的作用,當然這裡我們並不需要去記,只需瞭解即可。

 

我們再來回憶一下記憶體相關概念:

RAM[Random Access Memory],記憶體可讀可寫,通常是程式設計師編寫的程式執行所需的記憶體,斷電後資料丟失,訪問速度快。

ROM(Read Only Memory),只讀儲存器,斷電後資料不會丟失,也因為ROM的特點,所以將一些計算機開機啟動時必要的程式指令固化在ROM中,處理器每次加電時都會自動執行。

圖4

所以,對於8086CPU來說,如果要訪問0x00000-0x9FFFF,則訪問的是DRAM(動態隨機訪問儲存器)。如果要問0xF0000-0xFFFFF,則真正訪問的是ROM,也就是64KB的大小。

 

而8086CPU通電之後會進行初始化工作,將CS指向0xFFFF,IP指向0x0000,因此通過CS和IP暫存器形參的地址就是0xFFFF x 0x10 + 0x0000 = 0xFFFF0(0xFFFF0是一個由段地址和偏移地址合成的實體地址),我們可以知道0xFFFF0地址正好是ROM的起始地址,而ROM中固化了8086開機時需要執行的指令,即BIOS的入口。

 

3. 基本輸入輸出系統

對於BIOS系統,相信裝過系統的同學應該不陌生了。

當處理器定位到0xFFFF0地址後,就開始取出指令並執行了,從之前的圖來看,0xFFFF0-0xFFFFF裡面儲存了一條指令,翻譯成組合語言就是:jmp 0xF000:0xE05B。

這是8086CPU開機之後,執行的第一條指令。

在這裡,jmp是跳轉(jump)的簡化形式,0xF000是要跳轉到的段地址,用來改變段暫存器CS的內容。0xE05B是目的碼段的偏移地址,一旦執行這條指令後,處理器將會從0xF000:0xE05B指定的地址處開始重新取指令執行。

 

0xFFFF0-0xFFFFF區域是屬於ROM的,在ROM中的指令主要完成硬體的診斷、檢測和初始化。就是讓硬體處於一個正常的、預設的工作狀態,也是能夠讓計算機執行起來最基本,最常規的功能。因此又把ROM中的指令叫做基本輸入輸出系統,即(Base Input & Output System BIOS) ROM

 

4. 一切從主引導扇區開始

當計算機加電後,BIOS會完成基本的初始化工作,這時計算機還沒有完全啟動起來,當BIOS完成自己的工作之後,接下來就開始交接了,如下圖所示:

圖5-計算機啟動過程

BIOS-ROM完成初始化工作後,開始通知硬碟,把主引導扇區的512個位元組載入到記憶體地址:0x0000:0x7c00處(也就是實體地址0x07c00),然後用一個jmp指令跳到那裡接著執行,即jmp 0x0000:0x7c00 。

為什麼是0x07c00地址呢?這個問題是當初的設計者定的,我們知道就行,通常主引導扇區的作用就是繼續從硬碟中讀取更多的內容並加以執行,例如像我們熟悉的windows系統就是這樣一步一步把自己執行起來的。