跟我一起寫操作系統(一)——10分鐘寫個操作系統

轉載註明出處:http://www.cnblogs.com/lucasysfeng/p/4846119.html

項目地址:https://github.com/lucasysfeng/lucasOS

想動手,但不知從何入手,是學習一門新知識普遍會遇到的尷尬點。筆者喜歡邊實踐邊學習理論,筆者的寫作思路是:入門的文章要避免講一些高深的理論,而應該先拋出demo,從研究demo入手,逐步加深demo的難度,從而學習這個過程中涉及到的理論知識。下面就讓我們花10分鐘寫個“操作系統”。

第一節 開發環境


我們在linux下製作軟盤、編譯內核等,因此需要linux開發環境。如果你用windows, 那麼在windows下安裝VMware, 在VMware中安裝ubuntu虛擬機,此ubuntu作為開發環境。

注:筆者的開發環境是windows--VMware--ubuntu14.04.

第二節 計算機啟動過程


寫操作系統看似是一個複雜的過程,但只要我們將過程分解,完成每一步,那麼完成一個操作系統就是水到渠成的事了。好了,我們就看一下計算機的啟動過程,看操作系統何時被啟動的。

第一步:讀取BIOS

按下電源按鈕後,計算機首先讀取一塊ROM芯片,這塊芯片裡的程序是"基本輸入輸出系統"(Basic Input/Output System),即BIOS.

第二步:硬件自檢

BIOS會檢查計算機硬件是否滿足運行條件,如果硬件出現問題,主板會發出不同含義的蜂鳴,啟動中止。

第三步:啟動順序

硬件檢查完成後,BIOS會將控制權交給下一階段的啟動程序,注意,“下一階段的啟動程序”可能存放在硬盤中,也可能存放在CD/DVD中,或者軟盤中等等,可以設置BIOS選擇從哪個設備啟動。

第四步:主引導記錄

BIOS找到了“下一階段的啟動程序”所在設備,會讀取該設備的第一個扇區,即讀取最前面的512字節,稱為主引導記錄。主引導記錄會告訴計算機下一步到哪裡去找操作系統。

第五步:bootloader

計算機讀取"主引導記錄"前面446字節的機器碼之後,運行事先安裝的“啟動管理器”bootloader,由用戶選擇啟動哪個操作系統。如果你安裝了多個操作系統,那麼就要從這步做出選擇了。

第六步:加載內核

好了,選擇操作系統(內核)後,會加載內核,下面就交給內核去處理了。

第三節 主引導記錄


我們使用虛擬機來啟動操作系統,上面的第一步和第二步我們不做,由虛擬機去完成;第三步“啟動順序”我們選擇從軟盤啟動(我們用鏡像代替,並不是真的軟盤),需要對虛擬機做下設置,選擇從軟盤啟動。下面重點來看第四步,我們寫一下“主引導記錄”,讓BIOS讀取我們寫的主引導記錄。

1. 主引導記錄代碼

1 ; 文件名 boot.asm

2

3 org 7c00h ; BIOS讀入MBR後,從0x7c00h處開始執行

4

5 ; 下面部分和10h有關中斷,10h中斷用來顯示字符

6 mov ax, cs

7 mov es, ax

8 mov ax, msg

9 mov bp, ax ; ES:BP表示顯示字符串的地址

10 mov cx, msgLen ; CX存字符長度

11 mov ax, 1301h ; AH=13h表示向TTY顯示字符,AL=01h表示顯示方式(字符串是否包含顯示屬性,01h表示不包含)

12 mov bx, 000fh ; BH=00h表示頁號,BL=0fh表示顏色

13 mov dl, 0 ; 列

14 int 10h

15

16 msg: db "hello world, welcome to OS!"

17 msgLen: equ $ - msg ; 字符串長度

18 times 510 - ($ - $$) db 0 ; 填充剩餘部分

19 dw 0aa55h ; 魔數,必須有這兩個字節BIOS才確認是MBR

2. 編譯

# nasm boot.asm -o boot.bin

如果沒有nasm,安裝它 sudo apt-get install nasm, 執行完上述命令,會生成boot.bin文件,這就是我們的主引導記錄二進制。

第四節 代碼解釋


我們再來看下主引導記錄的彙編代碼,熟悉彙編的讀者可忽略本節。

1. 為什麼MBR要從0x7c00h處開始執行?

ORG是偽指令,org 7c00h是告訴編譯器,下面代碼裝入到內存的起始地址0x7c00h處。為什麼呢,這是因為BIOS讀取主引導記錄後,會從0x7c00h處開始執行,那麼BIOS為什麼會從0x7c00h這個地址開始執行,而不是其他地址呢,這一切都要從大明湖畔的8086cpu說起。

時光飛逝,容顏易老,8086卻還是那個樣子,如圖所示:

跟我一起寫操作系統(一)——10分鐘寫個操作系統

圖 8086實物圖

跟我一起寫操作系統(一)——10分鐘寫個操作系統

圖 8086引腳圖


正如圖中所示,8086cpu的地址總線寬度為20(AD0-AD19),可以傳送220的地址信息,即可以定位220(1M)的內存地址空間,那麼這1M的內存地址空間是如何分配的呢,見下圖所示(圖是386的,我們目前只關心實模式即1M內存地址空間分配):

跟我一起寫操作系統(一)——10分鐘寫個操作系統

圖 實模式內存地址空間分佈


看到0x7c00h了嗎?0x0000h--0x7c00h這一段存的是BIOS中斷向量和一些BIOS數據等,至於到底為什麼以0x7c00h為界,本文不做討論,有興趣看這裡http://www.glamenv-septzen.net/en/view/6。

2. int 10h是幹嘛的?

當出現int 10h中斷時,表示要操作顯示器了,此時AH寄存器表示如何顯示,代碼中的AH為13h,表示要在TTY(偽終端)顯示字符,此時其他幾個寄存器都有一定的含義,如下所示:

ES:BP -- 顯示字符串的地址 CX -- 顯示字符串的長度

BH -- 頁碼 BL -- 屬性(若AL=00H或 01H)

DH -- 行 DL -- 列

AL -- 顯示輸出方式

下面一段代碼也就不難理解了:

1 mov ax, cs

2 mov es, ax

3 mov ax, msg

4 mov bp, ax ; ES:BP表示顯示字符串的地址

5 mov cx, msgLen ; CX存字符長度

6 mov ax, 1301h ; AH=13h表示向TTY顯示字符,AL=01h表示顯示方式(字符串是否包含顯示屬性,01h表示不包含)

7 mov bx, 000fh ; BH=00h表示頁號,BL=0fh表示顏色

8 mov dl, 0 ; 列

9 int 10h

3. $和$$是什麼意思?

$ 是當前位置

$$ 是段開始位置

下面兩句就不難理解了:

1 msgLen: equ $ - msg ; 字符串長度

2 times 510 - ($ - $$) db 0 ; 填充剩餘部分

4. 為什麼要有0xaa55h魔數?

BIOS檢查完硬件後,會尋找下一個設備來啟動計算機,BIOS找到一個設備後,會讀取該設備的第一個扇區,也就是讀取最前面的512個字節。如果這512個字節的最後兩個字節是0x55和0xAA,表明這個設備可以用於啟動;如果不是,表明設備不能用於啟動,控制權於是被轉交給"啟動順序"中的下一個設備。

第五節 製作軟盤鏡像,加入主引導記錄


如何用dd命令製作軟盤,自行google之。

1. 首先,我們製作一個空的軟盤鏡像empty.img: 

# dd if=/dev/zero of=empty.img bs=512 count=2880

2. 之後,我們製作一個包含主引導記錄boot.bin的鏡像文件lucasOS.img:

# dd if=boot.bin of=lucasOS.img bs=512 count=1

3. 然後,將empty.img中1個扇區後的數據拷貝到lucasOS.img的後:

# dd if=empty.img of=lucasOS.img skip=1 seek=1 bs=512 count=2879

這樣就做成了一個大小為1.44Mb的包含主引導記錄的軟盤鏡像文件lucasOS.img。

4. 將虛擬機ubuntu中的文件lucasOS.img拷貝到windows下(鼠標直接拖拽,如果不行google之)。

第六節 用軟盤鏡像lucasOS.img啟動一個空的虛擬機


1. VMware創建空的虛擬機,去掉開機從CD/DVD啟動選項。

跟我一起寫操作系統(一)——10分鐘寫個操作系統

2. 網絡選擇host-only模式。

跟我一起寫操作系統(一)——10分鐘寫個操作系統

3. 選擇從軟盤驅動,路徑選擇上一節已經拷貝到windows下的鏡像lucasOS.img.

跟我一起寫操作系統(一)——10分鐘寫個操作系統

4. 開啟虛擬機電源,看到如下畫面,恭喜你,成功了。

跟我一起寫操作系統(一)——10分鐘寫個操作系統

這就是最基礎的操作系統了

好了,至此,我們完成了主引導記錄,後續會討論載入內核,並進一步討論進程管理、內存管理、文件系統和中斷等等。

代碼獲取


本系列GitHub地址 https://github.com/lucasysfeng/lucasOS.git

獲取代碼:

# git clone https://github.com/lucasysfeng/lucasOS.git

本講的代碼是code/chapter1,筆者已經將上面的命令集成到Makefile中了,讀者只需進入目錄,按ReadMe.txt執行即可。有問題請留言。


分享到:


相關文章: