本文來(lái)自微信公眾號(hào):低并發(fā)編程 (ID:dibingfa),作者:閃客
本系列會(huì)以一個(gè)讀小說(shuō)的心態(tài),從開(kāi)機(jī)啟動(dòng)后的代碼執(zhí)行順序,帶著大家閱讀和賞析 Linux 0.11 全部核心代碼,了解操作系統(tǒng)的技術(shù)細(xì)節(jié)和設(shè)計(jì)思想。
你會(huì)跟著我一起,看著一個(gè)操作系統(tǒng)從啥都沒(méi)有開(kāi)始,一步一步最終實(shí)現(xiàn)它復(fù)雜又精巧的設(shè)計(jì),讀完這個(gè)系列后希望你能發(fā)出感嘆,原來(lái)操作系統(tǒng)源碼就是這破玩意。以下是已發(fā)布文章的列表,詳細(xì)了解本系列可以先從開(kāi)篇詞看起。
開(kāi)篇詞
本系列的 GitHub 地址:點(diǎn)此訪問(wèn)
------- 正文開(kāi)始 -------
書(shū)接上回,上回書(shū)咱們說(shuō)到,操作系統(tǒng)的代碼最開(kāi)頭的 512 字節(jié)的數(shù)據(jù),從硬盤(pán)的啟動(dòng)區(qū)先是被移動(dòng)到了內(nèi)存 0x7c00 處,然后又立刻被移動(dòng)到 0x90000 處,并且跳轉(zhuǎn)到此處往后再稍稍偏移 go 這個(gè)標(biāo)簽所代表的偏移地址處。
那我們接下來(lái),就繼續(xù)把我們的目光放在 go 這個(gè)標(biāo)簽的位置,跟著 CPU 的步伐往后看。
: mov ax,cs mov ds,ax mov es,ax mov ss,ax mov sp,#0xFF00
全都是 mov 操作,那好辦了。
這段代碼的直接意思很容易理解,就是把 cs 寄存器的值分別復(fù)制給 ds、es 和 ss 寄存器,然后又把 0xFF00 給了 sp 寄存器。
回顧下 CPU 寄存器圖。
cs 寄存器表示代碼段寄存器,CPU 當(dāng)前正在執(zhí)行的代碼在內(nèi)存中的位置,就是由 cs:ip 這組寄存器配合指向的,其中 cs 是基址,ip 是偏移地址。
由于之前執(zhí)行過(guò)一個(gè)段間跳轉(zhuǎn)指令,還記得不?
jmpi go,0x9000
所以現(xiàn)在 cs 寄存器里的值就是 0x9000,ip 寄存器里的值是 go 這個(gè)標(biāo)簽的偏移地址。那這三個(gè) mov 指令就分別給 ds、es 和 ss 寄存器賦值為了 0x9000。
ds 為數(shù)據(jù)段寄存器,之前我們說(shuō)過(guò)了,當(dāng)時(shí)它被復(fù)制為 0x07c0,是因?yàn)橹暗拇a在 0x7c00 處,現(xiàn)在代碼已經(jīng)被挪到了 0x90000 處,所以現(xiàn)在自然又改賦值為 0x9000 了。
es 是擴(kuò)展段寄存器,僅僅是個(gè)擴(kuò)展,不是主角,先不用理它。
ss 為棧段寄存器,后面要配合?;芳拇嫫?sp 來(lái)表示此時(shí)的棧頂?shù)刂?。而此時(shí) sp 寄存器被賦值為了 0xFF00 了,所以目前的棧頂?shù)刂肪褪?ss:sp 所指向的地址 0x9FF00 處。
其實(shí)到這里,操作系統(tǒng)的一些最最最最基礎(chǔ)的準(zhǔn)備工作,就做好了。都做了些啥事呢?
第一,代碼從硬盤(pán)移到內(nèi)存,又從內(nèi)存挪了個(gè)地方,放在了 0x90000 處。
第二,數(shù)據(jù)段寄存器 ds 和代碼段寄存器 cs 此時(shí)都被設(shè)置為了 0x9000,也就為跳轉(zhuǎn)代碼和訪問(wèn)內(nèi)存數(shù)據(jù),奠定了同一個(gè)內(nèi)存的基址地址,方便了跳轉(zhuǎn)和內(nèi)存訪問(wèn),因?yàn)閮H僅需要指定偏移地址即可了。
第三,棧頂?shù)刂繁辉O(shè)置為了 0x9FF00,具體表現(xiàn)為棧段寄存器 ss 為 0x9000,?;芳拇嫫?sp 為 0xFF00。棧是向下發(fā)展的,這個(gè)棧頂?shù)刂?0x9FF00 要遠(yuǎn)遠(yuǎn)大于此時(shí)代碼所在的位置 0x90000,所以棧向下發(fā)展就很難撞見(jiàn)代碼所在的位置,也就比較安全。這也是為什么給棧頂?shù)刂吩O(shè)置為這個(gè)值的原因,其實(shí)只需要離代碼的位置遠(yuǎn)遠(yuǎn)的即可。
做好這些基礎(chǔ)工作后,接下來(lái)就又該折騰了其他事了。
總結(jié)拔高一下,這一部分其實(shí)就是把代碼段寄存器 cs,數(shù)據(jù)段寄存器 ds,棧段寄存器 ss 和?;芳拇嫫?sp 分別設(shè)置好了值,方便后續(xù)使用。
再拔高一下,其實(shí)操作系統(tǒng)在做的事情,就是給如何訪問(wèn)代碼,如何訪問(wèn)數(shù)據(jù),如何訪問(wèn)棧進(jìn)行了一下內(nèi)存的初步規(guī)劃。其中訪問(wèn)代碼和訪問(wèn)數(shù)據(jù)的規(guī)劃方式就是設(shè)置了一個(gè)基址而已,訪問(wèn)棧就是把棧頂指針指向了一個(gè)遠(yuǎn)離代碼位置的地方而已。
所以,千萬(wàn)別多想,就這么點(diǎn)事兒。那再給大家留個(gè)作業(yè),把當(dāng)前的內(nèi)存布局畫(huà)出來(lái),告訴我現(xiàn)在 cs、ip、ds、ss、sp 這些寄存器的值,在內(nèi)存布局中的位置。
好了,接下來(lái)我們應(yīng)該干什么呢?我們回憶下,我們目前僅僅把硬盤(pán)中 512 字節(jié)加載到內(nèi)存中了,但操作系統(tǒng)還有很多代碼仍然在硬盤(pán)里,不能拋下他們不管呀。
所以你猜下一步要干嘛了?
后面的世界越來(lái)越精彩,欲知后事如何,且聽(tīng)下回分解。
廣告聲明:文內(nèi)含有的對(duì)外跳轉(zhuǎn)鏈接(包括不限于超鏈接、二維碼、口令等形式),用于傳遞更多信息,節(jié)省甄選時(shí)間,結(jié)果僅供參考,IT之家所有文章均包含本聲明。