1. 程式人生 > >進入保護模式

進入保護模式

目錄

進入保護模式

進入保護模式

進入保護模式的步驟:

  1. 關閉中斷,開啟地址線A20GATE,使得CPU可以訪問1M以上的記憶體空間。
  2. 設定CR0暫存器,進入保護模式。
  3. 載入臨時GDT
  4. 進入保護模式後,首先執行jmp指令。因為記憶體定址方式改變,需要重新整理指令流水線

開啟A20Gate

1. A20Gate的作用

在真實模式下,A20Gate是關閉的,意味著只能使用20根地址線,需要通過開啟A20Gate,訪問第21根以上的匯流排。

A20Gate關閉時侯的記憶體訪問:

A20Gate關閉式,只能使用20根匯流排,所以定址範圍位 0x00000 ~ 0xFFFFF,總共1M的地址範圍。

當訪問的地址大於這個範圍,高位的值將被擷取掉,導致超出1M的地址訪問會使得CPU回滾到1M內地址範圍的現象

例如

當使用 [0xFFFF :0xFFFF ] 記憶體地址,得到的地址位 0x10FFEF 。但是在真實模式下,由於20根匯流排的限制,最高位的1是無效的,實際的訪問地址迴繞到 [0x0FFEF]。

A20Gate開啟後的記憶體訪問:

開啟A20Gate, 可以使用到32位的地址匯流排,記憶體地址訪問也達到了1<<32 的4G範圍。

實際上開啟A20Gate,匯流排的定址能力達到了4G,但是cpu的記憶體訪問能力因為16位段暫存器,和16位偏移地址的限制,並不能協調工作。

所以需要進入保護模式突破cpu的記憶體訪問限制。

2. 開啟A20Gate

開啟A20Gate,只要設定io埠0x92的第一位為1就可以了。

;------------------
;開啟A20
cli                         ;禁止CPU級別的中斷
in      al,0x92
or      al,0000_0010B           ;設定第1位為1
out     0x92,al

設定CR0暫存器,進入保護模式

CR0暫存器

CR0暫存器是一個32位的暫存器

設定CR0暫存器的最高位為0,最低位為1,則可以進入保護模式。

CR0暫存器的作用

  • 改變段定址方式,使用段描述符方式定址。
  • 真實模式指令的運算元預設為16位,保護模式指令的運算元預設為32位。

程式碼:

;------------------
;進入保護模式
mov     eax,CR0
or      eax,0x00000001            ;設定第0位為1
mov     CR0,eax

loader.asm完整程式碼如下

;Rats OS
;Tab=4
[bits 16]

section loader vstart=LOADER_BASE_ADDR ;指明程式的偏移的基地址

;----------- loader const ------------------
LOADER_BASE_ADDR        equ 0x9000  ;記憶體地址0x9000
;---------------------------------------    
    jmp Entry
    
    
;程式核心內容
Entry:
    

    ;------------------
    ;禁止CPU級別的中斷
    cli                         

    ;------------------
    ;開啟A20
    in      al,0x92
    or      al,0000_0010B       ;設定第1位為1
    out     0x92,al
    

    ;------------------
    ;進入保護模式
    mov     eax,cr0
    or      eax,0x00000001      ;設定第0位為1
    mov     cr0,eax



;程式掛起       
    jmp $           ;讓CPU掛起,等待指令?

使用bochs除錯

在0x7c00打斷點,輸入c跳轉執行

$ pb 0x7c00

$ c

輸入顯示切換模式命令

$ show mode

輸入c繼續執行

$ c

可以看到控制他輸出:

00017609546: switched from 'real mode' to 'protected mode'

說明系統成功的從真實模式切換到保護模式

檢視CR0的PE位

$ creg