10、試驗保護模式

    問題1、怎麼理解界限 = 大小 - 1?
數組

    界限就是邊界、分界線,就是終止的地方,內存的界限就是一段內存的終址相對於基址的偏移號(不是偏移量,偏移號 = 偏移量 -1)。數據結構

    爲何要減一?由於內存地址編號從 0 開始,第一個內存地址對應內存地址編號 0 ,第 n 個內存地址對應內存地址編號 n - 1。內存地址序號的上限減一對應內存地址編號的上限,而內存地址的最大序號就是這段內存的大小,即一段內存的大小  -  1 = 這段內存的界限。ide


     問題二:描述符是什麼?學習

    不要被「符」字迷惑了,說白了「符」就是個數據結構(在 C語言裏就是個 struct)。「描述」兩個字從字面理解就行,就是對一個東西進行詳細說明。咱們這裏學習的保護模式,描述的就是內存的分段管理模式。那麼「描述符」就是說明一段內存的詳細狀況的數據結構。實際上,描述符就是定義一段內存的起始地址、界限、訪問屬性的一個數據結構,描述符表就是一個由描述符爲元素組成的數組,看起來像一個表格而已。spa


    問題三:GDT 表第一個爲何要留空呢?code

    由於選擇子的結構是這樣的:orm

;  ┏━┳━┳━┳━┳━┳━┳━┳━┳━┳━┳━━┳━┳━┳━┳━┓
索引

;  ┃15┃14┃13┃12┃11┃10┃09┃08┃07┃06┃05┃04┃03┃02┃01┃0  ┃ip

;  ┣━┻━┻━┻━━┻━┻━┻━┻━━┻━┻━╋━╋━┻━┫內存

;  ┃                   描述符索引                                         ┃TI ┃  RPL  ┃

;  ┗━━━━━━━━━━━━━━━━━━━━━━━━┻━┻━━┛

      選擇子中正真索引 GDT 表的索引號只在高 13 位,低 3 位要留給 TI 和 RPL,即索引號實際上從第 3 位開始,就是0b0000000000001000 = 8;索引號每次增長的值(步進)也不是 1 ,而是 0b1000 =  8 。

      恰好 GDT 表中,一個描述符也是佔用 8 個字節。

      如今簡單了:把第一個描述符留空不用,只是佔據 8 個字節的空間,在 TI 和 RPL 都等於 0 的狀況下,選擇子就能夠簡單等同於描述符在 GDT 表中的偏移了!即:

      第一個選擇子   =  一號描述符在 GDT 表中的偏移  =  8

      第 n 個選擇子  = n 號描述符在 GDT 表中的偏移    =  n * 8


    打開地址線 A20、打開保護模式標誌都是固定格式,照抄就行。lgdt 和 cli 是 CPU 指令,看看其指令說明就行。再來讀下面的代碼,就沒啥難度了。

; TestPM.nas
; 初識保護模式
; 四彩
; 2015-11-15


; ========================================================================================
; ----------------------------------------------------------------------------------------
    org 0x7C00
    jmp Label_RM_main

; ****************************************************************************************


; ========================================================================================
%include "./INC/Descriptor.inc"
;
; ----------------------------------------------------------------------------------------
; GDT                          段基址   段界限    屬性
Label_Desc_Empty  : Descriptor 0,       0,        0                 ; 空描述符
Label_Desc_PM     : Descriptor 0,       0xFFFF,   DA_32 + DA_CS_E   ; 保護模式代碼段描述符
Label_Desc_Video  : Descriptor 0xB8000, 0xFFFF,   DA_DS_RW          ; 顯存段描述符
;
; ----------------------------------------------------------------------------------------
; GDTPtr
GDTLen  equ $ - Label_Desc_Empty
GDTPtr  dw  GDTLen - 1                      ; 界限
        dd  0                               ; 基址
;
; ----------------------------------------------------------------------------------------
; 選擇子
SelectorPM      equ Label_Desc_PM    - Label_Desc_Empty
SelectorVideo   equ Label_Desc_Video - Label_Desc_Empty
;
; ****************************************************************************************


[BITS 16]
; ========================================================================================
; 實模式下開啓保護模式
; ----------------------------------------------------------------------------------------
; 程序入口,實模式代碼段
Label_RM_main:
    ; 填上保護模式代碼段描述符的基址(界限、屬性在定義時已初始化)
    xor eax, eax
    mov ax, cs
    shl eax, 4
    add eax, Label_PM_main                  ; 保護模式程序入口的絕對內存地址,即爲其基址
    mov word[Label_Desc_PM + 2], ax         ; 拆分紅 3 部分存入相應位置
    shr eax, 16
    mov byte[Label_Desc_PM + 4], al
    mov byte[Label_Desc_PM + 7], ah

    ; 填上 GDTPtr 的基址(界限在定義時已初始化)
    xor eax, eax
    mov ax, cs
    shl eax, 4
    add eax, Label_Desc_Empty
    mov dword[GDTPtr + 2], eax

    ; 加載 GDT
    lgdt [GDTPtr]

    ; 屏蔽中斷
    cli

    ; 打開地址線 A20
    in al, 0x92
    or al, 0b10
    out 0x92, al

    ; 打開保護模式標誌
    mov eax, cr0
    or eax, 1
    mov cr0, eax

    ; 修改 CS : EIP
    jmp dword SelectorPM : 0

; ****************************************************************************************


[BITS 32]
; ========================================================================================
; 保護模式代碼段,由實模式跳入
Label_PM_main:
    mov ax, SelectorVideo
    mov gs, ax
    mov edi, (80 * 5 + 35) * 2
    mov ah, 0xC
    mov al, 'O'
    mov [gs : edi], ax
    mov al, 'K'
    mov [gs : edi + 2], ax

    jmp $

; ****************************************************************************************


; ========================================================================================
; FAT12 文件系統引導扇區引導代碼的剩餘部分用 0 填滿
    times 510 - ($ - $$) db 0

; ****************************************************************************************


; ========================================================================================
; FAT12 文件系統引導扇區的的結束標誌(最後 2 字節,必須是 0xAA55)
    dw 0xAA55

; ****************************************************************************************

; ========================================================================================
    CodeLenOfPM     equ $ - Label_PM_main

; ****************************************************************************************
相關文章
相關標籤/搜索