跑起了一個(gè)hello world的操作系統(tǒng) ,流程可以看2022-02-10 嘗試跑個(gè)hello world的操作系統(tǒng)。接下來要做的事情還有很多,怎么讓操作系統(tǒng)干事情?比如,最簡單的,時(shí)間怎么顯示?文件怎么創(chuàng)建?網(wǎng)絡(luò)怎么請求?UI怎么繪制?APP怎么安裝上去?等等一系列的問題,都需要去解決。那么,這些問題要怎么解決呢?我想到的方案的是看源碼,看看別人是怎么做的,才好知道自己應(yīng)該怎么做。于是,我找到了一份Linux 最簡單的源碼,0.11版本,Linux 0.11源碼。下面是看源碼做的一些筆記。
首先看看目錄結(jié)構(gòu),文件目錄不多。
├── Makefile
├── README.md
├── boot
├── cscope.files
├── fs
├── include
├── init
├── kernel
├── lib
├── mm
└── tools
boot則是啟動目錄,也就是最先執(zhí)行的代碼,所以我們先看看boot里面的。一共三個(gè)文件,其中第一個(gè)bootsect.s是啟動相關(guān)的,后面兩個(gè)后面再說
.
├── bootsect.s
├── head.s
└── setup.s
我們來打開bootsect.s文件看看里面的代碼。先看最開始的一部分
.globl begtext, begdata, begbss, endtext, enddata, endbss
.text
begtext:
.data
begdata:
.bss
begbss:
.text
SETUPLEN = 4 ! nr of setup-sectors
BOOTSEG = 0x07c0 ! original address of boot-sector
INITSEG = 0x9000 ! we move boot here - out of the way
SETUPSEG = 0x9020 ! setup starts here
SYSSEG = 0x1000 ! system loaded at 0x10000 (65536).
ENDSEG = SYSSEG + SYSSIZE ! where to stop loading
這部分代碼很容易理解,都是一些變量的定義,其中需要關(guān)注的是BOOTSEG = 0x07c0,看注釋可以知道0x07c0是啟動的首地址,也就是說,機(jī)器開機(jī)通電后,經(jīng)過一系列的自檢操作,bios啟動等等后,最后會跳到這個(gè)地址上,開始執(zhí)行操作系統(tǒng)的代碼。至于為什么是這個(gè)地址?可以不深究(因?yàn)槲乙矝]去深究,感興趣的可以去查一下然后評論告訴我)。
繼續(xù)往下走。今天我們先看兩行代碼
_start:
mov ax,#BOOTSEG !#BOOTSEG就是上面定義的0x07c0
mov ds,ax
第一行代碼就是把0x07c0賦值給ax
第二行代碼就是把a(bǔ)x賦值給ds
最后的結(jié)果是,ax和ds里面的值都是0x07c0。那么這樣做的作用是什么呢?這個(gè)要從ds的作用說起了,ds一般作為缺省的基址,何為基址?這么說吧,基址+偏移地址 = 物理地址,這里還有一個(gè)小細(xì)節(jié),ds會先左移4位再和偏移地址相加。也就是說,實(shí)際上基址是0x7c00,不過ds的值依然是0x07c0。只是在計(jì)算的時(shí)候會執(zhí)行左移的操作。所以,回到剛開始的問題 ,這兩句代碼的作用 ,其實(shí)就是保存一個(gè)基址。而保存基址的作用就是,開機(jī)時(shí)BIOS會執(zhí)行到這個(gè)地址,只有把代碼寫在這個(gè)地址上,才會被執(zhí)行到。
問題:為什么不直接把0x07c0賦值給ds呢?而要ax來中轉(zhuǎn)一下?
答:據(jù)說是不允許直接給ds賦值,匯編也有它的要求,其中三條是
- 不能直接給內(nèi)存地址賦值,必須通過DS:[偏移地址]指向內(nèi)存。
- 不能直接通過給DS賦值,必須通過寄存器中轉(zhuǎn)。
- 不能修改CS、IP的值
這里擴(kuò)展一些知識

AX:寄存器稱為累加器,常用于存放算術(shù)、邏輯運(yùn)算中的操作數(shù)或結(jié)果。另外,所有的I/O指令都要使用累加器與外設(shè)接口傳遞數(shù)據(jù)。
BX:寄存器稱為基址寄存器,常用來存放訪問內(nèi)存時(shí)的地址。
CX:寄存器稱為計(jì)數(shù)寄存器,在循環(huán)、串操作指令中用作計(jì)數(shù)器。
DX:寄存器稱為數(shù)據(jù)寄存器,在寄存器間接尋址中的I/O指令中存放I/O端口的地址。
CS:代碼段。
DS:數(shù)據(jù)段寄存器,一般用于存放數(shù)據(jù)。也是缺省的基址
SS:堆棧段。
ES:附加段。