熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Oracle >> 正文

自己動手寫操作系統(一)

2013-11-13 22:20:16  來源: Oracle 

  自由軟件社區是一個充滿自由和夢想的地方余年的時間裡它創造了一個又一個奇跡然而這些奇跡的創造者不只是Stallman也不只是Linus Torvalds而是活躍在世界各地的不計其數的開發人員
  
  在使用各種功能強大的自由軟件時我總會對其開發者充滿崇敬之情期盼有朝一日自己也能成為他們中的一員很多對自由社區充滿向往之情的人雖然也想努力融身於其中但又不知該怎麼做那麼就請與我們一起從編寫一個簡單的操作系統開始吧!
  
  我們要做的事情
  
  有人可能擔心自己既沒有學過計算機原理也沒有學過操作系統原理更不懂匯編語言對C語言也一知半解能寫操作系統嗎?答案是沒問題我將帶大家一步一步完成自己的操作系統當然如果學一學上述內容再好不過
  
  首先要明確處理器(也就是CPU)控制著計算機對PC而言啟動的時候CPU都處在實模式狀態相當於只是一個Intel 處理器也就是說即使你現在擁有一個奔騰處理器它的功能也只能是級別從這一點上來講可以使用一些軟件把處理器轉換到著名的保護模式只有這樣我們才可以充分利用處理器的強大功能
  
  編寫操作系統開始是對BIOS控制取出存儲在ROM裡的程序BIOS是用來執行POST(Power On Self Test自檢)的自檢是檢查計算機的完整性(比如外設是否工作正常鍵盤是否連接等)這一切完成以後你就會聽到PC喇叭發出一聲清脆的響聲如果一切正常BIOS就會選擇一個啟動設備並且讀取該設備的第一扇區(即啟動扇區)然後控制過程就會轉移到指定位置啟動設備可能是一個軟盤光盤硬盤或者其它所選擇的設備在此我們把軟盤作為啟動設備如果我們已經在軟盤的啟動扇區裡寫了一些代碼這時它就被執行因此我們的目的很明確就是往軟盤的啟動扇區寫一些程序
  
  首先使用匯編來寫一個小程序然後將其拷貝至軟盤的啟動扇區為了實現拷貝要寫一個C程序最後使用軟盤啟動計算機
  
  需要的工具
  
  ● as這是一個匯編程序它負責把寫的代碼轉換成目標文件
  
  ● ld這是一個連接器as產生的目標代碼由它來轉換成真正的機器語言機器語言是能夠解讀的形式
  
  ● GCC著名的C編程器因為我們需要寫一個C程序將自己的OS轉移到軟盤中
  
  ● 一張空軟盤它用於存儲編寫的操作系統也是啟動設備
  
  ● 一台裝有Linux的計算機這台機器可以很舊都可以
  
  在大部分標准Linux發行版中都會帶有as和ld在我使用的Red Hat 中就包含有這兩個工具並且在默認的情況下它已經安裝在機器裡如果使用的Linux沒有這兩個工具可以從網上下載(~mayday/)這兩個工具都包含在一個名為bin的軟件包中此外有關的文檔也可以在網上獲得(/docs/ldp/howto/AssemblyHOWTO/l)
  
  開始工作
  
  使用一個你喜歡的編輯器輸入以下內容
  
  entry start
  start:
   mov ax#xb
   mov esax
   seg es
   mov []#x
   seg es
   mov []#xf
  loop: jmp loop
  
  這是as可以讀懂的一段匯編程序第一個句子指明了程序的入口點聲明整個過程從start處開始第二行指明了start的位置說明整個程序要從start處開始執行xb是顯存的開始地址#表明其後是一個立即數執行語句
  
  mov ax#oxb
  
  ax寄存器的值就變為xb這就是顯存的地址下面再將這個值移至es寄存器es是附加段寄存器請記住有一個分段的體系結構它的各段寄存器為代碼段數據段堆棧段和附加段對應的寄存器名稱分別為csdsss和es事實上我們把顯存地址送入了附加段因此任何送入附加段的東西都會被送到顯存中
  
  要在屏幕上顯示字符就需要向顯存中寫兩個字節前一個是所要顯示字符的ASCⅡ值第二個字節表示該字符的屬性屬性包括字符的前景色背景色及是否閃爍等等seg es指明下一個將要執行的指令是指向es段的所以我們把值x(在ASCⅡ中表示的字符是A)送到顯存的第一個字節中接下來要把字符的屬性送到下一個字節當中在此輸入的是xf該屬性指的是在藍色背景下顯示白色的字符因此如果執行這個程序就可以在屏幕上得到顯示在藍底上的一個白色的A接著是一個循環因為在執行完顯示字符的任務後要麼讓程序結束要麼使用一個循環使其永遠運行下去把該文件命名為boots然後存盤
  
  此處顯存的概念說得不是很清楚有必要進一步解釋一下假設屏幕由列×行組成那麼第一行就需要字節其中一個字節用於表示字符另外一個字節用於表示字符的屬性如果要在第三行顯示某一字符的話就要跳過顯存的第字節(它們是用於顯示第列的)字節(它們是用於顯示第列的)然後把需要顯示字符的ASCⅡ碼值入第字節把字符的屬性寫入第字節
  
  把程序寫至啟動扇區
  
  下面寫一個C程序把我的操作系統寫入軟盤第一扇區程序內容如下
  
  #include <sys/typesh> /* unistdh 需要這個文件 */
  #include /* 包含有read和write函數 */
  #include
  int main()
  {
   char boot_buf[];
   int floppy_desc file_desc;
   file_desc = open(/boot O_RDONLY);
   read(file_desc boot_buf );
   close(file_desc);
   boot_buf[] = x;
   boot_buf[] = xaa;
   floppy_desc = open(/dev/fd O_RDWR);
   lseek(floppy_desc SEEK_CUR);
   write(floppy_desc boot_buf );
   close(floppy_desc);
  }
  
  首先以只讀模式打開boot文件然後在打開文件時把文件描述符復制到file_desc變量中從文件中讀取個字符或者讀取直到文件結束在本例中由於文件很小所以是讀取至文件結束然後關閉文件
  
  最後行代碼打開軟盤驅動設備(一般來說是/dev/fd)使用lseek找到文件開始處然後從緩沖中向軟盤寫個字節
  
  在readwriteopen和lseek的幫助頁中可以看到與函數所有有關的參數及其使用方法程序中有兩行比較難懂
  
  boot_buf[] = x;
  boot_buf[] = xaa;
  
  該信息是用於BIOS的如果它識別出該設備是一個可啟動的設備那麼在第的位置該值就應該是xxaa程序會把文件boot讀至名為boot_buf的緩沖中它要求改變第和第字節然後把boot_buf寫至軟盤之上如果執行代碼軟盤上的前字節就包含了啟動代碼最後把文件存為writec
  
  編譯運行
  
  使用下面的命令把文件變為可執行文件
  
  as boots o booto
  ld d booto o boot
  cc writec o write
  
  首先將boots文件編譯成目標文件booto然後將該文件連接成最終的boot文件最後C程序編譯成可執行的write文件
  
  插入一個空白軟盤運行以下程序
  
  /write
  
  重新啟動電腦進行BIOS的界面設置並且把軟盤設為第一個啟動的設備然後插入軟盤電腦從軟盤上啟動
  
  啟動完成後在屏幕上可以看到一個字母A(藍底白字)啟動速度很快幾乎是在瞬間完成這就意味著系統已經從我們制作的軟盤上啟動了並且執行了剛才寫入啟動扇區的程序現在它正處在一個無限循環的狀態所以如果想進入Linux必需拿掉軟盤並且重啟機器
  
  至此這個操作系統就算完成了雖然它沒有實現什麼功能但是它已經可以啟動機器了
  
  下一期我將在這個啟動扇區程序裡加入一些代碼使它可以做一些比較復雜的事情(比如使用BIOS中斷保護模式切換等等)

From:http://tw.wingwit.com/Article/program/Oracle/201311/18813.html
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.