以x86為例: flat32.asm
這段程式做了三件事情
1. 初始化GDT (Global Descriptor Table)
2. 切換至16 bit Protected mode
3. 切換至32 bit Protected mode
align 16
_ModuleEntryPoint PROC C PUBLIC
;
; Load the GDT table in GdtDesc
;
mov esi, OFFSET GdtDesc
db 66h
lgdt fword ptr cs:[si]
;
; Transition to 16 bit protected mode
;
mov eax, cr0 ; Get control register 0
or eax, 00000003h ; Set PE bit (bit #0) & MP bit (bit #1)
mov cr0, eax ; Activate protected mode
;
; Now we're in 16 bit protected mode
; Set up the selectors for 32 bit protected mode entry
;
mov ax, SYS_DATA_SEL
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
;
; Transition to Flat 32 bit protected mode
; The jump to a far pointer causes the transition to 32 bit mode
;
mov esi, offset ProtectedModeEntryLinearAddress
jmp fword ptr cs:[si]
_ModuleEntryPoint ENDP
這一篇要探討Global Descriptor Table 是什麼用途。Global Descriptor Table (GDT)是定義於IA32架構,它包含所有entries來告訴CPU關於Memory Segment. 它類似於Interrupts Descriptor Table, 存在著包含task和interrupts descriptors.
GDT 使用LGDT組合語言指令來讀取。它預計GDT描述結構的位置。(將GDT 暫存器讀至memory 中)
GDTR:
GDTR:
offset 是Table的本體,意思為分頁將應用的線性位址. Size是減1的大小。這是因為Size的最大值65535, 雖然GDT可達65536位元組 (8192 entries的最大值) 進一步說沒有GDT可以有大小為0.(1~65535)
Table 包含8 位元組的entries。每個entry具有複雜的結構。
Limit 0:15 => 該欄位包含0-15位元的限制。
Base 0:15 Base 16:23 Base 24:32 => Base是一個32位元值,包含線性位址segment開始的地方。
Limit,一個20位元的數值,表示最大可定址的單元(或者在1位元組為單位,或在分頁中)。因此,如果你選擇Page Granularity (4 KiB) 和Limit value 設置為0xFFFFF segment 將跨越全4 GiB位址空間。
以下是存取位元組(Access Byte)和Flag的結構.
這些位元欄位為:
- Pr: Present bit. 它必須為 1 ,來表示於有效的選擇子(valid selectors)。
- Privl: Privilege, 2 bits. 包含 ring level, 0 = 最高的 (kernel), 3 = 最小的 (user applications).
- Ex: Executable bit. 如果 1 在這段代碼是可以執行的。即為代碼選擇器。如果為 0,它是資料選擇器。
- DC: Direction bit/Conforming bit.
- 資料選擇器的方向位元 ︰用來告知方向。0 表示segment 增加。1表示segment 減少。即為偏移量必須大於limit。
- Conforming bit for code selectors:
- 如果 1 在這段代碼可以從相等或更低的權限等級執行。例如,ring 3 中的代碼可以far-jump到 conformingcode 中ring 2 段。Privl 位代表的允許執行段的最高權限等級。例如中ring 0, 的代碼不能far-jump到符合標準的程式碼片段與 privl = = 0x2,雖然ring 2 和 3 中的代碼可以。注意權限等級仍然是相同的即。對 privl 的far-jump表單ring 3 = 2 段仍在ring 3 = 後跳。
- 如果在這段代碼 0 只可以從ring 在 privl 中設置執行。
- RW: Readable bit/Writable bit.
- 可讀位元為代碼選擇器 ︰ 是否允許此段的讀存取權限。程式碼片段是永遠不會允許寫存取。
- 可寫位元為資料選擇器 ︰ 是否允許此段的寫存取權限。資料段總是允許讀取存取。
- Ac: Accessed bit. Just set to 0. 只是設置為 0。CPU 將此設置為 1 時存取部分。
- Gr: Granularity bit. 如果為 0 的極限是 1 byte blocks (byte granularity), 如果 1 的限制是在 4 KiB blocks (page granularity).
- Sz: Size bit.如果為 0,選擇器定義了 16 位受保護的模式。如果 1 它定義了 32 位保護的模式。你可以一次用 16 位和 32 位的選擇器。
沒有留言:
張貼留言