文章出處

《30天自制操作系統》筆記(06)——CPU的32位模式

進度回顧

上一篇中實現了啟用鼠標、鍵盤的功能。屏幕上會顯示出用戶按鍵、點擊鼠標的情況。這是通過設置硬件的中斷函數實現的,可以說硬件本身的設計就具有事件驅動的性質,所以軟件層面上才有基于事件的消息機制。

但上一篇沒有說明中斷的來龍去脈,本篇就從頭到尾描述一下CPU與此相關的設置問題。

Segment

32位的CPU使用32條地址線,能區分232=4G個內存地址。每個內存地址都有1Byte的內容。

分段,就是將4GB的內存分成很多塊(block),每一塊的起始地址都看作0來處理。有了這個功能,任何程序都可以先寫上一句"ORG 0",一個應用程序就不會占用別人的內存空間,這樣就可以同時運行多個程序。像這樣分割出來的塊,就稱為(segment)。還有一種"分頁"的技術,這里不討論。

為了表示一個段,需要記錄以下信息:

  • 段的起始地址
  • 段的大小
  • 段的管理屬性(禁止寫入,執行,系統專用等)

這些信息需要用8個字節保存。使用段的方式是和調色板神似的:DS是16位,理論上能夠表示216=65536個段。但由于CPU設計上的原因,低3位不能用,因此DS只能表示213=8192個段(即第0個~第8191個)。

在16位模式下,如果寫"MOV AL, [DS:EBX]",那么要計算的地址是DS*16+EBX。在32位模式下,則應該是DS表示的段(segment)的起始地址+EBX。

另外,如果寫成"MOV AL, [EBX]",則匯編器認為這等同于"MOV AL, [DS:EBX]"。這一點在16位和32位模式下是一致的。

要存儲8192個段,就需要占用8192*8=65536Byte=64KB的內存空間。這64KB的數據就稱為GDT (Global segment Descriptor Table)即"全局段號記錄表"。

將這64K的GDT整齊地排列在內存某處,再將其起始地址和有效設定個數放在CPU內被稱作GDTR的48bit寄存器中,GDT的設定就完成了。

段的起始地址、大小、管理屬性這些信息是按bit保存的,十分復雜,暫時不要理會。

IDT

當CPU遇到外部情況變化,或是內部發生某些錯誤時,會臨時切換過去處理這種突發事件。這就是中斷功能。鍵盤按鍵、鼠標按鍵、鼠標移動、除0等都會引發中斷。有了中斷機制,CPU就不需要一直查詢這些低速設備的狀態,將時間用在處理任務上。

因此,要使用鼠標鍵盤,就必須使用中斷機制,即設置IDT

IDT(Interrupt Descriptor Table)即"中斷記錄表"。IDT記錄了0~255的中斷號與調用函數之間的對應關系。當發生了123號中斷,就會調用對應的函數。其設置方式與GDT是相似的,IDT的每一項也需要8Byte保存,這8Byte里包括中斷處理函數名(即C語言中的函數指針)。

另外,必須先設置GDT后設置IDT。原因不詳。

PIC

PIC(Programmable Interrupt Controller)即"可編程中斷控制器"。它是一個硬件芯片

PIC控制器

當鍵盤鼠標發生按鍵、移動時,PIC就會向CPU發送電信號,然后CPU要求PIC發送2個Byte來(其內容為"0xcd 0x??",實際上是機器語言的INT指令),CPU還真就把PIC送來的這2個Byte看作一條指令執行。其結果是調用IDT中對應的函數。

PIC的設定基本上都是固定死的幾行代碼,暫時不用理會。

進入32位模式

進入32位模式實際上很簡單,按照一定的步驟將某些寄存器(CR0等)設置為特定的值就行了。也有點繁瑣,暫時不理會。

操作系統程序被加載到內存中的什么地方才行?這個沒有特別的規定,根據自己的偏好分給OS一些內存空間就行了。不過有些內存空間放著BIOS等程序,而且大部分高地址的內存是要給應用程序使用的。因此OS程序的空間分配也不要太隨意了。下圖是HariboteOS設計的內存分布圖。

HariboteOS的內存分布圖

總結

本文以輕量從簡的態度簡單說明了OS啟動時要初始化的大部分東西,即GDT、IDT、PIC、32位模式。我個人認為這些都是細節,應該進行封裝。后續的內存管理、多任務才是OS設計的核心內容。

 

請查看下一篇《《30天自制操作系統》筆記(07)——內存管理》


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()