本系列將以一種新奇的閱讀心態(tài)閱讀和欣賞Linux 0.11的所有核心代碼,從啟動后的代碼執(zhí)行序列中了解操作系統(tǒng)的技術細節(jié)和設計思路。
你會跟著我,看著一個操作系統(tǒng)從無到有,最后一步一步實現它復雜而精致的設計看完這個系列,希望你能感嘆原來操作系統(tǒng)源代碼就是這個蠢東西以下是已發(fā)表文章的列表想詳細了解這個系列,可以從開篇的話開始
開場白
第一次輸入的前兩行代碼
第二次,給自己挪個位置。
第三遍,做最基本的準備工作。
本系列GitHub地址:點擊此處訪問
—正文開始—
上一次,上一次,我們說操作系統(tǒng)的一些最基本的準備已經準備好了。
如圖,操作系統(tǒng)此時只有幾行代碼,數據段寄存器ds和代碼段寄存器cs都設置為0x9000,方便代碼跳轉和數據訪問此外,堆棧頂部的地址ss:sp被設置為0x9FF00,距離代碼的位置0x90000足夠遠,以確保堆棧在下降時不會輕易撞到代碼的位置
簡單來說就是設置數據的數據段如何訪問,代碼的代碼段如何訪問,棧頂指針如何訪問,也就是做一個初步的內存規(guī)劃從CPU的角度來看,訪問內存的地方只有三個
做完基礎工作,就該輪到新的了我們繼續(xù)往下看
load_setup:movdx,# 0x0000drive0,head0movcx,# 0x0002扇區(qū)2,track0movbx,# 0x0200地址=512,in0x9000movax,# 0x 0200+4,service2,nrofsectorsint0x13readitjncok _ load _ setupok—continuemovdx,#0x0000movax,# 0x0000resettedisketteint 0x 13 jmp load _ setup ok _ load _ setup:...
這里有兩個我們還沒見過的int指令。
注意,這個int是匯編指令,不是高級語言中的整數變量Int13表示啟動0x13中斷在該指令中,dx,cx,bx和ax被指定為該中斷程序的參數
中斷是什么如果你不懂,就不要管它如果你就是放不下,那就看看我之前的文章:認真談中斷,很詳細
簡而言之,這個中斷發(fā)起后,CPU會通過這個中斷號找到對應中斷處理程序的入口地址,跳轉執(zhí)行,邏輯上相當于執(zhí)行一個函數0x13中斷的處理程序是BIOS預先寫好的,是讀盤相關函數的函數
進入操作系統(tǒng)內核后,中斷處理程序需要我們自己重新編寫在后面的章節(jié)中,你會不斷看到每個模塊都注冊了自己相關的中斷處理程序,所以不用擔心此時,為了方便起見,請?zhí)崆笆褂肂IOS為我們編寫程序
可見,即使是操作系統(tǒng)的源代碼,有時為了自身的方便也需要調用現成的函數,并不是車輪建設者要完全從零開始構建。
這段代碼的注釋已經寫的很清楚了這么說吧,最后的功能是啟動硬盤第二個扇區(qū),將數據加載到內存0x90200,一共加載四個扇區(qū)這實際上是如圖所示的情況
可以看到,如果復制成功,就會跳轉到標簽ok_load_setup如果失敗了,你會重復執(zhí)行這段代碼,也就是再試一次那么讓我們忘記重試邏輯,只看成功后跳轉的標簽ok_load_setup后的代碼
確定_加載_設置:...movax,#0x1000moves,ax,0x10000callread_it段...jmpi0,0x9020
這段代碼省略了很多非主邏輯代碼,比如輸出加載系統(tǒng)...屏幕上的這個字符串是為了防止用戶厭倦等待。
其余的主要代碼就寫在這里,只有幾行它的作用是將硬盤第6扇區(qū)的240個扇區(qū)加載到內存0x10000中,與上一個相同
至此,整個操作系統(tǒng)的所有代碼都已經從硬盤移到了內存中。
然后通過一個大家熟悉的段間跳轉指令jmpi0,0x9020,跳轉到0x90200,也就是硬盤第二個扇區(qū)開頭的內容。
這里的內容是什么別急,借此機會說一下整個操作系統(tǒng)的編譯過程
1.將bootsect.s編譯成bootsect,放在硬盤的1扇區(qū)。
2.把setup.s編譯成setup,放在硬盤的2~5個扇區(qū)。
3.將所有剩余的代碼編譯到系統(tǒng)中,放入硬盤的下240個扇區(qū)。
所以整個路徑是這樣的。
所以我們要跳轉到的內存中0x90200處的代碼是從硬盤第二扇區(qū)開始加載到內存中的在第二個扇區(qū)的開頭,這是setup.s文件中的第一行代碼
這是什么代碼這個我們以后再說,但是先打開setup.s文件看一下
start:movax,# 0x9000thisisdoneinbootsectalready,butmovds,axmovah,# 0x03readcursorposxorbh,bhint0x10saveitinknownplace,con_initfetchesmov,dx,itfrom0x90000。
好了,到目前為止,你覺得,我去,前面編譯放在硬盤上的位置,和后面代碼寫的跳轉地址耦合的這么強嗎如果整件事都是錯的呢
對,就是這樣你怎么想呢操作系統(tǒng)剛建立的時候,完全是自己安排的,一個字節(jié)都不能有偏差就是這么強的耦合,需要小心翼翼,需要大腦時刻保持清醒,規(guī)劃好自己寫的代碼在硬盤什么地方編譯存儲,然后會加載到內存里,不能搞混
但也很有好處,就是在這個階段,你完全知道如何設計和規(guī)劃跳轉和數據訪問的每一步,沒有黑箱。
不像我們寫高級語言的時候,我們不知道底層幫助我們做了多少工作雖然這樣讓程序員不用擔心底層細節(jié),但是遇到問題或者想知道原理的時候就很煩了
更何況,之所以在頂層可以為所欲為,是因為很多底層的細節(jié)根本不需要考慮,非常省心正是因為像今天以及之后的每一章各種底層代碼都做了大量精心的準備
好了,本文到此結束。這也標志著我們已經完成了第一個操作系統(tǒng)源文件bootsect.s,開始進入下一個文件設置. s!
我們身后的世界越來越精彩欲知后事如何,且聽下回分解
鄭重聲明:此文內容為本網站轉載企業(yè)宣傳資訊,目的在于傳播更多信息,與本站立場無關。僅供讀者參考,并請自行核實相關內容。