按下開(kāi)機(jī)鍵后的4.98秒,到底發(fā)生了什么
本講只為講明白下面一個(gè)問(wèn)題:
我們按下開(kāi)機(jī)鍵后究竟發(fā)生了什么?
好的,這似乎是好多人都特別想搞明白的一個(gè)問(wèn)題,有時(shí)候非常納悶,為什么一個(gè)看似這么簡(jiǎn)單的問(wèn)題,就是搜不到一個(gè)直面問(wèn)題的答案呢?
好問(wèn)題,我也不知道為什么會(huì)這樣,但我猜是因?yàn)椋?/p>
- 其一,似懂非懂的人太多,他們其實(shí)也不知道究竟發(fā)生了什么,所以只能模糊大概地說(shuō)一些教科書(shū)上的話。
- 其二,知道這個(gè)答案的人一定是大牛,大牛要么不回答這個(gè)問(wèn)題,要么就不會(huì)簡(jiǎn)單地回答這個(gè)問(wèn)題。而我呢,自認(rèn)為剛好處于兩者之間,現(xiàn)在又特別想把自己知道的分享出來(lái),所以你在這里找到了答案。
我想當(dāng)你探尋這個(gè)問(wèn)題的答案時(shí),搜到的大多數(shù)是這樣的描述:
BIOS 按照“啟動(dòng)順序”,把控制權(quán)轉(zhuǎn)交給排在第一位的存儲(chǔ)設(shè)備:硬盤(pán)。然后在硬盤(pán)里尋找主引導(dǎo)記錄的分區(qū),這個(gè)分區(qū)告訴電腦操作系統(tǒng)在哪里,并把操作系統(tǒng)被加載到內(nèi)存中,然后你就能看到經(jīng)典的啟動(dòng)界面了,這個(gè)開(kāi)機(jī)過(guò)程也就完成了。
這種描述簡(jiǎn)直太魔幻了,為什么是 BIOS 主導(dǎo)這一切?怎么叫按照啟動(dòng)順序?這個(gè)分區(qū)咋就被加載到內(nèi)存了,又咋告訴電腦操作系統(tǒng)在哪里了?我無(wú)法忍受這樣的魔幻描述,我非要把它說(shuō)得清清楚楚。
首先學(xué)一個(gè)東西,一定要有一個(gè)前置的知識(shí),我們把它當(dāng)做已知的,我不可能從原子組成分子開(kāi)始講原理。那學(xué)習(xí)計(jì)算機(jī)啟動(dòng)過(guò)程的前置知識(shí)是什么呢?我要求你已知以下幾點(diǎn):
- 內(nèi)存是存儲(chǔ)數(shù)據(jù)的地方,給出一個(gè)地址信號(hào),內(nèi)存可以返回該地址所對(duì)應(yīng)的數(shù)據(jù)。
- CPU 的工作方式就是不斷從內(nèi)存中取出指令,并執(zhí)行。
- CPU 從內(nèi)存的哪個(gè)地址取出指令,是由一個(gè)寄存器中的值決定的,這個(gè)值會(huì)不斷進(jìn)行 +1 操作,或者由某條跳轉(zhuǎn)指令指定其值是多少。
好了,只需要知道這三點(diǎn)前置知識(shí),你就能專(zhuān)業(yè)地解釋計(jì)算機(jī)的啟動(dòng)過(guò)程了。
一、為什么是 BIOS 主導(dǎo)?
都說(shuō)開(kāi)機(jī)后,BIOS 就開(kāi)始運(yùn)行自己的程序了,又硬件自檢,又加載啟動(dòng)區(qū)的。我就不服了,為什么開(kāi)機(jī)后是執(zhí)行 BIOS 里的程序?為啥不是內(nèi)存里的?為啥不是硬盤(pán)里的?
好的,不要懷疑前置知識(shí),CPU 的工作方式,就是不斷從內(nèi)存中取指令并執(zhí)行,那為什么會(huì)說(shuō)是執(zhí)行 BIOS 里的程序呢?這就不得不說(shuō)說(shuō)內(nèi)存映射了。
二、內(nèi)存映射
CPU 地址總線的寬度決定了可訪問(wèn)的內(nèi)存空間的大小。比如 16 位的 CPU 地址總線寬度為 20 位,地址范圍是 1M。32 位的 CPU 地址總線寬度為 32 位,地址范圍是 4G。你可以算算我們現(xiàn)在的 64 位機(jī)的地址范圍。
可是,可訪問(wèn)的內(nèi)存空間這么大,并不等于說(shuō)全都給內(nèi)存使用,也就是說(shuō)尋址的對(duì)象不只有內(nèi)存,還有一些外設(shè)也要通過(guò)地址總線的方式去訪問(wèn),那怎么去訪問(wèn)這些外設(shè)呢?就是在地址范圍中劃出一片片的區(qū)域,這塊給顯存使用,那塊給硬盤(pán)控制器使用,等等 。
這樣說(shuō),其實(shí)就不符合我們的前置知識(shí)了,所以可以有一種不太正確的理解方式,那就是內(nèi)存中的這塊位置就是顯存,那塊位置就是硬盤(pán)控制器。我們?cè)谙鄳?yīng)的位置上讀取或者寫(xiě)入,就相當(dāng)于在顯存等外設(shè)的相應(yīng)位置上讀取或者寫(xiě)入,就好像這些外設(shè)的存儲(chǔ)區(qū)域,被映射到了內(nèi)存中的某一片區(qū)域一樣。這樣我們就不用管那些外設(shè)啦,關(guān)注點(diǎn)仍然是一個(gè)簡(jiǎn)簡(jiǎn)單單的內(nèi)存。這就是所謂的內(nèi)存映射。
太好了,現(xiàn)在又用簡(jiǎn)單的前置知識(shí)就能解釋得通了,我們繼續(xù)往下推。
三、實(shí)模式下的內(nèi)存分布
剛剛說(shuō)到內(nèi)存中劃分出了一片一片區(qū)域給各種外設(shè),那么問(wèn)題自然就來(lái)了,哪塊區(qū)域,分給了哪塊外設(shè)了呢?如果是規(guī)定,那應(yīng)該有一張表比較好吧。嗯沒(méi)錯(cuò),還真有,它就是實(shí)模式下的內(nèi)存分布,筆者給它畫(huà)了一張圖:
在這里插入圖片描述
哎喲我真是個(gè)小天使,把比例都表現(xiàn)出來(lái)了,網(wǎng)上能再找出比我這個(gè)更直觀的請(qǐng)給我留言。實(shí)模式之后再解釋?zhuān)F(xiàn)在簡(jiǎn)單理解就是計(jì)算機(jī)剛開(kāi)機(jī)的時(shí)候只有 1M 的內(nèi)存可用。
我們看到,內(nèi)存被各種外設(shè)瓜分了,即映射在了內(nèi)存中。BIOS 更狠,不但其空間被映射到了內(nèi)存 0xC0000 - 0xFFFFF 位置,其里面的程序還占用了開(kāi)頭的一些區(qū)域,比如把中斷向量表寫(xiě)在了內(nèi)存開(kāi)始的位置,真所謂先到先得啊。
四、怎么就從 BIOS 里的程序開(kāi)始執(zhí)行了
好了,現(xiàn)在我們知道 BIOS 里的信息被映射到了內(nèi)存 0xC0000 - 0xFFFFF 位置,其中最為關(guān)鍵的系統(tǒng) BIOS 被映射到了 0xF0000 - 0xFFFFF 位置。假如我現(xiàn)在說(shuō),CPU 開(kāi)機(jī)就是執(zhí)行了這塊區(qū)域的代碼,然后巴拉巴拉一頓操作就開(kāi)機(jī)了,你肯定要噴我了,為什么就執(zhí)行到這了呢,那咋不從頭開(kāi)始執(zhí)行?
這就自然有了一種猜想,我們要用到另一個(gè)前置知識(shí)了,就是 CPU 從內(nèi)存的哪個(gè)位置取出執(zhí)行并執(zhí)行呢?是 PC 寄存器中的地址值。BIOS 程序的入口地址也就是開(kāi)始地址是 0xFFFF0(人家就那么寫(xiě)的),也就是開(kāi)機(jī)鍵一按下,一定有一個(gè)神奇的力量,將 pc 寄存器中的值變成 0xFFFF0,然后 CPU 就開(kāi)始馬不停蹄地跑了起來(lái)。沒(méi)錯(cuò),接下來(lái)這句話,可能就是你找了很久的答案,請(qǐng)做好準(zhǔn)備:
在你開(kāi)機(jī)的一瞬間,CPU 的 PC 寄存器被強(qiáng)制初始化為 0xFFFF0。如果再說(shuō)具體些,CPU 將段基址寄存器 cs 初始化為 0xF000,將偏移地址寄存器 IP 初始化為 0xFFF0,根據(jù)實(shí)模式下的最終地址計(jì)算規(guī)則,將段基址左移 4 位,加上偏移地址,得到最終的物理地址也就是抽象出來(lái)的 PC 寄存器地址為 0xFFFF0。
當(dāng)我在學(xué)習(xí)這段知識(shí)時(shí),看到這句話才讓將我心里積壓了很久的疑惑解開(kāi),多么簡(jiǎn)單粗暴的道理啊。寫(xiě)到這里我也是長(zhǎng)舒了一口氣,因?yàn)槭O碌倪^(guò)程,就幾乎只是流水賬一樣的正推了。
至于怎么強(qiáng)制初始化的,我覺(jué)得就越過(guò)了前置知識(shí)的邊界了,況且各個(gè)廠商的硬件實(shí)現(xiàn)也不一定相同,有很多辦法,也很簡(jiǎn)單。討論起來(lái)意義就不大了。
五、BIOS 里到底寫(xiě)了什么程序
好了,我們現(xiàn)在知道了 BIOS 被映射到了內(nèi)存的某個(gè)位置,并且開(kāi)機(jī)一瞬間 CPU 強(qiáng)制將自己的 pc 寄存器初始化為 BIOS 程序的入口地址,從這里開(kāi)始 CPU 馬不停蹄地向前跑了起來(lái)。那接下來(lái)的問(wèn)題似乎也非常自然地就問(wèn)出來(lái)了,那就是 BIOS 程序里到底寫(xiě)了啥?
把 BIOS 程序里的二進(jìn)制信息全貼出來(lái)也不合適,我們分析一些主要的。我們首先還是來(lái)猜測(cè),你看入口地址是 0xFFFF0,說(shuō)明程序是從這執(zhí)行的。實(shí)模式下內(nèi)存的下邊界就是 0xFFFFF,也就是只剩下 16 個(gè)字節(jié)的空間可以寫(xiě)代碼了,這夠干啥的呢?如果你有心的話應(yīng)該能猜出,入口地址處可能是個(gè)跳轉(zhuǎn)指令,跳到一個(gè)更大范圍的空間去執(zhí)行自己的任務(wù)。沒(méi)錯(cuò)就是這樣,0xFFFF0 處存儲(chǔ)的機(jī)器指令,翻譯成匯編語(yǔ)言是:
- jmp far f000:e05b
意思是跳轉(zhuǎn)到物理地址 0xfe05b 處開(kāi)始執(zhí)行(回憶下前面說(shuō)的實(shí)模式下的地址計(jì)算方式)。
地址 0xfe05b 處開(kāi)始,便是 BIOS 真正發(fā)揮作用的代碼了,這塊代碼會(huì)檢測(cè)一些外設(shè)信息,并初始化好硬件,建立中斷向量表并填寫(xiě)中斷例程。這里的部分不要展開(kāi),這只是一段寫(xiě)死的程序而已,而且對(duì)理解開(kāi)機(jī)啟動(dòng)過(guò)程無(wú)幫助,我們看后面精彩的部分,也就是 BIOS 的最后一項(xiàng)工作:加載啟動(dòng)區(qū)。
六、0x7c00 是啥
該較真的地方就是要較真,我絕對(duì)不會(huì)讓加載這種魔幻的詞出現(xiàn)在這里,我們現(xiàn)在就來(lái)把它拆解成人話。
其實(shí)這個(gè)詞也并不魔幻,加載在計(jì)算機(jī)領(lǐng)域就是指,把某設(shè)備上(比如硬盤(pán))的程序復(fù)制到內(nèi)存中的過(guò)程。那加載啟動(dòng)區(qū)這個(gè)過(guò)程,翻譯過(guò)來(lái)就是,BIOS 程序把啟動(dòng)區(qū)的內(nèi)容復(fù)制到了內(nèi)存中的某個(gè)區(qū)域。好了,問(wèn)題又自然出來(lái)了,啟動(dòng)區(qū)是哪里?被復(fù)制到了內(nèi)存的哪個(gè)位置?然后呢?我們一個(gè)個(gè)來(lái)回答。
什么是啟動(dòng)區(qū)呢?即使你不知道,你也應(yīng)該能夠猜到,一定是符合某種特征的一塊區(qū)域,于是人們把它就叫做啟動(dòng)區(qū)了,那要符合什么特征呢?先不急,不知道你有沒(méi)有過(guò)設(shè)置 BIOS 啟動(dòng)順序的經(jīng)歷,通常有 U 盤(pán)啟動(dòng)、硬盤(pán)啟動(dòng)、軟盤(pán)啟動(dòng)、光盤(pán)啟動(dòng)等等,BIOS 會(huì)按照順序,讀取這些啟動(dòng)盤(pán)中位于 0 盤(pán) 0 道 1 扇區(qū)的內(nèi)容。
至于磁盤(pán)格式的劃分,本篇就不做講解了,總之對(duì)于內(nèi)存,我們給出一個(gè)數(shù)字地址就能獲取到該地址的數(shù)據(jù),而對(duì)于磁盤(pán),我們需要給出磁頭、柱面、扇區(qū)這三個(gè)信息才能定位某個(gè)位置的數(shù)據(jù),都是描述位置的一種方式而已。
接著說(shuō), 這 0 盤(pán) 0 道 1 扇區(qū)的內(nèi)容一共有 512 個(gè)字節(jié),如果末尾的兩個(gè)字節(jié)分別是 0x55 和 0xaa,那么 BIOS 就會(huì)認(rèn)為它是個(gè)啟動(dòng)區(qū)。如果不是,那么按順序繼續(xù)向下個(gè)設(shè)備中尋找位于 0 盤(pán) 0 道 1 扇區(qū)的內(nèi)容。如果最后發(fā)現(xiàn)都沒(méi)找到符合條件的,那直接報(bào)出一個(gè)無(wú)啟動(dòng)區(qū)的錯(cuò)誤。
BIOS 找到了這個(gè)啟動(dòng)區(qū)之后干嘛呢?哦,前面說(shuō)過(guò)了是加載,就是把這 512 個(gè)字節(jié)的內(nèi)容,一個(gè)比特都不少的全部復(fù)制到內(nèi)存的 0x7c00 這個(gè)位置。怎么復(fù)制的?當(dāng)然是指令啦。哪些指令呢?這里我只能簡(jiǎn)單說(shuō)指令集中是有 in 和 out 的,用來(lái)將外設(shè)中的數(shù)據(jù)復(fù)制到內(nèi)存,或者將內(nèi)存中的數(shù)據(jù)復(fù)制到外設(shè),用這兩個(gè)指令,以及外設(shè)給我們提供的讀取方式,就能做到這一點(diǎn)啦。
啟動(dòng)區(qū)內(nèi)容此時(shí)已經(jīng)被 BIOS 程序復(fù)制到了內(nèi)存的 0x7c00 這個(gè)位置,然后呢?這個(gè)其實(shí)也不難猜測(cè),啟動(dòng)區(qū)的內(nèi)容就是我們自己寫(xiě)的代碼了,復(fù)制到這里之后,就開(kāi)始執(zhí)行唄,之后我們的程序就接管了接下來(lái)的流程,BIOS 的使命也就結(jié)束啦。所以復(fù)制完之后,接下來(lái)應(yīng)該是一個(gè)跳轉(zhuǎn)指令吧!沒(méi)錯(cuò),正是這樣,PC 寄存器的值變?yōu)?0x7c00,指令開(kāi)始從這里執(zhí)行。
咦?不知道你有沒(méi)有發(fā)現(xiàn),我們似乎不知不覺(jué)又把之前的一句魔法語(yǔ)言翻譯成人話了,開(kāi)頭我們說(shuō):
BIOS 把控制權(quán)轉(zhuǎn)交給排在第一位的存儲(chǔ)設(shè)備。
所以這句話是什么意思呢?就是 BIOS 把啟動(dòng)區(qū)的 512 字節(jié)復(fù)制到內(nèi)存的 0x7c00 位置,并且用一條跳轉(zhuǎn)指令將 pc 寄存器的值指向 0x7c00。你看,這不是也沒(méi)多幾個(gè)字嘛,就把這個(gè)問(wèn)題說(shuō)得明明白白,簡(jiǎn)簡(jiǎn)單單。
哦,對(duì)了,現(xiàn)在似乎就剩下一個(gè)問(wèn)題了,為什么非要是 0x7c00 呢?好問(wèn)題,當(dāng)然答案也很簡(jiǎn)單,那就是人家 BIOS 開(kāi)發(fā)團(tuán)隊(duì)就是這樣定的,之后也不好改了,不然不兼容。為什么不好改?我們看一個(gè)簡(jiǎn)單的啟動(dòng)區(qū) 512 字節(jié)的代碼。(代碼摘抄自《30 天自制操作系統(tǒng)》)
- ; hello-os
- ; TAB=4
- ORG 0x7c00 ;程序加載到內(nèi)存的 0x7c00 這個(gè)位置
- ;程序主體
- entry:
- MOV AX,0 ;初始化寄存器
- MOV SS,AX
- MOV SP,0x7c00
- MOV DS,AX ;段寄存器初始化為 0
- MOV ES,AX
- MOV SI,msg
- putloop:
- MOV AL,[SI]
- ADD SI,1
- CMP AL,0 ;如果遇到 0 結(jié)尾的,就跳出循環(huán)不再打印新字符
- JE fin
- MOV AH,0x0e ;指定文字
- MOV BX,15 ;指定顏色
- INT 0x10 ;調(diào)用 BIOS 顯示字符函數(shù)
- JMP putloop
- fin:
- HLT
- JMP fin
- msg:
- DB 0x0a,0x0a ;換行、換行
- DB "hello-os"
- DB 0x0a ;換行
- DB 0 ;0 結(jié)尾
- RESB 0x7dfe-$ ;填充0到512字節(jié)
- DB 0x55, 0xaa ;可啟動(dòng)設(shè)備標(biāo)識(shí)
我們看第一行:
- ORG 0x7c00
這個(gè)數(shù)字就是剛剛說(shuō)的啟動(dòng)區(qū)加載位置,這行匯編代碼簡(jiǎn)單說(shuō)就表示把下面的地址統(tǒng)統(tǒng)加上 0x7c00。正因?yàn)?BIOS 將啟動(dòng)區(qū)的代碼加載到了這里,因此有了一個(gè)偏移量,所以所有寫(xiě)啟動(dòng)區(qū)代碼的人就需要在開(kāi)頭寫(xiě)死一個(gè)這樣的代碼,不然全都串位了。
然后正因?yàn)樗袑?xiě)操作系統(tǒng)的,啟動(dòng)區(qū)的第一行匯編代碼都寫(xiě)死了這個(gè)數(shù)字,那 BIOS 開(kāi)發(fā)者最初定的這個(gè)數(shù)字就不好改了,否則它得挨個(gè)聯(lián)系各個(gè)操作系統(tǒng)的開(kāi)發(fā)廠商,說(shuō)唉我這個(gè)地址改一下哈,你們跟著改改。在公司推動(dòng)另一個(gè)團(tuán)隊(duì)改個(gè)代碼都得大費(fèi)周折,想想看這樣的推動(dòng)得耗費(fèi)多大人力。況且即使改了,之前的代碼也都不兼容了,這不得被人們罵死啊。
再看最后一行:
- DB 0x55, 0xaa
這也驗(yàn)證了我們之前說(shuō)的這 512 字節(jié)的最后兩個(gè)字節(jié)得是 0x55 0xaa,BIOS 才會(huì)認(rèn)為它是一個(gè)啟動(dòng)區(qū),才會(huì)去加載它,僅此而已。
回過(guò)頭來(lái)說(shuō) 0x7c00 這個(gè)值,它其實(shí)就是一個(gè)規(guī)定死的值,但還是會(huì)有人問(wèn),那必然有它的合理性吧。其實(shí),我的解釋也只能說(shuō)是人家規(guī)定了這個(gè)值,后人們替他們解釋這個(gè)合理性,并不是說(shuō)當(dāng)初人家就一定是這樣想的,就好比我們做語(yǔ)文的閱讀理解題一樣。
第一個(gè) BIOS 開(kāi)發(fā)團(tuán)隊(duì)是 IBM PC 5150 BIOS,當(dāng)時(shí)被認(rèn)為的第一個(gè)操作系統(tǒng)是 DOS 1.0 操作系統(tǒng),BIOS 團(tuán)隊(duì)就假設(shè)是為它服務(wù)的。但操作系統(tǒng)還沒(méi)出,BIOS 團(tuán)隊(duì)假設(shè)其操作系統(tǒng)需要的最小內(nèi)存為 32 KB。BIOS 希望自己所加載的啟動(dòng)區(qū)代碼盡量靠后,這樣比較“安全”,不至于過(guò)早的被其他程序覆蓋掉。可是如果僅僅留 512 字節(jié)又感覺(jué)太懸了,還有一些棧空間需要預(yù)留,那擴(kuò)大到 1 KB 吧。這樣 32 KB 的末尾是 0x8000,減去 1KB(0x400) ,剛好等于 0x7c00。哇塞,太精準(zhǔn)了,這可以是一種解釋方式。
七、啟動(dòng)區(qū)里的代碼寫(xiě)了啥
其實(shí)寫(xiě)到這,我這篇文章就應(yīng)該戛然而止了,因?yàn)樽畛醯哪莻€(gè)問(wèn)題已經(jīng)解決了,CPU 已經(jīng)開(kāi)始馬不停蹄地從我們預(yù)期的位置跑起來(lái)了,萬(wàn)事開(kāi)頭難,剩下的內(nèi)容,就是操作系統(tǒng)想怎么玩就怎么玩了。
但我覺(jué)得還不夠味,似乎還有些問(wèn)題縈繞在你腦海里。比如說(shuō)這個(gè)問(wèn)題:
啟動(dòng)區(qū)里的代碼寫(xiě)了啥?就 512 字節(jié)就是全部操作系統(tǒng)內(nèi)容了?
這是一個(gè)好問(wèn)題,512 個(gè)字節(jié)確實(shí)干不了啥,現(xiàn)在的操作系統(tǒng)怎么也得按 M 為單位算吧,512 個(gè)字節(jié)遠(yuǎn)遠(yuǎn)不夠呢,那是怎么回事呢?
其實(shí)我們可以按照之前的思路猜測(cè),BIOS 用很少的代碼就把 512 字節(jié)的啟動(dòng)區(qū)內(nèi)容加載到了內(nèi)存,并跳轉(zhuǎn)過(guò)去開(kāi)始執(zhí)行。那按照這個(gè)套路,這 512 字節(jié)的啟動(dòng)區(qū)代碼,是不是也可以把更多磁盤(pán)中存儲(chǔ)的操作系統(tǒng)程序,加載到內(nèi)存的某個(gè)位置,然后跳轉(zhuǎn)過(guò)去呢?
沒(méi)錯(cuò),就是這個(gè)套路。所以 BIOS 負(fù)責(zé)加載了啟動(dòng)區(qū),而啟動(dòng)區(qū)又負(fù)責(zé)加載真正的操作系統(tǒng)內(nèi)核,這配合默契吧?
由于用于啟動(dòng)盤(pán)的磁盤(pán)是人家寫(xiě)操作系統(tǒng)的廠商制作的,俗稱(chēng)制作啟動(dòng)盤(pán),所以他也肯定知道操作系統(tǒng)的核心代碼存儲(chǔ)在磁盤(pán)的哪個(gè)扇區(qū),因此啟動(dòng)區(qū)就把這個(gè)扇區(qū),以及之后的好多好多扇區(qū)(具體取決于操作系統(tǒng)有多大)都讀到內(nèi)存中,然后跳轉(zhuǎn)到開(kāi)始的程序開(kāi)始的位置。跳轉(zhuǎn)到哪里呢?這個(gè)就不像 0x7c00 這個(gè)數(shù)那么經(jīng)典了,不同的操作系統(tǒng)肯定也不一樣,也不用事先規(guī)定好,反正寫(xiě)操作系統(tǒng)的人給自己定一個(gè)就好了,別覆蓋其他關(guān)鍵設(shè)備用到的區(qū)域就好。
八、操作系統(tǒng)內(nèi)核寫(xiě)了啥
好了現(xiàn)在經(jīng)過(guò)好幾輪跳跳跳,終于跳到內(nèi)核代碼啦,我們來(lái)一起回顧一下:
- 按下開(kāi)機(jī)鍵,CPU 將 PC 寄存器的值強(qiáng)制初始化為 0xffff0,這個(gè)位置是 BIOS 程序的入口地址(一跳)
- 該入口地址處是一個(gè)跳轉(zhuǎn)指令,跳轉(zhuǎn)到 0xfe05b 位置,開(kāi)始執(zhí)行(二跳)
- 執(zhí)行了一些硬件檢測(cè)工作后,最后一步將啟動(dòng)區(qū)內(nèi)容加載到內(nèi)存 0x7c00,并跳轉(zhuǎn)到這里(三跳)
- 啟動(dòng)區(qū)代碼主要是加載操作系統(tǒng)內(nèi)核,并跳轉(zhuǎn)到加載處(四跳)
經(jīng)過(guò)這連續(xù)的四次跳躍,終于來(lái)到了操作系統(tǒng)的世界了,剩下的內(nèi)容,可以說(shuō)是整個(gè)操作系統(tǒng)課程所講述的原理,分段、分頁(yè)、建立中斷、設(shè)備驅(qū)動(dòng)、內(nèi)存管理、進(jìn)程管理、文件系統(tǒng)、用戶(hù)態(tài)接口等等。
這些名詞在操作系統(tǒng)的課程中你可能都或多或少聽(tīng)過(guò),如果你好好學(xué)了的話也一定知道大概的原理,不過(guò)像筆者這樣從頭到尾研讀過(guò) linux 內(nèi)核源碼的硬核狗來(lái)說(shuō),這些概念不只是書(shū)本上枯燥無(wú)味的概念,而是活靈活現(xiàn)在操作系統(tǒng)的每一行代碼上,有的展現(xiàn)了作者無(wú)比的智慧,有的讓我看到了作者由于硬件設(shè)定不得已做出的屈服。
如果這篇文章提起了你對(duì)操作系統(tǒng)的好奇心,建議你也找時(shí)間讀一讀,和我一起入坑,你會(huì)發(fā)現(xiàn)一個(gè)新世界的大門(mén)向你打開(kāi)了
九、參考資料
好了,這回我真的要結(jié)束了,相信如果你真的看完了全文,計(jì)算機(jī)的啟動(dòng)過(guò)程,可以說(shuō)有了比較具象的了解。如果你想深入細(xì)節(jié),也就是了解整個(gè)過(guò)程的每一點(diǎn),那可要下功夫了。