一步步編寫操作系統 07 開機啓動bios

bios是如何甦醒的

bios其實一直睡在某個地方,直到被喚醒……前面熱火朝天的說了bios的功能和內存佈局,似乎還沒說到正題上,bios是如何啓動的呢。因爲bios是計算機上第一個運行的軟件,所以它不可能自己加載自己,由此可以知道,它是由硬件加載的。那這個硬件是誰呢?其實前面已經提到過了,相當於是隻讀存儲器ROM,因爲它一直就睡在那裏不動。

大家知道,只讀存儲器中的內容是不可擦除的,也就是它不像動態隨機訪問存儲器DRAM那樣,掉電後,裏面的數據就會丟失。這種存儲介質是用來存儲一成不變的數據,當數據寫進去後,便與日月同輝,庭前坐看花開花落,不朽於天地萬物之間,哈哈,有點誇張了。

bios代碼所做的工作也是一成不變的,而且在正常情況下,其本身是不需要修改的,平時聽說的那些主板壞了要刷bios屬於例外。於是bios順理成章地便被寫進此ROM。ROM也是塊內存,內存就需要被訪問。此ROM被映射在低端1M內存的頂部,即地址0xF0000~0xFFFFF處,可以參考表1-1頂部的bios部分。只要訪問此處的地址便是訪問了bios,這個映射是由硬件完成的。

bios本身是個程序,程序要執行,就要有個入口地址才行,此入口地址便是0xFFFF0。最重要的一點來了,知道了bios在哪裏後,cpu如何去執行它,即cpu中的cs:ip值是如何組合成0xFFFF0的。如果大家不瞭解內存的分段訪問機制,可以參考第0章,裏面有講解cpu爲什麼分段方式內存。說正事,cpu訪問內存是用段地址+偏移地址來實現的,由於在實模式之下,段地址需要乘以16後才能與偏移地址相加,求出的和便是物理地址,cpu便拿此地址直接用了。這個“段基址:段內偏移地址”的組合是0xffff:0嗎?或者是0xF000:0xFFF0?或者是更奇葩一點的組合:0xFEEE:0x1110? 或者您想出的組合比我的還奇葩,好啦,不折磨大家了,還是說正事要緊。既然做爲第一個運行的程序都沒開始執行,自然就沒辦法用軟件搞定這件事了,還是得靠硬件支持才行。在開機的一瞬間,也就是接電的一瞬間,cpu的cs:ip寄存器被強制初始化爲0xF000:0xFFF0。由於開機的時候是處於實模式,再重複一遍加深印象,在實模式下的段基址要乘以16,也就是左移4位,於是0xF000:0xFFF0的等效地址將是0xFFFF0。上面說過了,此地址便是bios的入口地址。當我給出這個地址後,不知道大家意識到什麼沒有。bios是在實模式下運行的,而實模式只能訪問1M空間(20位地址線,2的20次方是1M)。而地址0xFFFF0距1M只有16個字節了(見表1-1除標題外的第一行),這麼小的空間夠幹嗎?bios又要檢測硬件、做各種初始化工作、還要建立中斷向量表……16字節的機器指令肯定幹不了這麼多事。也許有的同學會問,超過寄存器寬度會怎麼樣呢?比如0xFFFF0+16,這樣就溢出了,由於實模式下的寄存器寬度是16位,0xFFFF0+16已經超過了其最大值0xFFFFF。溢出的部分就會回捲到0,又會重新開始,即0xFFFF0+16等於0,0xFFFF0+17等於1。

既然此處只有16字節的空間了,這隻能說明bios真正的代碼不在這,那此處的代碼只能是個跳轉指令才能解釋得通了。好,既然心裏有了推斷,那咱們就來證明這個推斷正確與否。下圖是我在bochs中抓的圖,下面給大家分析一下這圖中的信息都代表什麼。

 

首先得承認,這張圖有點超前了,這是在有了MBR後才能抓到的,否則會提示boot failed: not a bootable disk,而我們還沒有MBR,還沒有寫主引導記錄。先不管這張圖是怎麼來的啦,反正大家馬上就能夠在自己的虛擬機裏看到這張圖了,大概還有1柱香的工夫,可能是很長的那種香^—^。大家先注意框框中的內容。一共有3個,最上面左邊第1個標有cs:ip的那個框,cs寄存器的值是0xf000,ip寄存器的值是0xfff0,也就是段基址0xf000,段內偏移地址0xfff0,這個組合出來的地址便是0xffff0,這是處理器下一條待執行指令的地址。這與上面所說的bios入口地址是吻合的。另外,因爲cs和ip寄存器中存儲的是下一條要執行的指令,目前還沒有執行,也就是說,當前還沒有執行bios,這是機器剛開機的那一刻。這一刻還是值得慶祝的,因爲即使是計算機行業的同學都很少看到這一刻,何況我們讓這一刻停了下來,成爲永恆。

按理說,既然讓cpu去執行0xFFFF0處的內容(目前還不知道其是指令還是數據),此內容應該是指令才行,否則這地址處的內容若是數據而不是指令,cpu硬是把它當成指令來譯碼的話,一定會弄巧成拙鑄成大錯。現在咱們又有了新的推斷,物理地址0xFFFF0處應該是指令,繼續探索。繼續看第二個框框,裏面有條指令jmp far f000:e05b,這是條跳轉指令,也就是證明了在內存物理地址0xFFFF0處的內容是一條跳轉指令,我們的判斷是正確的。那cpu的執行流是跳到哪裏了呢?段基址0xf000左移4位+0xe05b,即跳向了0xfe05b處,這是bios代碼真正開始的地方。

第三個框框cs:f000,其意義是cs寄存器的值是f000,與我們剛剛所說的加電時強制將cs置爲f000是吻合的,正確。接下來bios便馬不停蹄的檢測內存,顯卡等外設信息,當檢測通過,並初始化好硬件後,開始在內存中0x000~0x3FF處建立數據結構,中斷向量表IVT並填寫中斷例程。

好了,終於到了接力的時刻,這是這場接力賽的第一棒,它將交給誰呢,咱們下回再說。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章