1. 程式人生 > >跟我一起寫作業系統(二)——史上最簡單的核心

跟我一起寫作業系統(二)——史上最簡單的核心

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

  上一講地址:http://www.cnblogs.com/lucasysfeng/p/4846119.html

  專案地址:https://github.com/lucasysfeng/lucasOS

  

  上一講我們介紹了計算機的啟動流程,並給出了一份簡單的主引導記錄程式碼,此份程式碼僅僅是顯示幾個字元,並沒有做它本應該做的事--啟動核心。本講我們首先看下核心是如何被啟動的,然後寫一個簡單的核心,用已經實現的主引導記錄配合GRUB啟動它。

如何啟動核心


  前一講我們說到,計算機讀取"主引導記錄"前面446位元組的機器碼之後,會執行事先安裝的“啟動管理器”bootloader,由使用者選擇啟動哪個核心,之後就會載入核心,將控制權交給核心。GNU GRUB(GRand Unified Bootloader)就是一種bootloader,滿足多重引導規範(The Multiboot Specification),GRUB可選擇作業系統分割槽上的不同核心,下圖就是GRUB的圖形介面:

圖 GRUB介面

  能夠被GRUB啟動的核心需要滿足兩個的條件:

(1) 核心的前8K位元組內必須要包含多重引導規範的頭資訊(Multiboot Header);
(2) 核心要載入在記憶體地址的1MB以上。

  那麼Multiboot Header是什麼樣子的呢?它必須包含4位元組對齊的3個域(還有其他非必須域,我們不討論),如下:

魔數域(magic):標誌頭的魔數,必須等於 0x1BADB002。。 
標誌域(flag):是否需要載入程式支援某些特性,我們不關心這些特性,這個標誌置為0。 
校驗域(checksum):校驗等式是否成立(magic + flags + checksum = 0)

   本文不討論GRUB的實現,我們會用前人已經寫好的GRUB(筆者會給出),我們要做的是完成符合GRUB啟動規範的核心。為了完成這個核心,我們需要寫少量的彙編用來在核心中加入Multiboot Header,然後用C語言寫核心入口,最後將彙編目的碼和C語言目的碼連結起來生成真正的核心。下面就讓我們一步步地完成這些吧!

 

第一步 彙編入口


  1. 彙編程式碼如下:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 ; 檔名 boot.asm ; Copyright: www.cnblogs.com/lucasysfeng   MBOOT_MAGIC  equ 0x1BADB002  ; multiboot magic域,必須為此值 MBOOT_FLAGS  equ 0x00        ; multiboot flag域, GRUB啟動時是否要做一些特殊操作 MBOOT_CHECKSUM  equ -(MBOOT_MAGIC + MBOOT_FLAGS) ; multiboot checksum域,校驗上面兩個域是否正確   [BITS 32]                    ; 以32位編譯   section .text    dd  MBOOT_MAGIC    dd  MBOOT_FLAGS    dd  MBOOT_CHECKSUM    dd  start   [GLOBAL start] [EXTERN kernel_main]         ; 核心入口函式, EXTERN表明此符號在外部定義   start:    cli                        ; 禁用中斷    call kernel_main           ; 呼叫核心入口函式    jmp $                      ; 無限迴圈

  在上面彙編中,我們定義了GRUB啟動需要的域MBOOT_MAGIC、MBOOT_FLAGS和MBOOT_CHECKSUM,並呼叫了核心入口函式kernel_main, kernel_main下一節實現。

  2. 編譯生成目標檔案boot.o

# nasm -f elf boot.asm -o boot.o

  執行上面命令後會生成目標檔案boot.o,-f  elf的意思是生成ELF格式的目的碼。

 

第二步 核心入口


   1. 核心程式碼如下:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 /**************************************************** # Copyright(c) www.cnblogs.com/lucasysfeng, all rights reserved # File        : kernel.c # Author      : lucasysfeng # Description : 核心入口函式 ****************************************************/   int  kernel_main() {      // 視訊記憶體開始地址      char  *display_buf = ( char *)0xb8000;                // 清屏      unsigned  int  i = 0;      const  unsigned  int  total = 80 * 25 * 2;       // 一屏25行,每行80個字元,每個字元2個位元組      while (i < total)      {          display_buf[i++] =  ' ' ;          display_buf[i++] = 0x04;                  // 顏色      }        // 顯示字元      const  char  *str =  "Hello World, welcome to kernel!" ;      for  (i = 0;  '\0'  != *str;)      {          display_buf[i++] = *(str++);          display_buf[i++] = 0x04;      }        return  0; }

  0xb8000h是視訊記憶體開始的地址,讀者可以看第一講(http://www.cnblogs.com/lucasysfeng/p/4846119.html)“真實模式記憶體地址空間分佈”那張圖,找到0xb8000h這個地址。從0xb8000h這個地址開始,每2個位元組表示一個字元,前一個位元組是字元的ASCII碼,後一個位元組是這個字元的顏色和屬性,顏色和屬性此處先不用關心。這段C程式碼的其餘部分相信讀者都能看得懂,我就不過多解釋了。 

  2. 編譯生成目標檔案kernel.o

# gcc -m32 -c -o kernel.o kernel.c

  執行上面命令後,目標檔案kernel.o就生成了。

 

第三步 生成核心


   上面講到了能被GRUB啟動的核心需要滿足的條件:

(1) 核心的前8K位元組內必須要包含多重引導規範的頭資訊(Multiboot Header);
(2) 核心要載入在記憶體地址的1MB以上。

  我們將頭資訊放在了彙編生成的目標檔案boot.o中,因此我們需要將boot.o和kernel.o連結到一起生成真正的kernel,並且這個真正的核心要載入到1MB記憶體上,為此,我們需要下面的連結指令碼和命令(關於連結指令碼的使用自行google):

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

相關推薦

一起作業系統()——簡單核心

轉載註明出處:http://www.cnblogs.com/lucasysfeng/p/4847662.html   上一講地址:http://www.cnblogs.com/lucasysfeng/p/4846119.html   專案地址:https://github.com/lucasys

一起作業系統(一)——10分鐘作業系統

轉載註明出處: http://www.cnblogs.com/lucasysfeng/p/4846119.html   專案地址:https://github.com/lucasysfeng/lucasOS     想動手,但不知從何入手,是學習一門新知識普遍會遇到的尷尬點。筆

一起 Makefile(

三、make是如何工作的 在預設的方式下,也就是我們只輸入make命令。那麼,     1、make會在當前目錄下找名字叫“Makefile”或“makefile”的檔案。    2、如果找到,它會找檔案中的第一個目標檔案(target),在上面

一起 Makefile(十

隱含規則———— 在我們使用Makefile時,有一些我們會經常使用,而且使用頻率非常高的東西,比如,我們編譯C/C++的源程式為中間目標檔案(Unix下是[.o]檔案,Windows下是[.obj]檔案)。本章講述的就是一些在Makefile中的“隱含的”,早先約定了的,不需要我們再寫出來的規則。 “隱

一起Makefile(七)

awk 註意事項 ack ref 個人 c語言 分開 數據庫 特性 make 的運行——————一般來說,最簡單的就是直接在命令行下輸入make命令,make命令會找當前目錄的makefile來執行,一切都是自動的。但也有時你也許只想讓make重編譯某些文件,而不是整個工程

一起Makefile(四)

比較 命令解釋 例子 exec 上層 tab鍵 file 順序 變量傳遞 書寫命令————每條規則中的命令和操作系統Shell的命令行是一致的。make會一按順序一條一條的執行命令,每條命令的開頭必須以[Tab]鍵開頭,除非,命令是緊跟在依賴規則後面的分號後的。在命令行之間

一起Makefile(三)

image 函數名 headers 波浪 用法 日期 最好 頭文件 哪些 書寫規則————規則包含兩個部分,一個是依賴關系,一個是生成目標的方法。在Makefile中,規則的順序是很重要的,因為,Makefile中只應該有一個最終目標,其它的目標都是被這個目標所連帶出來的,

一起Makefile:使用函數

ref pos weibo blank log vdi make linu wiki 跟我一起寫Makefile:使用函數 兩個排版不一樣 書籍下載 書籍下載跟我一起寫Makefile:使用函數

【轉】一起 Makefile

軟件 linux下 是我 main c++ class 情況 如果 反斜杠 概述—— 什麽是makefile?或許很多Winodws的程序員都不知道這個東西,因為那些Windows的IDE都為你做了這個工作,但我覺得要作一個好的和professional的程序員,makef

一起 Makefile - 6. 使用條件判斷

跟我一起寫 Makefile - 6. 使用條件判斷 http://wiki.ubuntu.org.cn 6. 使用條件判斷 使用條件判斷,可以讓 make 根據執行時的不同情況選擇不同的執行分支。條件表示式可以是比較變數的值,或是比較變數和常量的值。 6.1 示例 下面

一起 Makefile - 4. 書寫命令

跟我一起寫 Makefile - 4. 書寫命令 http://wiki.ubuntu.org.cn 4. 書寫命令 每條規則中的命令和作業系統 shell 的命令列是一致的。make 會按順序一條一條的執行命令,每條命令的開頭必須以 Tab 鍵開頭,除非命令是緊跟在依賴規則後面

一起 Makefile - 2. Makefile 介紹

跟我一起寫 Makefile - 2. Makefile 介紹 http://wiki.ubuntu.org.cn 2. Makefile 介紹 make 命令執行時,需要一個 Makefile 檔案,以告訴 make 命令如何去編譯和連結程式。 以下示例來源於 GNU 的

一起 Makefile - 1. 概述

跟我一起寫 Makefile - 1. 概述 http://wiki.ubuntu.org.cn 1. 概述 什麼是 Makefile?Windows 的整合開發環境 (integrated development environment, IDE) 完成了 Makefile 的

一起Makefile:MakeFile介紹

makefile 介紹 make命令執行時,需要一個 makefile 檔案,以告訴make命令如何去編譯和連結程式。 首先,我們用一個示例來說明makefile的書寫規則。以便給大家一個感性認識。這個示例來源於gnu的make使用手冊,在這個示例中,我們的工程有8個

一起Makefile:書寫命令

轉載: 書寫命令 每條規則中的命令和作業系統Shell的命令列是一致的。make會按順序一條一條的執行命令,每條命令的開頭必須以[Tab]鍵開頭,除非,命令是緊跟在依賴規則後面的分號後的。在命令列之間中的空格或是空行會被忽略,但是如果該空格或空行是以Tab鍵開頭的,那

一起Makefile:使用變數

轉載: 使用變數 在Makefile中的定義的變數,就像是C/C++語言中的巨集一樣,他代表了一個文字字串,在Makefile中執行的時候其會自動原模原樣地展開在所使用的地方。其與C/C++所不同的是,你可以在Makefile中改變其值。在Makefile中,變數可以

一起Makefile:使用條件判斷

轉載: 使用條件判斷 使用條件判斷,可以讓make根據執行時的不同情況選擇不同的執行分支。條件表示式可以是比較變數的值,或是比較變數和常量的值。 示例 下面的例子,判斷$(CC)變數是否“gcc”,如果是的話,則使用GNU函式編譯目標。 libs_for_gcc

一起Makefile:隱含規則

轉載: 隱含規則 在我們使用Makefile時,有一些我們會經常使用,而且使用頻率非常高的東西,比如,我們編譯C/C++的源程式為中間目標檔案(Unix下是[.o]檔案,Windows下是[.obj]檔案)。本章講述的就是一些在Makefile中的“隱含的”,早先約定

一起Makefile:使用make更新函式庫檔案

轉載: 使用make更新函式庫檔案 函式庫檔案也就是對Object檔案(程式編譯的中間檔案)的打包檔案。在Unix下,一般是由命令"ar"來完成打包工作。 函式庫檔案的成員 一個函式庫檔案由多個檔案組成。你可以以如下格式指定函式庫檔案及其組成: archi

一起 Makefile-陳浩

makefile:是告訴編譯器(交叉工具鏈)如何去編譯、連結一個工程的規則。 一、概述     什 麼是makefile?或許很多Winodws的程式設計師都不知道這個東西,因為那些Windows的IDE都為你做了這個工作,但我覺得要作一個好的和 professi