【從頭到腳品讀 Linux 0.11 原始碼】第一回 最開始的兩行程式碼

閃客sun發表於2021-11-21

從這一篇開始,您就將跟著我一起進入這作業系統的夢幻之旅!

別擔心,每一章的內容會非常的少,而且你也不要抱著很大的負擔去學習,只需要像讀小說一樣,跟著我一章一章讀下去就好。

話不多說,直奔主題。當你按下開機鍵的那一刻,在主機板上提前寫死的韌體程式 BIOS 會將硬碟中啟動區的 512 位元組的資料,原封不動複製到記憶體中的 0x7c00 這個位置,並跳轉到那個位置進行執行。

啟動區的定義非常簡單,只要硬碟中的 0 盤 0 道 1 扇區的 512 個位元組的最後兩個位元組分別是 0x55 和 0xaa,那麼 BIOS 就會認為它是個啟動區。

所以對於我們理解作業系統而言,此時的 BIOS 僅僅就是個程式碼搬運工,把 512 位元組的二進位制資料從硬碟搬運到了記憶體中而已。所以作為作業系統的開發人員,僅僅需要把作業系統最開始的那段程式碼,編譯並儲存在硬碟的 0 盤 0 道 1 扇區即可。之後 BIOS 會幫我們把它放到記憶體裡,並且跳過去執行。

而 Linux-0.11 的最開始的程式碼,就是這個用匯編語言寫的 bootsect.s,位於 boot 資料夾下。

通過編譯,這個 bootsect.s 會被編譯成二進位制檔案,存放在啟動區的第一扇區。

隨後就會如剛剛所說,由 BIOS 搬運到記憶體的 0x7c00 這個位置,而 CPU 也會從這個位置開始,不斷往後一條一條語句無腦地執行下去。

那我們的夢幻之旅,就從這個檔案的第一行程式碼開始啦!

mov ax,0x07c0
mov ds,ax

好吧,先連續看兩行。

這段程式碼是用匯編語言寫的,含義是把 0x07c0 這個值複製到 ax 暫存器裡,再將 ax 暫存器裡的值複製到 ds 暫存器裡。那其實這一番折騰的結果就是,讓 ds 這個暫存器裡的值變成了 0x07c0。

ds 是一個 16 位的段暫存器,具體表示資料段暫存器,在記憶體定址時充當段基址的作用。啥意思呢?就是當我們之後用匯編語言寫一個記憶體地址時,實際上僅僅是寫了偏移地址,比如:

mov ax, [0x0001]

實際上相當於

mov ax, [ds:0x0001]

ds 是預設加上的,表示在 ds 這個段基址處,往後再偏移 0x0001 單位,將這個位置的記憶體資料,複製到 ax 暫存器中。

形象地比喻一下就是,你和朋友商量去哪玩比較好,你說天安門、南鑼鼓巷、頤和園等等,實際上都是偏移地址,省略了北京市這個基址

當然你完全可以說北京天安門、北京南鑼鼓巷這樣,每次都加上北京這個字首。不過如果你事先和朋友說好,以下我說的地方都是北京市裡的哈,之後你就不用每次都帶著北京市這個詞了,是不是很方便?

那 ds 這個資料段暫存器的作用就是如此,方便了描述一個記憶體地址時,可以省略一個基址,沒什麼神奇之處。

 

ds : 0x0001

北京市 : 南鑼鼓巷

 

再看,這個 ds 被賦值為了 0x07c0,由於 x86 為了讓自己在 16 位這個真實模式下能訪問到 20 位的地址線這個歷史因素(不瞭解這個的就先別糾結為啥了),所以段基址要先左移四位。那 0x07c0 左移四位就是 0x7c00,那這就剛好和這段程式碼被 BIOS 載入到的記憶體地址 0x7c00 一樣了。

也就是說,之後再寫的程式碼,裡面訪問的資料的記憶體地址,都先預設加上 0x7c00,再去記憶體中定址。

為啥統一加上 0x7c00 這個數呢?這很好解釋,BIOS 規定死了把作業系統程式碼載入到記憶體 0x7c00,那麼裡面的各種資料自然就全都被偏移了這麼多,所以把資料段暫存器 ds 設定為這個值,方便了以後通過這種基址的方式訪問記憶體裡的資料。

OK,趕緊消化掉前面的知識,那本篇就到此為止,只講了兩行程式碼,知識量很少,我沒騙你吧。

希望你能做到,對 BIOS 將作業系統程式碼載入到記憶體 0x7c00,以及我們通過 mov 指令將預設的資料段暫存器 ds 暫存器的值改為 0x07c0 方便以後的基址定址方式,這兩件事在心裡認可,並且沒有疑惑,這才方便後面繼續進行。

後面的世界越來越精彩,欲知後事如何,且聽下回分解。

 

------- 本回擴充套件資料 -------

 

有關暫存器的詳細資訊,可以參考 Intel 手冊:

Volume 1 Chapter 3.2 OVERVIEW OF THE BASIC EXECUTION ENVIRONMEN

有關計算機啟動部分的原理如果還不清楚,可以看我之前的一篇文章瞭解一下:

計算機的啟動過程

如果想了解計算機啟動時詳細的初始化過程,還是得參考 Intel 手冊:

Volume 3A Chapter 9 PROCESSOR MANAGEMENT AND INITIALIZATION

 

------- 關於本系列 -------

 

本系列的開篇詞看這

開篇詞

本系列的擴充套件資料看這,這裡有很多有趣的資料、答疑、互動參與專案,持續更新中,希望有你的參與。

https://github.com/sunym1993/flash-linux0.11-talk

本系列全域性視角

最後,祝大家都能追更到系列結束,只要你敢持續追更,並且把每一回的內容搞懂,我就敢讓你在系列結束後說一句,我對 Linux 0.11 很熟悉。

另外,本系列完全免費,希望大家能多多傳播給同樣喜歡的人,同時給我的 GitHub 專案點個 star,這些就足夠讓我堅持寫下去了!我們下回見。

相關文章