在 x86 保護模式程式設計中,異常處理是核心且複雜的課題。本文透過一個完整的組合語言實例(實例七),詳細演示如何模擬並處理多種常見的處理器異常,包括除法錯誤、溢出、段不存在、堆疊段錯誤與通用保護故障。同時展示如何利用任務門實現獨立任務的鍵盤輸入處理。此實例對於理解中斷描述符表(IDT)、任務狀態段(TSS)、局部描述符表(LDT)的實際運作極具參考價值。
程式包含兩個獨立任務:演示任務與讀鍵盤任務。主要組成部分:
切換到保護模式後進入臨時代碼段,演示任務不發生特權級變換,簡化了演示邏輯。
INT 0FFh 調用讀鍵盤任務(任務門),接收用戶輸入的異常類型字符(0、4、B、C、D)故意執行 DIV CL(被除數 2000,除數 2)觸發。處理程序顯示提示後,將 AX 右移一位(除以 2),然後 IRETD 返回。因為是 Fault,指令會重新執行,經過幾次處理後被除數變小,不再觸發故障。
執行 INTO 觸發。處理程序僅顯示提示並返回。屬於 Trap,返回下一條指令繼續執行。
將 P=0 的選擇子載入 GS 觸發。處理程序顯示提示、彈出錯誤碼、調用顯示錯誤碼子程序、調整返回地址(+2 字節)後 IRETD,跳過故障指令。
透過超出段界限的堆疊訪問指令觸發。處理邏輯類似段不存在,調整返回地址 +4 字節。
將系統段描述符選擇子載入 GS 觸發。處理程序保護現場、顯示提示與錯誤碼、調整返回地址 +2 字節、清除錯誤碼後返回。
IDT 中 0FFh 為任務門,指向獨立 TSS。演示任務執行 INT 0FFh 發起任務切換。讀鍵盤任務為簡化在實模式下運作:
IRETD 觸發反向任務切換返回演示任務任務代碼段中 IRETD 後緊跟 JMP GKeyBegin,確保下次進入時從頭開始執行。
源碼採用 TASM/TLINK 開發,包含完整的 GDT/IDT 定義、各任務 LDT/TSS/代碼/數據段、異常處理入口、顯示子程序、實模式啟動代碼。關鍵宏定義見 386SCD.INC。程式展示了保護模式下多任務、異常處理、任務門切換的實戰範本。
實例七通過精心設計的指令序列模擬真實異常場景,配合完整的描述符表與任務結構,直觀展示了 x86 保護模式異常處理的核心機制。特別是任務門實現的鍵盤輸入任務,演示了硬體任務切換的自動現場保存/恢復特性。雖然演示代碼為教學簡化(如未完整保護現場),但架構完整,極適合深入研讀保護模式程式設計。