怎樣寫一個簡單的操作系統?(原文標題:How to write a simple operating system) 分類: 翻譯 2011-01-26 01:10 3175人閱讀 評論(3) 收藏

分類: 翻譯2011-01-26 01:10 3175人閱讀 評論(3) 收藏 舉報

 

怎樣寫一個簡單的操作系統?

 

 

翻譯:magictong(童磊)2011年1月

版權:Mike Saunders和Mike OS的全體開發 2009年

原文地址:http://mikeos.berlios.de/write-your-own-os.html

 

P.S.很簡單的一篇關於操作系統編寫的入門文章,本身可能沒什麼特別深的技術含量,但是不失爲一個繼續研究的起點,當時隨意瀏覽了一下,覺得還不錯,就決定把它翻譯出來,歡迎大牛批評和斧正,可能有一些翻譯錯誤,也希望不吝賜教。

——magictong 2010.01.26 晨

 

 

目錄

 

簡介

必備知識

計算機啓動

彙編入門

第一個操作系統

進階

 

 

簡介

本文主要介紹怎樣編寫和構建您的第一個,基於x86彙編語言的操作系統。它解釋了計算機開機的基本過程,一些基本的彙編語言,以及怎樣進一步提升自己這方面的技術。最終編寫的操作系統將是非常小的一個程序(僅僅是一個系統引導程序),並且只有非常少的功能,但它是您在這方面進一步進行研究和探索的一個起點。

在您閱讀了本文之後,如果您想更進一步在這方面進行探索並擴展您的能力,您可以繼續看一下Mike OS(譯註:http://mikeos.berlios.de/)項目,這是一個更大更完備的x86彙編語言操作系統。

 

 

必備知識

編程經驗是必不可少的。如果你已經使用一些高級語言像PHP和JAVA之類的做過一些開發,那再好不過,但是,你最好還要具備一些更底層語言的知識,像C之類的,特別是對一些內存和指針的問題比較熟悉。

在本文中,我們將使用Linux操作系統來作開發平臺,當然,在Windows上面進行操作系統開發也是可以是的,但是顯然在Linux上面開發更加的簡單,因爲你需要點擊幾下鼠標敲擊幾個命令就可以獲得一套完整的開發工具。 在Linux上面製作軟盤和CD – ROM也更方便,你不需要安裝一些繁瑣的驅動程序。

現在安裝Linux是非常容易的,如果你不想在你的計算機上面安裝雙系統,你可以把Ubuntu(譯註:Ubuntu是Linux操作系統中的一個)安裝在VMware或者VirtualBox上面,進入Ubuntu之後,只需要在命令行窗口鍵入下面的命令,就可以獲得本文所需要的全部工具,簡單把:

sudo apt-get install build-essential qemu nasm

通過這個命令你可以獲得開發工具(編譯器等等),QEMU PC仿真器和NASM的彙編器等等,彙編器能把彙編語言轉換原生的機器碼而組成可執行文件。

 

 

計算機啓動

如果你正在爲一個x86系統(這是最好的選擇,因爲有大量的文檔可以參考)的計算機寫操作系統,你需要理解計算機啓動過程的基本知識,不過幸運的是,你現在不需要去了解圖形驅動程序和網絡協議等等複雜的部分,因此你可以專注於最本質的地方。

當計算機通電之後,它最開始執行的是BIOS(基本輸入/輸出系統)程序,它本質上是一個內置在系統中的微型操作系統。BIOS執行一些基本的硬件檢測(如內存檢查等),並且繪製一些特殊的圖形(如DELL的LOGO)或者打印一些診斷文本到屏幕上。做完這些之後,它開始從某個可以找到的媒介上加載你的操作系統。然後大部分的計算機會跳轉到硬盤驅動器並開始執行主引導區(MBR)的代碼,主引導區是指一個硬盤驅動器最開始的512個字節的部分。有些計算機會嘗試在一個軟盤(啓動扇區)或者CD – ROM上找到可執行代碼。

計算機具體會去哪裏尋找引導程序,依賴於引導順序 - 你可以在BIOS的選項屏幕上明確的指定它。BIOS從選中的媒介(譯註:硬盤,軟盤,CD - ROM)中加載512字節到內存中,然後開始執行它。這就是(傳說中的)引導程序,這個小程序然後加載操作系統內核或一個更大一些的引導程序(例如,Linux系統下的GRUB / LILO)。爲了告訴操作系統它是一個引導扇區,512字節的引導程序在最後面有兩個特殊的數字作標記,我們稍後將介紹它。

在計算機啓動、引導的時候,有一個有趣的地方。在以前,基本上所有的計算機都配有一個軟盤驅動器,因此BIOS配置的是從軟盤驅動器啓動,然而,現在的大部分的個人電腦都沒有軟盤驅動器,而是配備了一個CD – ROM,爲了滿足這種需要,專門開發了一個hack(譯註:a hack直譯不知道怎麼翻譯,大概就是類似外掛一樣的意思,干預引導程序,呵呵)程序。當計算機從CD - ROM啓動的時候,它可以模擬一個軟盤出來,BIOS將從CD – ROM驅動器上面讀取一個數據塊並加載,然後執行它,就好像它是一個軟盤一樣。這對於操作系統開發者來說是非常(譯註:原文用了incredibly,表示非常非常有用的,呃)有用的,因爲我們可以只製作一個引導我們的操作系統的軟盤,但是依然可以引導只有CD – ROM設備的機器。(相對來說,軟盤是比較容易使用和操作的,而CD - ROM的文件系統則顯然要複雜得多)。

 

因此總的來說,啓動過程如下:

1、  打開電源,計算機啓動然後開始執行BIOS代碼。

2、  BIOS程序尋找軟盤或硬盤驅動器等多種媒介(譯註:可以在BIOS中設定尋找順序)。

3、  BIOS將從指定的媒介中加載512字節的引導扇區,然後開始執行它。

4、  引導扇區然後再去加載操作系統本身,或者更加複雜的引導程序。

 

對於Mike OS,我們寫了一個512字節的引導程序,並將它製作成一個軟盤映像文件(虛擬軟盤)。對於只有CD – ROM的驅動器,我們可以把該映像文件拷貝到CD上。不過無論使用哪種方式,BIOS都將正常加載它,就好像它是一個軟盤一樣,並開始執行它。之後我們就可以控制整個系統了!

 

 

彙編入門

現代操作系統大部分都是使用C或者C++編寫,因爲這對於可移植性和代碼維護來說是至關重要的,但是這不是免費的午餐,在處理上就增加了一個更加複雜的層次。編寫您的第一個操作系統,建議您最好是使用彙編語言,在Mike OS中也是使用的彙編語言,雖然彙編語言顯得冗餘和不可移植,但是您不用去擔心編譯器和鏈接器,這是它的優點。另外,此外,你需要一點彙編代碼去啓動任何操作系統。

彙編語言(或俗稱的“彙編”)是表示CPU執行指令的一種文本化方式。例如,一條表示在CPU中移動數據的指令用二進制表示可能11001001 01101110,這種表示方法非常令人難以記憶(譯註:簡直是發狂的)。彙編語言使用一些助記符,如mov ax, 30來代替這些指令。彙編指令直接與機器碼CPU指令相關聯,我們就不用再關心那些看起來毫無意義的二進制數字。

跟大多數的編程語言一樣,彙編語言也是有序的指令流。你可以在不同的指令位置進行跳轉,也可以設置子程序或者函數,但是它比C#之類的程序要小得多。使用匯編,你無法給出一個打印“Hello World”到屏幕的指令,因爲CPU根本沒有屏幕這樣一個概念!相反,你可以直接操作內存,控制RAM(譯註:隨機存取存儲器),在它們上面進行算術運算並把結果放到正確的位置。聽起來很瘋狂麼?但是彙編並不是很難掌握,雖然在一開始你會覺得有點陌生和不可理解。

在彙編語言層次,並沒有高級語言中類似變量這樣的一些抽象的概念。你所能做的就是設置Registers(譯註:寄存器)的值,Registers是內置在CPU中的高速存儲設備。你可以把數據存放在Registers上面並且執行計算。在16位模式下,這些寄存器只可以存儲0到65535之間的數字。下面是一個典型的X86 CPU的基本寄存器列表:

 

AX, BX, CX, DX

通用數據寄存器,可以用於存儲正在使用的數據。譬如,你可以使用AX存儲鍵盤上剛剛按下的字符;使用CX作爲一個循環計數器。(注:16位寄存器可以被分割爲8位寄存器使用,比如,AH/AL,BH/BL等等)

SI, DI

源操作數和目的操作數寄存器。用於指向內存中的某個地址來獲取和存儲數據。

SP

堆棧寄存器(稍後再解釋)。

IP(sometimes CP)

指令寄存器,存放着即將要執行的下一條指令的內存地址,當一條指令執行結束後,指令寄存器進行自增(譯註:不是增加1,而應該是自增下一條指令的長度)以便於指向接下來的指令地址。你可以改變指令寄存器的內容使得代碼邏輯跳轉執行(譯註:一般不能直接改動,而是通過call和ret之類的指令間接改動)。

(譯註:32位系統寄存器的位數增加到32位,相應的名稱叫EAX, EBX, ECX, EDX等等)

 

因此你可以像使用變量一樣用這些寄存器來存儲數據,只不過它們在數據大小和用途上比較固定。有一類比較特殊的寄存器,叫做段寄存器,這主要是因爲舊的計算機系統的限制,內存的處理被限制在一個64K的叫做段的塊上。這是一個非常麻煩而混亂的問題,不過幸運的是,你現在不用擔心,因爲目前你即將編寫操作系統遠遠小於一千字節,在Mike OS裏面,我們把程序侷限在一個64K的段裏面,這樣我們就不必去招惹麻煩的段寄存器了。

堆棧是從主存儲器上面專門開闢的一塊區域,用來存儲臨時信息。之所以叫着棧是因爲一個數字堆積在另一個數字是上面,很形象的一種稱呼。你可以想象一下,如果你有一個品客(譯註:國際著名薯片品牌)的包裝筒,如果你往裏面順序放入一張撲克牌,一個iPod Shuffle和一個啤酒杯墊子,那麼你再把它們拿出來的時候就是完全相反的順序了(先是啤酒杯墊子,然後是ipod shuffle,最後是撲克牌)。這跟數字也是一樣的,如果你把數字5,7和15順序壓入堆棧,那麼你彈出這些數字的時候順序就剛好相反了,先是數字15,然後是數字7,最後是15。在彙編裏面,你可以把寄存器的值壓到堆棧上,處理完某些事情後在把它們從堆棧上彈回到寄存器中,這個主要用於當你想使用某些寄存器去幹別的事情的時候,而你又不想破壞現在寄存器裏面的值,那麼你可以把寄存器裏面的值壓入堆棧,等處理完其他事情後再從堆棧上把值彈回寄存器中。

計算機的內存可以看作一個線性的空間,就像一個個連續的鴿子籠一樣,它的範圍從0開始直到你所安裝的內存的最大值(現代計算機的內存高達數百萬字節)。例如,你可能怎在使用瀏覽器來查看內存中53634246字節的一個文檔文件,但是我們人類的計數是基於10的冪的(10,100,1000等等,也就是十進制),而計算機計數則是基於2的冪的(因爲計算機使用2進制更好)。爲了能更好的描述數字,我們使用16(基於16的冪)進制,可以對照下面的表格來理解:

 

10進制

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

16進制

0

1

2

3

4

5

6

7

8

9

A

B

C

D

E

F

10

11

12

13

14

        

如圖中表格所示,我們平時都是使用的十進制計數系統,用0-9計數,十六進制計數系統使用0-F進行計數,對於沒有接觸過進制的人來說,可能有點困惑,不過沒關係,很快你就能學會它。在彙編語言裏面,我們通過在數字字符後面加上‘h’表示一個十六進制的數字,比如0Ah就表示十進制的10(你也可以通過加一個0x前綴的方式來表示十六進制,例如0x0A)。

讓我們先來看看幾條常用的彙編指令,主要是數據傳送指令,比較指令和數學計算指令等等,它們將是構建你的操作系統的基石。總共大概有數百條彙編指令,不過你不需要全部記住它們,熟悉常用指令就可以了,因爲90%的時間我們都是在使用其中的極少數指令。

 

mov

數據傳送指令,從寄存器或者內存中移動數據到另一個地方。例如:mov ax, 30 表示把數據30傳送到寄存器ax中。要獲取內存中的數據,如果它被某個寄存器指向,你可以使用方括號。例如,如果bx中的數據是80,那麼mov ax, [bx]的意思就是,獲取內存地址爲80的處的數據,並把它傳送到ax寄存器中。你也可以使用這條指令在兩個寄存器之間傳送數據,譬如:mov bx, cx。

add/sub

數據加減指令,add ax, FFh表示加上一個FFh(十六進制數,表示十進制的255)到ax寄存器中,sub指令的使用也是一樣的,sub dx, 50。

cmp

比較指令。用來比較一個寄存器和一個數字,例如,cmp cx, 12的意思是將cx中的數據和12進行比較。根據比較的結果,更新CPU的標誌寄存器(譯註:標誌寄存器是用來存儲最後一次運算結果的狀態的特殊寄存器)。在這個例子裏面,如果12大於cx中存儲的值,比較結果是一個負數,那麼標誌寄存器的符號標誌位就會標識爲負,我們會在下面的指令中用到這種信息……

jmp/jg/jl …

跳轉指令。跳轉到代碼的另一個地方。jmp label是無條件跳轉指令,能跳轉到我們定義的標籤位置,也就是label。跳轉指令中使用更多的是條件跳轉指令,它根據之前的指令設置在狀態寄存器中值,有條件的進行跳轉。例如:如果一條cmp指令執行完成後,確定寄存器比與它比較的數值要小,你可以使用指令jl label(如果小於則跳轉到標籤label),類似,jge label的意思是,如果cmp左邊的值比右邊和它進行比較的數值大或者等於則跳轉到label。

int

中斷指令。中斷程序的執行並且跳轉到內存中的一個指定的地方。操作系統觸發一箇中斷有點類似高級語言中的子程序。例如,在MS-DOS裏面,21h中斷表示調用一個DOS的服務(例如打開一個文件)。通常,在ax寄存器中存入一個數值,然後調用中斷等待結果(結果也是通過寄存器傳回)。如果你是完全從頭寫一個操作系統,你可以使用int 10h,int 13h, int 14h或int 16h等等指令來調用BIOS的中斷,可以完成打印字符串,從一個磁盤讀取一個扇區等等任務。

 

我們看看這些指令的更多一些細節,思考如下的彙編代碼片斷:

 

         mov bx, 1000h

         mov ax, [bx]

         cmp ax, 50

         jge label

         ...

 

label:

         mov ax, 10

 

我們來看看這幾條指令,第一條指令,把1000h傳送到寄存器bx中。然後,第二條指令是把bx寄存器指向的內存單元的數據傳送到ax寄存器中,如果我們僅僅使用mov ax, bx,那麼它的意思就是簡單的把數據1000h傳送到ax寄存器中,但是在bx上使用了方括號之後,意義就變化了,不是簡單的把數據從bx傳送到ax了,而是傳送bx所指向的內存的內容到ax寄存器中。具體到這條指令,bx中是1000h,那麼它的意思就是說把內存地址1000h中的數據傳送到ax寄存器中。

因此,如果內存地址1000h中存放的數據是37,那麼執行完上面的第二條指令之後,ax中存放的數據將是37,接下來,將是使用cmp指令對ax中的數據和50(十進制數50,注意,並沒有h後綴)進行比較,之後的jge指令將作用在cmp的比較結果上,因爲cmp指令執行之後,會設置標誌寄存器的某些標誌位,指令jge label的意思就是說,如果之前的比較結果是大於或者等於則跳轉到label標籤的位置繼續執行,因此,如果ax寄存器中的數據不比50小的話,程序就跳轉到label標籤處執行,否則,程序繼續執行“…”部分的代碼。

最後一點:您可以使用db(字節定義)標識將數據插入到程序中。與數據庫程序中插入數據(定義字節)指令。例如,定義一個字符串,可以使用一段以0結尾的連續字節來表示。如下所示:

 

mylabel: db 'Message here', 0

 

在彙編代碼中,我們就可以知道一個以0結尾的字符串能通過mylabel: position找到。我們還可以設置單個字節的值,然後在其他地方像一個變量一樣使用它,看下面的代碼:

 

foo: db 0

 

現在foo:在代碼中指向單字節,在這種情況下,Mike OS將是可寫的,因爲整個操作系統都被拷貝到了內存中。因此,你可以使用下面的指令:

 

mov byte al, [foo]

 

這條指令的意思是把foo指向的一個字節傳送到al寄存器中。

這就是X86體系彙編語言的基本要點,已經足夠讓你開始後面的學習了。當你編寫一個操作系統的時候,隨着你的進展,你需要學習更多的彙編知識和其他知識,你可以參考Resources部分的輔導資料(譯註:沒有找到所謂的輔導資料)。

 

 

第一個操作系統

現在,你已經可以開始編寫您的第一個操作系統內核了!當然,這將是一個極其精簡的部分,僅僅是一個512字節的引導扇區,就跟之前敘述的一樣,但是,它是您進行進一步探索的一個起點。複製粘貼下面的代碼到一個名爲myfirst.asm的文件中,並把它保存到你的home目錄——這就是你的第一個操作系統的源代碼。O(∩_∩)o

BITS 16

 

start:

       mov ax, 07C0h          ; Set up 4K stack space after this bootloader

       add ax, 288         ; (4096 + 512) / 16 bytes per paragraph

       mov ss, ax

       mov sp, 4096

 

       mov ax, 07C0h          ; Set data segment to where we're loaded

       mov ds, ax

 

 

       mov si, text_string    ; Put string position into SI

       call print_string ; Call our string-printing routine

 

       jmp $                   ; Jump here - infinite loop!

 

 

       text_string db 'This is my cool new OS!', 0

 

 

print_string:                     ; Routine: output string in SI to screen

       mov ah, 0Eh              ; int 10h 'print char' function

 

.repeat:

       lodsb                   ; Get character from string

       cmp al, 0

       je .done              ; If char is zero, end of string

       int 10h                ; Otherwise, print it

       jmp .repeat

 

.done:

       ret

 

 

       times 510-($-$$) db 0      ; Pad remainder of boot sector with 0s

       dw 0xAA55         ; The standard PC boot signature

 

讓我們一步步的來分析這段代碼。BITS 16這條並不是一個x86系統的指令,這裏僅僅是告訴NASM彙編器,接下來我們將工作在16位模式。NASM將把下面的指令翻譯成原生的x86二進制代碼。然後是一個start: 標籤,在文件的開頭,這個標籤不是必須的,不過是一個好的編碼習慣,分號(;)用來進行代碼註釋,裏面可以寫任何你覺得對代碼註解有用的東西,它不會被執行。

接下來的6行代碼對我們來說並不是特別的有意義,這幾行代碼用來設置段寄存器的值,以便於堆棧指針(SP)能方便的知道我們的堆棧數據在哪兒,我們的數據段又在哪個位置。之前提到過,段是老的16位系統遺留下來一種混亂噁心的管理內存的東西,不過我們這裏僅僅是設置段寄存器的值,然後你就忘了它吧(代碼中引用的07C0H     是BIOS加載我們的代碼的等效段地址,因此我們從這個地方開始)。

接下來的代碼開始有意思起來,mov si, text_string這行的意思是,把text_string的地址複製到si寄存器中。然後是一條call指令,call指令類似於BASIC語言中的Go Sub或者C語言中函數調用。call指令含義是:跳轉到到指定的代碼塊執行,當任務完成後再回到call指令的下一條指令繼續執行。

對於call指令,代碼是怎麼做到跳轉執行之後又正常返回的?當我們使用一個call指令的時候CPU增加IP(指令指針)寄存器的值,並把該值壓到棧上。你可以回顧一下之前對棧的解釋,棧是一種後進先出(譯註:傳說中的LIFO)的內存存儲結構。所有的事情在最開始通過設置堆棧指針(SP)和堆棧段指針(SS)的值做好了,爲棧專門開闢了一塊空間,因此你能把臨時數據存放在這個上面而不會覆蓋我們本身的代碼。

所以,call print_string的意思就是說,跳轉到print_string分支去執行,並且把call指令的下一條指令的地址壓入堆棧中,當從分支返回後,再把該地址從堆棧上彈出並從該地址處的指令接着執行。運行到了print_string分支之後,這個分支的代碼使用BIOS輸出文本到屏幕上面。首先把0Eh傳送到ah寄存器裏面(ax寄存器的高8位),然後lodsb指令從si寄存器指向的地址處取出一個字節存放到al寄存器(ax寄存器的低8位)裏面,接下來將使用cmp指令判斷取出來的這個指令是否爲0,如果等於0,說明已經是字符串的末尾,將退出打印(跳轉到.done標籤)。

如果取出來的值不是0,那麼將通過int 10h指令觸發中斷進入BIOS,在BIOS裏面,將會讀取ah寄存器的值,之前設置的是0Eh,這個值對於BIOS來說就是打印al寄存器中的字符到屏幕上的意思。因此BIOS首先打印我們的字符串裏面的第一個字符,然後從中斷返回,代碼跳轉到.repeat標籤,然後重複上面的過程,lodsb指令繼續從si寄存器(每次該指令會把si寄存器增加1)指向的地址處取得一個字節放入al寄存器,判斷是否爲0並決定做什麼事情。print_sting分支最後的ret指令的意思是:這裏的工作已經做完啦,可以回去了,o(∩_∩)o ,然後程序會返回到我們調用該分支代碼的地方,並彈出堆棧上的值到IP寄存器中(譯註:之前不是說過把call指令的下一條指令存放到了堆棧中麼)。

在這個單獨的分支裏面有一個循環語句。在代碼裏面,text_string標識符的旁邊是一個字符流,是通過上面提到過的db指令插入到我們的操作系統中的。這段文本包含在一對單引號(’)裏面,就是告訴NASM這裏面不是代碼,並且以一個0結尾,標識文本的結束,在print_string分支裏面作爲字符串的結束的判斷標誌。

         重新敘述一下基本要點:首先是設置段寄存器,因此操作系統就知道了堆棧的位置和可執行代碼的起始位置。然後我們把si寄存器指向我們系統中的一個二進制串,然後調用一個字符串打印子程。這個子程通過si寄存器指向的字符指針掃描整個二進制串,直到遇到0,然後程序回到調用這個子程的下一句代碼繼續執行。jmp $ 這句的意思跳轉到同一行(在NSAM裏面“$”的意思是表示當前代碼行)。這樣就設置了一個無限循環,因此在信息被打印到屏幕上之後我們的系統將不再執行下面的代碼(譯註:因爲一直在這裏死循環)。

最後的兩行代碼比較的有意思,就我們的計算機來說,一個合法有效的磁盤引導扇區,必須是精確的512字節,並且以AAh和55h結尾(引導扇區的簽名)。因此times 510-($-$$) db 0這句的意思是說,填充我們的二進制目標文件直到大小達到510個字節。然後第二句dw 0xAA55的意思是使用dw(定義一個word,兩個字節)指令填充之前說的引導扇區的簽名。510+2不是剛好512字節了麼,一個以引導扇區的簽名結尾的,正確大小的啓動文件就此誕生,呵呵。

下面我們來編譯我們的新操作系統,在命令行窗口中,進入你的home目錄,輸入如下的命令:

 

nasm -f bin -o myfirst.bin myfirst.asm

 

用這個命令,我們把文本代碼彙編成了原始的機器碼二進制文件。命令參數 –f bin是告訴NASM,我們需要的是一個純的二進制文件(而不是一個複雜的linux下的可執行文件——總之我們希望這個文件越簡單純粹越好)。-o myfirst.bin部分是告訴彙編器生成一個名爲myfirst.bin的二進制文件。

現在我們需要一個虛擬軟盤映像來存放我們的引導程序,把mikeos.flp文件從Mike OS 包目下的disk_images/文件夾中拷貝到你的home目錄下,並且改名爲myfirst.flp,然後輸入下面的命令:

 

dd status=noxfer conv=notrunc if=myfirst.bin of=myfirst.flp

 

使用‘dd’命令把我們的內核文件直接複製到軟件映像的第一個扇區。做完這些之後,我們就可以使用QEMU PC模擬器用下面的命令進行引導:

 

qemu -fda myfirst.flp

 

瞧!你的操作系統將在虛擬機裏面啓動起來了。如果你真的想在一臺個人計算機上使用它,你可以把軟盤映像寫到一個真正的軟盤上去,並設置爲從它啓動,或者生成一個CD - ROM的ISO映像。如果你使用後一種方法,你需要創建一個新的目錄cdiso,並把myfirst.flp放到這個文件夾下面。然後在你的home目錄下輸入如下命令:

 

mkisofs -o myfirst.iso -b myfirst.flp cdiso/

 

執行之後將生成一個CD – ROM的ISO映像文件,名字叫myfirst.iso。這是使用之前那個可引導的虛擬軟盤映像生成的。現在你可以把這個ISO文件刻錄到你的CD-R裏面去,並且用它來引導你的計算機。(要注意的是你要直接把它刻錄爲一個iso映像,而不是把它複製到光盤上面)

接下來,如果你想改進自己的操作系統——瀏覽一下Mike OS的源代碼你也許能獲得一些靈感。需要記住的是,引導程序被限制在512個字節,如果你想做更多的事情,你需要讓你的引導程序從磁盤上裝入一個單獨的文件,然後執行它,Mike OS中就是這麼做的。

 

 

進階

現在你已經有了一個非常簡單的引導加載程序。下一步呢?這裏給出一些建議:

1、增加更多的子程序——在你的內核中已經有了print_string子程序,你可以添加子程序獲得字符串或者是移動鼠標等等。關於實現這些的方法,你可以在網上搜索一下BIOS的調用。

2、加載文件——引導程序被限制在512字節,因此你沒有太多發揮的餘地。不過你可以用引導程序把磁盤上後續的一些扇區加載到內存(RAM)裏面,並跳轉到該處繼續執行。或者你研究一下軟盤驅動器上使用的文件系統FAT12,然後再實現它。(可以看一下Mike OS裏面的一個實現,文件位置:source/bootload/bootload.asm)

3、加入某個項目——本文檔是由Mike OS的首席開發Mike Saunders撰寫的,Mike OS是一個簡單的基於x86彙編語言的16位操作系統,一旦你完全理解了這裏介紹的一些概念,你就可以深入代碼進行挖掘併爲它增加功能。查看系統的開發手冊的鏈接(譯註:這個項目的地址http://mikeos.berlios.de/),可以獲得更多的信息,你也可以加入這個項目的郵件組。

原文截圖:

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章