天天看點

80386保護模式--描述符,附pm.inc代碼詳解

    描述符包括,存儲段描述符(代碼段,資料段,堆棧段),系統描述符(任務狀态段TSS,局部描述符表LDT),門描述符(調用門,任務門,中斷門,陷阱門),注意門描述符和系統描述符都是DT=0時候,對應的狀态。存儲段描述符和系統描述符如圖1,門描述符如圖2。

80386保護模式--描述符,附pm.inc代碼詳解

                                   圖1 存儲段描述符和系統描述符

80386保護模式--描述符,附pm.inc代碼詳解

                                      圖2 門描述符

    (1) P:存在(Present)位。

    P=1 表示描述符對位址轉換是有效的,或者說該描述符所描述的段存在,即在記憶體中;

    P=0 表示描述符對位址轉換無效,即該段不存在。使用該描述符進行記憶體通路時會引起異常。

    (2) DPL:  表示描述符特權級(Descriptor Privilege level),共2位。它規定了所描述段的特權級,用于特權檢查,以決定對該段能否通路。 

    (3) DT:說明描述符的類型。

    對于存儲段描述符而言,DT=1,以差別與系統段描述符和門描述符(DT=0)。 

    (4) TYPE: 說明存儲段描述符所描述的存儲段的具體屬性。

    資料段類型 類型值說明

    ----------------------------------

    0 隻讀 

    1 隻讀、已通路 

    2 讀/寫 

    3 讀/寫、已通路 

    4 隻讀、向下擴充 

    5 隻讀、向下擴充、已通路 

    6 讀/寫、向下擴充 

    7 讀/寫、向下擴充、已通路 

    類型值 說明

    代碼段類型 ----------------------------------

    8 隻執行 

    9 隻執行、已通路 

    A 執行/讀 

    B 執行/讀、已通路 

    C 隻執行、一緻碼段 

    D 隻執行、一緻碼段、已通路 

    E 執行/讀、一緻碼段 

    F 執行/讀、一緻碼段、已通路 

    系統段類型 類型編碼說明

    ----------------------------------

    0 <未定義>

    1 可用286TSS

    2 LDT

    3 忙的286TSS

    4 286調用門

    5 任務門

    6 286中斷門

    7 286陷阱門

    8 未定義

    9 可用386TSS

    A <未定義>

    B 忙的386TSS

    C 386調用門

    D <未定義>

    E 386中斷門

    F 386陷阱門

    (5) G:段界限粒度(Granularity)位。

    G=0 表示界限粒度為位元組;

    G=1 表示界限粒度為4K 位元組。

    注意,界限粒度隻對段界限有效,對段基位址無效,段基位址總是以位元組為機關。 

    (6) D:D位是一個很特殊的位,在描述可執行段、向下擴充資料段或由SS寄存器尋址的段(通常是堆棧段)的三種描述符中的意義各不相同。 

    在描述可執行段的描述符中,D位決定了指令使用的位址及操作數所預設的大小。

    ① D=1表示預設情況下指令使用32位位址及32位或8位操作數,這樣的代碼段也稱為32位代碼段;

    ② D=0 表示預設情況下,使用16位位址及16位或8位操作數,這樣的代碼段也稱為16位代碼段,它與80286相容。可以使用位址大小字首和操作數大小字首分别改變預設的位址或操作數的大小。 

    在向下擴充資料段的描述符中,D位決定段的上部邊界。

    ① D=1表示段的上部界限為4G;

    ② D=0表示段的上部界限為64K,這是為了與80286相容。 

    在描述由SS寄存器尋址的段描述符中,D位決定隐式的堆棧通路指令(如PUSH和POP指令)使用何種堆棧指針寄存器。

    ① D=1表示使用32位堆棧指針寄存器ESP;

    ② D=0表示使用16位堆棧指針寄存器SP,這與80286相容。 

    (7) AVL:軟體可利用位。80386對該位的使用未左規定,Intel公司也保證今後開發生産的處理器隻要與80386相容,就不會對該位的使用做任何定義或規定。 

    (8) Dword Count:從調用者堆棧中将參數複制到被調用者堆棧(新堆棧)中,複制參數的個數由調用門中Dword Count一項來決定。如果Dword Count為0,那麼不會複制參數。

    選擇子圖示:

         ┏━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┓

         ┃ 15 ┃ 14 ┃ 13 ┃ 12 ┃ 11 ┃ 10 ┃ 9  ┃ 8  ┃ 7  ┃ 6  ┃ 5  ┃ 4  ┃ 3  ┃ 2  ┃ 1  ┃ 0  ┃

         ┣━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━╋━━╋━━┻━━┫

         ┃                                 描述符索引                                 ┃ TI ┃   RPL    ┃

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

    RPL(Requested Privilege Level): 請求特權級,用于特權檢查。

    TI(Table Indicator): 引用描述符表訓示位

    TI=0 訓示從全局描述符表GDT中讀取描述符;

    TI=1 訓示從局部描述符表LDT中讀取描述符。 

    LDT中的描述符和GDT中的描述符除了選擇子的bit3一個為0一個為1用于區分該描述符是在GDT中還是在LDT中外,描述符本身的結構完全一樣。開始我考慮既然是這樣,為什麼要将LDT放在GDT中而不是像GDT那樣找一個GDTR寄存器呢?

    後來終于明白了原因--很簡單,GDT表隻有一個,是固定的;而LDT表每個任務就可以有一個,是以有多個,并且由于任務的個數在不斷變化其數量也在不斷變化。如果隻有一個LDTR寄存器顯然不能滿足多個LDT的要求。是以INTEL的做法是把它放在放在GDT中。

    pm.inc代碼如下:

;----------------------------------------------------------------------------
; 描述符類型值說明
; 其中:
;       DA_  : Descriptor Attribute
;       D    : 資料段
;       C    : 代碼段
;       S    : 系統段
;       R    : 隻讀
;       RW   : 讀寫
;       A    : 已通路
;       其它 : 可按照字面意思了解
G D 0 AVL 0 0 0 0 P DPL(2位) DT TYPE(4位)
;----------------------------------------------------------------------------
DA_32		EQU	4000h	; 32 位段 0100 0000 0000 0000

DA_DPL0		EQU	  00h	; DPL = 0 0000 0000
DA_DPL1		EQU	  20h	; DPL = 1 0010 0000
DA_DPL2		EQU	  40h	; DPL = 2 0100 0000
DA_DPL3		EQU	  60h	; DPL = 3 0110 0000
;----------------------------------------------------------------------------
; 存儲段描述符類型值說明
;----------------------------------------------------------------------------
DA_DR		EQU	90h	; 存在的隻讀資料段類型值  1001 0000
DA_DRW		EQU	92h	; 存在的可讀寫資料段屬性值 1001 0010
DA_DRWA		EQU	93h	; 存在的已通路可讀寫資料段類型值 1001 0011
DA_C		EQU	98h	; 存在的隻執行代碼段屬性值 1001 1000
DA_CR		EQU	9Ah	; 存在的可執行可讀代碼段屬性值 1001 1010
DA_CCO		EQU	9Ch	; 存在的隻執行一緻代碼段屬性值 1001 1100
DA_CCOR		EQU	9Eh	; 存在的可執行可讀一緻代碼段屬性值 1001 1110
;----------------------------------------------------------------------------
; 系統段描述符類型值說明
;----------------------------------------------------------------------------
DA_LDT		EQU	  82h	; 局部描述符表段類型值 1000 0010
DA_TaskGate	EQU	  85h	; 任務門類型值 1000 0101
DA_386TSS	EQU	  89h	; 可用 386 任務狀态段類型值 1000 1001
DA_386CGate	EQU	  8Ch	; 386 調用門類型值 1000 1100
DA_386IGate	EQU	  8Eh	; 386 中斷門類型值 1000 1110
DA_386TGate	EQU	  8Fh	; 386 陷阱門類型值 1000 1111
;----------------------------------------------------------------------------


;----------------------------------------------------------------------------
; 選擇子類型值說明
; 其中:
;       SA_  : Selector Attribute


SA_RPL0		EQU	0	; ┓00
SA_RPL1		EQU	1	; ┣ RPL01
SA_RPL2		EQU	2	; ┃10
SA_RPL3		EQU	3	; ┛11


SA_TIG		EQU	0	; ┓TI 0000
SA_TIL		EQU	4	; ┛  0100
;----------------------------------------------------------------------------


; 宏 ------------------------------------------------------------------------------------------------------
;
; 描述符
; usage: Descriptor Base, Limit, Attr
;        Base:  dd
;        Limit: dd (low 20 bits available)低二十位可用
;        Attr:  dw (lower 4 bits of higher byte are always 0)高位元組的低四位始終為0
%macro Descriptor 3 ;段界限為低位址 1代表Base 2代表Limit 3代表屬性 
	dw	%2 & 0FFFFh				; 段界限 1				(2 位元組)
	dw	%1 & 0FFFFh				; 段首位址 1				(2 位元組)
	db	(%1 >> 16) & 0FFh			; 段首位址 2				(1 位元組)
	dw	((%2 >> 8) & 0F00h) | (%3 & 0F0FFh)	; 屬性 1 + 段界限 2 + 屬性 2		(2 位元組)
	db	(%1 >> 24) & 0FFh			; 段首位址 3				(1 位元組)
%endmacro ; 共 8 位元組
;
; 門
; usage: Gate Selector, Offset, DCount, Attr
;        Selector:  dw
;        Offset:    dd
;        DCount:    db
;        Attr:      db
%macro Gate 4 ;1代表Selector 2代表Offset 3代表DCount 4代表Attr
	dw	(%2 & 0FFFFh)				; 偏移 1				(2 位元組)
	dw	%1					; 選擇子				(2 位元組)
	dw	(%3 & 1Fh) | ((%4 << 8) & 0FF00h)	; 屬性					(2 位元組)
	dw	((%2 >> 16) & 0FFFFh)			; 偏移 2				(2 位元組)
%endmacro ; 共 8 位元組
           

繼續閱讀