前言
在 80386 保護模式架構中,任務狀態段 (TSS) 與控制門 (Control Gates) 共同構成了硬體級任務管理與特權轉移的基石。TSS 保存任務完整上下文,控制門則提供受檢查的轉移入口。本文將系統剖析系統段描述符、各類門描述符、TSS 內部佈局、特權級轉移規則與任務切換流程。
一、系統段描述符:LDT 與 TSS 的元數據
1. 通用格式 (8 位元組)
位 63~56: 基址 31~24
位 55~52: G(粒度) D/B(預設大小) 0 AVL(可用) 界限 19~16
位 51~48: 界限 19~16 (續)
位 47: P(段存在)
位 46~45: DPL(描述符特權級 0~3)
位 44: DT(描述符類型) = 0 表示系統段
位 43~40: TYPE(系統段子類型)
位 39~32: 基址 23~16
位 31~16: 基址 15~0
位 15~0: 界限 15~0
關鍵區別:DT=1 為儲存段 (代碼/資料/堆疊);DT=0 為系統段。TYPE 欄位編碼完全不同:
| TYPE | 系統段/門類型 | 備註 |
| 1 | 可用 286 TSS | |
| 2 | LDT 段 | 僅能放於 GDT |
| 3 | 忙碌 286 TSS | |
| 4 | 286 呼叫門 | 16 位參數複製 |
| 5 | 任務門 | |
| 6 | 286 中斷門 | |
| 7 | 286 陷阱門 | |
| 9 | 可用 386 TSS | 32 位上下文 |
| B | 忙碌 386 TSS | |
| C | 386 呼叫門 | 32 位參數複製 |
| E | 386 中斷門 | 清 IF |
| F | 386 陷阱門 | 保留 IF |
只有 TYPE=1,2,3,9,B 是真正的系統段描述符 (描述記憶體段);其餘為門描述符 (描述轉移入口)。系統段選擇子不能直接讀寫段內容,需用別名技術 (建立對應資料段描述符) 訪問。
2. LDT 描述符範例
LDTABLE DESC <1Fh, 4321h, 65h, 82h, ,> ; 界限=1Fh, 基址=654321h, DPL=0, TYPE=2(LDT)
載入 LLDT 指令時,描述符基址/界限/屬性自動載入 LDTR 隱藏快取。
3. TSS 描述符範例
TempTask DESC <104, 3456h, 12h, 89h, ,> ; 界限=104(104 bytes), 基址=123456h, DPL=0, TYPE=9(可用386 TSS)
載入 LTR 或任務切換時,資訊載入 TR 隱藏快取。TYPE 位 0 (忙/可用) 由硬體自動維護:當前任務及鏈接任務為「忙」,其餘為「可用」。
二、門描述符:受控轉移的入口哨兵
1. 通用門格式 (8 位元組)
位 63~48: 偏移 31~16
位 47~16: 選擇子(16) + 屬性(16) + 雙字計數(5) + 000(3)
位 15~0: 偏移 15~0
屬性位組:P(1) DPL(2) DT=0 TYPE(4)。選擇子指向目標代碼段 (呼叫/中斷/陷阱門) 或 TSS 描述符 (任務門)。
2. 結構定義範例
GATE STRUC
OFFSETL DW 0 ; 偏移低 16
SELECTOR DW 0 ; 目標選擇子
DCOUNT DB 0 ; 雙字計數 (僅呼叫門有效)
GTYPE DB 0 ; P+DPL+DT+TYPE
OFFSETH DW 0 ; 偏移高 16
GATE ENDS
SUBRG GATE <3456h, 10h, , 8Ch+60h, 12h> ; 386 呼叫門, 選擇子=10h, 偏移=123456h, DPL=3
3. 四大門類型功能對比
| 門類型 | 選擇子指向 | 偏移含義 | 觸發指令/事件 | 特權轉移 | 參數複製 |
| 呼叫門 | 代碼段描述符 | 入口點偏移 | CALL FAR | 外層→內層 (CPL>DPL) | 依 DCOUNT 複製雙字參數至內層堆疊 |
| 任務門 | GDT 中 TSS 描述符 | 無意義 (0) | JMP/CALL FAR, Int/Exception | 任意級→目標任務任意級 | 無 (新任務獨立上下文) |
| 中斷門 | 代碼段描述符 | ISR 入口偏移 | 硬體中斷, INT n | 外層→內層 (同呼叫門) | 無 (硬體自動壓 EFLAGS/CS/EIP/錯誤碼) |
| 陷阱門 | 代碼段描述符 | 處理程序入口 | 異常, INT n | 外層→內層 | 無 (同中斷門,但保留 IF) |
核心差異:中斷門進入時清 IF (屏蔽可屏蔽中斷);陷阱門保留 IF。呼叫門獨有雙字計數字段,支援跨特權級參數傳遞。
三、任務狀態段 (TSS) 內部架構全景
386 TSS 基本區固定 104 位元組 (偏移 00h~67h),五大功能區:
1. 鏈接字段 (Offset 00h, 4 bytes)
- 低 16 位:前一任務 TSS 選擇子;高 16 位保留 (0)。
- 任務由 CALL/JMP/Int 經任務門激活時,硬體自動填入被掛起任務 TSS 選擇子,並置 EFLAGS.NT=1。
- IRET (NT=1) 時沿此字段返回前一任務。
2. 內層堆疊指標區 (Offset 04h~1Fh, 24 bytes)
| 偏移 | 欄位 | 大小 | 用途 |
| 04h | ESP0 | 4 | Ring 0 堆疊頂 (SS0:ESP0) |
| 08h | SS0 | 2 | Ring 0 堆疊段選擇子 |
| 0Ch | ESP1 | 4 | Ring 1 堆疊頂 |
| 10h | SS1 | 2 | Ring 1 堆疊段選擇子 |
| 14h | ESP2 | 4 | Ring 2 堆疊頂 |
| 18h | SS2 | 2 | Ring 2 堆疊段選擇子 |
外層→內層轉移時,硬體自動從此區載入 SS:ESP;外層堆疊指標 (SS:ESP) 壓入新堆疊。硬體從不寫回此區,故內層堆疊視為「空堆疊」,不支援同級遞迴。
3. 位址映射暫存器區 (Offset 1Ch, 20h, 60h)
- CR3 (Offset 1Ch, 4 bytes):頁目錄表物理基址。任務切換時自動載入 CR3,切換線性→物理映射。
- LDTR (Offset 60h, 2 bytes):LDT 描述符選擇子。任務切換時自動載入 LDTR,切換虛擬→線性映射。
重要:硬體不自動儲存舊 CR3/LDTR 回 TSS。OS 若修改 CR3/LDTR,必須以別名技術手動更新 TSS 對應欄位。
4. 暫存器保存區 (Offset 20h~5Fh, 64 bytes)
依序保存:EIP、EFLAGS、EAX、ECX、EDX、EBX、ESP、EBP、ESI、EDI、ES、CS、SS、DS、FS、GS (各 4 bytes,段暫存器高 16 位置 0)。任務切出時自動存入,切入時自動恢復。
5. I/O 許可位圖基址與 T 旗標 (Offset 64h~66h)
- Offset 64h (Word):I/O 位圖在 TSS 內偏移 (從 TSS 基址起算)。位圖大小可變,每 I/O 埠 1 位,CPL=3 存取時檢查。
- Offset 66h (Word, 實為 64h 同字低位):T 旗標 (Bit 0)。=1 時任務切入後第一條指令前產生除錯陷阱 (向量 1)。
6. TSS 結構定義巨集 (MASM)
TSS STRUC
TRLink DW 0, 0 ; 鏈接字段
TRESP0 DD 0 ; ESP0
TRSS0 DW 0, 0 ; SS0
TRESP1 DD 0 ; ESP1
TRSS1 DW 0, 0 ; SS1
TRESP2 DD 0 ; ESP2
TRSS2 DW 0, 0 ; SS2
TRCR3 DD 0 ; CR3
TREIP DD 0 ; EIP
TREFlag DD 0 ; EFLAGS
TREAX DD 0 ; EAX
TRECX DD 0 ; ECX
TREDX DD 0 ; EDX
TREBX DD 0 ; EBX
TRESP DD 0 ; ESP
TREBP DD 0 ; EBP
TRESI DD 0 ; ESI
TREDI DD 0 ; EDI
TRES DW 0, 0 ; ES
TRCS DW 0, 0 ; CS
TRSS DW 0, 0 ; SS
TRDS DW 0, 0 ; DS
TRFS DW 0, 0 ; FS
TRGS DW 0, 0 ; GS
TRLDTR DW 0, 0 ; LDTR
TRTrip DW 0 ; T 旗標 (Bit 0)
TRIOMap DW ? ; I/O 位圖偏移
TSS ENDS
四、任務切換完整流程
- 觸發源:
JMP/CALL 任務門或 TSS 描述符、IRET (NT=1)、中斷/異常經任務門。
- 檢查目標 TSS 描述符:P=1、TYPE=可用 (1/9)、DPL ≥ CPL (任務門除外)。
- 儲存當前上下文至舊 TSS (暫存器區、CR3、LDTR 不自動存)。
- 標記舊 TSS 忙位=1,新 TSS 忙位=1 (若經任務門/CALL,舊 TSS 鏈接字段寫入新 TSS 選擇子,NT=1)。
- 載入 TR 可見部 = 新 TSS 選擇子,隱藏快取 = 新 TSS 基址/界限/屬性。
- 從新 TSS 載入:CR3、LDTR、暫存器區 (含 EIP/EFLAGS/通用暫存器/段暫存器)、SS0:ESP0~SS2:ESP2 (依 CPL 選擇)。
- 若新 TSS T 旗標=1,執行第一條指令前產生除錯陷阱。
- 開始執行新任務。
五、工程實踐要點
- TSS 界限:386 TSS 至少 104 (068h) 位元組;含 I/O 位圖時界限 = 104 + 位圖大小 + 1 (終止位)。
- 初始化順序:建立 GDT TSS 描述符 → 以別名寫入 TSS 初始值 (CR3、LDTR、SS0:ESP0 等) →
LTR 載入 TR 啟動首個任務。
- 嵌套任務:僅 CALL/JMP 任務門、中斷任務門會建立鏈接 (NT=1);IRET 返回時自動順鏈恢復。
- 效能考量:硬體任務切換 ~300 週期,遠慢於軟體切換 (現代 OS 多用軟體切換 + TSS 僅作 Ring 0 堆疊與 I/O 位圖)。
結語
TSS 與控制門是 80386 實現硬體強制多任務隔離、特權受控轉移的雙引擎。雖然現代作業系統為效能多採用軟體調度,但 TSS 仍保留關鍵角色:Ring 0 堆疊指標、I/O 許可位圖、雙重錯誤/機器檢查等致命異常的專用 TSS。深入理解其結構與硬體流程,是作業系統核心開發、Hypervisor 編寫、安全研究的核心基本功。
- 上一篇文章: 從零打造磁碟分區掃描器:prw.asm 核心邏輯與 BIOS Int 13h 深度實戰
- 下一篇文章: Win32 組合語言 GUI 程式設計:以對話框為主視窗的兩種實戰架構模式
Copyright ©
程式碼之家 All Rights Reserved