一步步编写操作系统 08 bios跳转到神奇的内存地址0x7c00
為什么是0x7c00
計(jì)算機(jī)執(zhí)行到這份上,bios也即將完成自己的歷史使命了,完成之后,它又將睡去。想到這里,心中不免一絲憂傷,甚至有些許挽留它的想法。可是,這就是它的命,它生來(lái)被設(shè)計(jì)成這樣,在它短暫的一生中已經(jīng)為后人創(chuàng)造了足夠的精彩。何況,在下一次開(kāi)機(jī)時(shí),bios還會(huì)重復(fù)這段輪回,它并沒(méi)有消失。好了,讓傷感停止,讓夢(mèng)想前行。
先說(shuō)重點(diǎn),bios最后一項(xiàng)工作校驗(yàn)啟動(dòng)盤(pán)中,位于0盤(pán)0道1扇區(qū)的內(nèi)容。在此插播一段小告示:在計(jì)算機(jī)中是習(xí)慣以0做為起始索引的,因?yàn)槿藗円呀?jīng)習(xí)慣了偏移量的概念,無(wú)論是機(jī)器眼里和程序員眼里,用“相對(duì)”的概念,即偏移量來(lái)表示位置顯得很直觀,所以很多指令中的操作數(shù)都是用偏移量表示的。0盤(pán)0道1扇區(qū)本質(zhì)上就相當(dāng)于0盤(pán)0道0扇區(qū)。為什么稱(chēng)為1呢,因?yàn)橛脖P(pán)扇區(qū)的表示法有兩種,我們描述0盤(pán)0道1扇區(qū)用的便是其中的一種:CHS方法,即柱面Cylinder 磁頭Header 扇區(qū)Sector(另外一種是LBA方式,暫不關(guān)心),“0盤(pán)”說(shuō)的是0磁頭,因?yàn)橐粡埍P(pán)是有上下兩個(gè)盤(pán)面的,一個(gè)盤(pán)面上對(duì)應(yīng)一個(gè)磁頭,所以用磁頭Header來(lái)表示盤(pán)面。“0道”是指0柱面,柱面Cylinder指的是所有盤(pán)面上、編號(hào)相同的磁道的集合,形象一點(diǎn)描述就是把很多環(huán)疊摞在一起的樣子,組合在一起之后是一個(gè)立體的管狀。“1扇區(qū)”才是我們要解釋的部分,將磁道等距劃分成一段段的小區(qū)間,由于磁道是圓形,確切地說(shuō)是圓環(huán),所以這些被劃分出來(lái)的小區(qū)間便是扇形,所以稱(chēng)為扇區(qū)。好了,背景交待完了,重點(diǎn)來(lái)了,在CHS方式中扇區(qū)的編號(hào)是從1開(kāi)始的,不是0,不是0,原諒我說(shuō)了兩次,良苦用心你懂的,所以0盤(pán)0道1扇區(qū)是其實(shí)就相當(dāng)于0盤(pán)0道0扇區(qū),它就是磁盤(pán)上最開(kāi)始的那個(gè)扇區(qū)。而LBA方式中,扇區(qū)編號(hào)是從0開(kāi)始的。關(guān)于硬盤(pán)的知識(shí)我會(huì)在以后章節(jié)專(zhuān)門(mén)來(lái)講,這里我若沒(méi)表達(dá)清楚,大家先不要著急,只要知道MBR所在的位置是磁盤(pán)上最開(kāi)始的那個(gè)扇區(qū)就行了。繼續(xù)說(shuō),如果此扇區(qū)末尾的兩個(gè)字節(jié)分別是魔數(shù)0x55和0xaa,bios便認(rèn)為此扇區(qū)中確實(shí)存在可執(zhí)行的程序(在此先劇透一下,此程序便是久聞大名的主引導(dǎo)記錄MBR),便加載到物理地址0x7c00,隨后跳轉(zhuǎn)到此地址,繼續(xù)執(zhí)行。
這里有個(gè)小細(xì)節(jié),bios跳轉(zhuǎn)到0x7c00是用jmp 0:0x7c00實(shí)現(xiàn)的,這是jmp指令的直接絕對(duì)遠(yuǎn)轉(zhuǎn)移用法,段寄存器cs會(huì)被替換,這里的段基址是0,即cs由之前的0xf000變成了0。如果此扇區(qū)的最后2個(gè)不是0x55和0xaa,即使里面有可執(zhí)行代碼也無(wú)濟(jì)于事了,bios不認(rèn),它也許還認(rèn)為此扇區(qū)是沒(méi)格干凈呢,嘿嘿。
不過(guò),這就又拋出兩個(gè)問(wèn)題:
先回答第1個(gè),我想這個(gè)問(wèn)題不用官方解釋了,因?yàn)楣俜酱_實(shí)沒(méi)什么好說(shuō)的,不過(guò)他們出于尊重客戶,還是會(huì)像我一樣說(shuō)出類(lèi)似下面的話。
我就個(gè)人觀點(diǎn)給大家一個(gè)理由,未經(jīng)核實(shí),僅是自己一面之詞,請(qǐng)大家提高警惕,小心謹(jǐn)慎^—^。
在計(jì)算機(jī)中處處充滿了協(xié)議、約定,所以,將0盤(pán)0道1扇區(qū)做為mbr的棲身之地,我完全可以理解為規(guī)定。我們反證一下,如果不存在這個(gè)“規(guī)定”,會(huì)發(fā)生什么。當(dāng)然,此扇區(qū)最初是給bios使用的,咱們?cè)O(shè)想一下bios的工作將變成怎樣。
主引導(dǎo)記mbr是段程序,無(wú)論是位于軟盤(pán)、硬盤(pán)、或者其它介質(zhì),總該有個(gè)地方保存它。Ok,現(xiàn)在不告訴bios 它存儲(chǔ)在哪個(gè)位置了。bios只好將所有檢測(cè)到的存儲(chǔ)設(shè)備上的每一個(gè)存儲(chǔ)單位都翻一遍,挨個(gè)對(duì)比,如果發(fā)現(xiàn)該存儲(chǔ)單位最后的兩個(gè)字節(jié)是0x55和0xaa,就認(rèn)為它mbr。這就好比查字典一樣,不用偏旁部首和拼音檢索的方法,只能一頁(yè)一頁(yè)翻了。
幾經(jīng)花開(kāi)花落,找到mbr的那一刻,bios滿臉疲憊地說(shuō):“你是我找了好久好久的那個(gè)人”。mbr抬起經(jīng)不起歲月等待的臉:“難得你還認(rèn)得我,我等你等到花兒都謝了”。其實(shí)bios的心聲是:“看我手忙腳亂的樣子,你們這是要鬧哪樣啊。就那么512字節(jié)的內(nèi)容,害我找遍全世界,我們是在跑接力賽啊,下一棒的選手我都不知道在哪里……以后讓它站在固定的位置等我!”。
由于0盤(pán)0道1扇區(qū)是磁盤(pán)的第一個(gè)扇區(qū),mbr選擇了離bios最近的位置站好了,從此以后再也不擔(dān)心被bios罵了。
計(jì)算機(jī)中處處有固定寫(xiě)死的東西,還用舉個(gè)例子嗎?不用了吧?因?yàn)槿魏我粋€(gè)魔數(shù)都是啊^_^,有請(qǐng)下一個(gè)魔數(shù)0x7c00登場(chǎng)。
至于0x7c00,很久之前,比我好奇心大的人查遍了intel開(kāi)發(fā)手冊(cè)都沒(méi)找到相關(guān)的說(shuō)明。要想知道事情的來(lái)龍去脈,還是要從個(gè)人電腦的老祖宗說(shuō)起,同樣是很久很久以前……1981年8月,IBM公司生產(chǎn)了世界上第一臺(tái)個(gè)人電腦PC 5150,所以它就是現(xiàn)代x86個(gè)人電腦兼容機(jī)的祖先。說(shuō)到有關(guān)歷史的東西,不給來(lái)點(diǎn)真相就感覺(jué)氣場(chǎng)不足,上圖啦,這是IBM PC 5150,有沒(méi)有感受到計(jì)算機(jī)文化底蘊(yùn)呢。
?
既然intel開(kāi)發(fā)手冊(cè)中沒(méi)有相關(guān)說(shuō)明,那咱們就朝其它方向找答案,換句話說(shuō),既然不是cpu的硬性規(guī)定,那很可能就是代碼中寫(xiě)死的。為了搞清楚0x7c00是哪里來(lái)的,咱們先探索下 "IBM PC 5150"的bios的秘密。請(qǐng)先深深呼吸一大口氣,“0x7C00”最早出現(xiàn)在IBM 公司出產(chǎn)的個(gè)人電腦PC5150的ROM BIOS的 INT19H中斷處理程序中,說(shuō)了這么多定語(yǔ),感覺(jué)氣都喘不上來(lái)了。
通電開(kāi)機(jī)之后,bios處理程序開(kāi)始自檢,隨后,調(diào)用bios中斷0x19h,即 call int 19h。在此中斷處理函數(shù)中,bios要檢測(cè)這臺(tái)電腦有多少硬盤(pán)或軟盤(pán),如果檢測(cè)到了任何可用的磁盤(pán),bios就把它的第一個(gè)扇區(qū)加載到0x7c00.
現(xiàn)在應(yīng)該搞清楚了為什么在x86手冊(cè)里找不到它的說(shuō)明了,它是屬于bios中的規(guī)范。似乎這下好辦了,既然是bios中的規(guī)范,那肯定是IBM PC 5150 BIOS 開(kāi)發(fā)團(tuán)隊(duì)規(guī)定的這個(gè)數(shù)。
個(gè)人計(jì)算機(jī)肯定要運(yùn)行操作系統(tǒng),在這臺(tái)計(jì)算機(jī)上,運(yùn)行的操作系統(tǒng)是DOS 1.0,不清楚此系統(tǒng)要求的最小內(nèi)存是16KB還是32KB,反正PC 5150 BIOS研發(fā)工程師就假定其是32K,所以此版本bios是按最小內(nèi)存32KB研發(fā)的。
MBR不是隨便放在哪里都行的,首先不能覆蓋已有的數(shù)據(jù),其次,不能過(guò)早的被其它數(shù)據(jù)覆蓋。不覆蓋已有數(shù)據(jù),這個(gè)好理解。說(shuō)一下后面這個(gè)“其次”。通常,MBR的任務(wù)是加載某個(gè)程序(這個(gè)程序一般是內(nèi)核加載器,很少有直接加載內(nèi)核的)到指定位置,并將控制權(quán)交給它。所謂的交控制權(quán)就是jmp過(guò)去而已。之后MBR就沒(méi)用了,被覆蓋也沒(méi)關(guān)系。我說(shuō)的過(guò)早被覆蓋,是指不能讓mbr破壞自己,比如被加載的程序,如內(nèi)核加載器,其放置的內(nèi)存位置若是MBR自己所在的范圍,這不就是破壞自己了嗎,這就是我所說(shuō)的“過(guò)早”了,怎么也得等mbr執(zhí)行完才行。
重現(xiàn)一下當(dāng)時(shí)的內(nèi)存使用情況:8086cpu要求物理地址0x0~0x3FF存放中斷向量表,所以此處不能動(dòng)了,再選新的地方看看。按DOS 1.0要求的最小內(nèi)存32KB來(lái)說(shuō),MBR希望給人家盡可能多的預(yù)留空間,這樣也是保全自己的作法,免得過(guò)早被覆蓋。所以MBR只能放在32KB的末尾。MBR本身也是程序,是程序就要用到棧,棧也是在內(nèi)存中的,所以MBR雖然本身只有512字節(jié),但還要為其所用的棧分配點(diǎn)空間,所以其實(shí)際所用的內(nèi)存空間要大于512字節(jié),估計(jì)1k內(nèi)存夠用了。結(jié)合以上三點(diǎn),選擇32KB中的最后1K最為合適,那此地址是多少呢。32KB換算為16進(jìn)制為0x8000,減去1K(0x400)的話,等于0x7c00。這就是倍受質(zhì)疑的0x7c00的由來(lái),這下清楚了。可見(jiàn),加載MBR的位置是取決于操作系統(tǒng)本身所占內(nèi)存大小和內(nèi)存布局。
我想大家現(xiàn)在都心癢癢了吧,說(shuō)了這么久,cpu中運(yùn)行的都是bios的代碼,連自己一句代碼都沒(méi)跑起來(lái)呢。事不宜遲,馬上寫(xiě)一個(gè)MBR,先讓它跑起來(lái)再說(shuō)。
總結(jié)
以上是生活随笔為你收集整理的一步步编写操作系统 08 bios跳转到神奇的内存地址0x7c00的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 中信信金卡是什么意思 中信信金卡是什么卡
- 下一篇: matlab电压稳定极限,电力系统电压稳