到目前為止,我們都受限於 16 位元的「實模式(Real Mode)」。在那裡,我們只能存取約 1MB 的記憶體,且沒有任何硬體層級的權限保護。
進入 32 位元保護模式後,我們將獲得:
在保護模式下,CPU 不再使用 Segment * 16 + Offset 的公式,而是透過 GDT 這張「權限清單」來決定記憶體的屬性。
我們在定義 GDT 時,會看到兩組神祕的位元設定。這就是決定段屬性的關鍵:
決定了這段記憶體是「代碼」還是「資料」,以及誰能讀寫它。
| 位元 (Bit) | 名稱 | 說明 | 程式碼段 (1010b) | 資料段 (0010b) |
|---|---|---|---|---|
| 7 | P (Present) | 必須為 1 才是有效的描述符。 | 1 | 1 |
| 6-5 | DPL | 特權等級。00 為最高 (Kernel), 11 為最低 (User)。 | 00 | 00 |
| 4 | S (System) | 1 代表代碼/資料段,0 代表系統專用段。 | 1 | 1 |
| 3 | Ex (Executable) | 核心位元:1 為程式碼,0 為資料。 | 1 | 0 |
| 2 | DC | 描述段的生長方向或一致性。 | 0 | 0 |
| 1 | RW | 程式碼段:1 可讀;資料段:1 可寫。 | 1 | 1 |
| 0 | Ac (Accessed) | CPU 自動設定,初始化通常設為 0。 | 0 | 0 |
決定了記憶體段的大小計算方式。
| 位元 (Bit) | 名稱 | 說明 | 設定值 |
|---|---|---|---|
| 7 | G (Granularity) | 0 為 1B 單位;1 為 4KB 單位 (讓 Limit 達到 4GB)。 | 1 |
| 6 | D/B (Size) | 1 代表 32-bit 定址;0 代表 16-bit。 | 1 |
| 5 | L (Long mode) | 1 代表 64-bit。在 32-bit 開發中必須為 0。 | 0 |
gdt.asm)gdt_start:
; the GDT table requires an empty GDT as first entry
gdt_null: ; 1. 強制性的空描述符 (8 bytes)
dd 0x0
dd 0x0
gdt_code: ; 2. 程式碼段描述符
dw 0xffff ; Limit (0-15 bits)
dw 0x0 ; Base (0-15 bits)
db 0x0 ; Base (16-23 bits)
db 10011010b ; Access Byte (Present, Ring 0, Code, Exec/Read)
db 11001111b ; Flags + Limit (4KB granularity, 32-bit)
db 0x0 ; Base (24-31 bits)
gdt_data: ; 3. 資料段描述符
dw 0xffff
dw 0x0
db 0x0
db 10010010b ; Access Byte (Present, Ring 0, Data, Read/Write)
db 11001111b
db 0x0
gdt_end:
gdt_descriptor:
dw gdt_end - gdt_start - 1 ; GDT 大小
dd gdt_start ; GDT 起始位址
; 常數定義,方便段暫存器載入
CODE_SEG equ gdt_code - gdt_start
DATA_SEG equ gdt_data - gdt_start