象中斷分為多種類型一樣,異常也可分為多種類型。
1.80386識別的異常
80386識別的多種不同類別的異常及賦予的對應中斷向量號如下表所示。某些異常還以出錯碼的形式提供一些附加信息傳遞給異常處理程序,出錯代碼列中的“無”表示沒有出錯代碼,“有”表示有出錯代碼。
異
常
一
覽
表
向量號
異常名稱
異常類型
出錯代碼
相關指令
0
除法出錯
故障
無
DIV,IDIV
1
調試異常
故障/陷阱
無
任何指令
3
單字節INT3
陷阱
無
INT 3
4
溢出
陷阱
無
INTO
5
邊界檢查
故障
無
BOUNT
6
非法操作碼
故障
無
非法指令編碼或操作數
7
設備不可用
故障
無
浮點指令或WAIT
8
雙重故障
中止
有
任何指令
9
協處理器段越界
中止
無
訪問存儲器的浮點指令
0AH
無效TSS異常
故障
有
JMP、CALL、IRET或中斷
0BH
段不存在
故障
有
裝載段寄存器的指令
0CH
堆棧段異常
故障
有
裝載SS寄存器的任何指令、對SS尋址的段訪問的任何指令
0DH
通用保護異常
故障
有
任何特權指令、任何訪問存儲器的指令
0EH
頁異常
故障
有
任何訪問存儲器的指令
10H
協處理器出錯
故障
無
浮點指令或WAIT
11H—0FFH
軟中斷
陷阱
無
INT n
由上表可見,保護模式下的某些中斷向量號的分配與實模式的中斷向量號發生了沖突。實模式下的中斷向量號的分配基於PC微機系統的8086/8088 CPU,上表中的中斷向量號的分配是80386所規定的。實際上,Intel在宣布8086/8088時,保留了這些發生沖突的中斷向量號。盡管發生這樣的沖突,但以80386為CPU的微機系統仍可保持與以8086/8088為CPU的微機系統的兼容,原因是在80386的實模式下,幾乎不發生那些中斷向量號與外部硬件中斷請求時所提供的中斷向量號存在沖突的異常。需要注意的是,在保護模式下必須重新設置8259A中斷控制器,以產生不與異常相沖突的硬件中斷向量。
2.故障類異常
當發生故障,控制轉移到故障處理程序時,所保存的斷點CS及EIP的值指向引起故障的指令,以便在排除故障後恢復執行。
(1)除法出錯故障(異常0)
除法出錯是一種故障。當執行DIV指令或IDIV指令時,如果除數等於0或者商太大,以至於存放商的操作數容納不下,那麼就產生這一故障。除法出錯故障不提供出錯碼。
(2)邊界檢查故障(異常5)
如果BOUND指令發現被測試的值超過了指令中給定的范圍,那麼就發生邊界檢查故障。邊界檢查故障不提供出錯碼。
(3)非法操作碼故障(異常6)
如果80386不能把CS和EIP所指向存儲單元的位模式識別為某條指令的部分,那麼就發生非法操作碼故障。當出現如下情況時,發生這樣的故障:(1)操作碼字段的內容不是一個合法的80386指令代碼;(2)要求使用存儲器操作數的場合,使用了寄存器操作數;(3)不能被加鎖的指令前使用了LOCK前綴。非法操作碼故障不提供操作碼。
(4)設備不可用故障(異常7)
設備不可用故障支持80387數字協處理器。在沒有80387協處理器硬件的系統中,可用該異常的處理程序代替協處理器的軟件模擬器。在發生任務切換時,使得只有在新任務使用浮點指令時,才進行80387寄存器狀態的切換。設備不可用故障不提供出錯碼。該故障在下列情況下產生:(1)在執行浮點指令時,控制寄存器CR0中的EM位或TS位為1;(2)在執行WAIT指令時,控制寄存器CR0中TS位及EM位都為1。需要注意的是,本異常的處理程序必須是一個過程而不能是任務,否則當處理程序發布一條IRET指令時,80386就設置TS位。然後協處理器再次執行這個發生故障的指令,發現TS是置位的,因此就再次發生異常7,結果是無休止的循環。處理程序能通過陷阱門被調用,因為執行期間可以允許中斷。
(5)無效TSS故障(異常0AH)
當正從任務狀態段TSS裝入選擇子時,如果發生了除了段不存在故障以外的段異常時,就發生無效TSS故障。在進入故障處理程序時,保存的CS及EIP指向發生故障的指令;或者該故障作為任務切換的一部分發生時,指向任務的第一條指令。 無效TSS故障提供了一個出錯碼,出錯碼的格式如下圖所示。其中選擇子部分是指向引起故障的TSS的選擇子。16位的出錯代碼的主要成分是選擇子,指向引起故障的TSS的選擇子。高13位是選擇子的索引部分,TI位是描述符表指示位。
出錯代碼的格式
BIT15—BIT3
BIT2
BIT1
BIT0
選擇子的索引部分
TI
IDT
EXT
上圖所示出錯碼格式是異常時出錯碼的一般格式。從圖中可見出錯碼中不含選擇子的RPL,而由IDT位和EXT位代替。當處理某一異常或外部中斷時,又發生了某種異常,那麼EXT位置1。當從中斷描述符表IDT中讀出表項並產生異常時,IDT位置1,這只在中斷或異常的處理期間才會發生。當沒有選擇子時,構成出錯碼選擇子部分的值為0。 一些引起無效TSS故障的原因如下: TSS描述符中的段限長小於103; 無效的LDT描述符,或者LDT未出現; 堆棧段不是一個可寫段; 堆棧段選擇子索引的描述符超出描述符表界限; 堆棧段DPL與新的CPL不匹配; 堆棧段選擇子的RPL不等於CPL; 代碼段選擇子索引的描述符超出描述符表界限; 代碼段選擇子不指向代碼段; 非一致代碼段的DPL不等於新的CPL; 一致代碼段的DPL大於新的CPL; 對應DS、ES、FS或GS的選擇子指向一個不可讀段(如系統段); 對應DS、ES、FS或GS的選擇子索引的描述符超出描述符表的界限。
(6)段不存在故障(異常0BH)
處理器在把描述符裝入非SS段寄存器的高速緩沖時,如果發現描述符其它方面有效,而P位為0(表示對應段不存在),那麼在引用此描述符時就發生段不存在故障。有關SS段的情形納入堆棧段故障。在進入故障處理程序時,保存的CS及EIP執行發生故障的指令;或者該故障作為任務切換的一部分發生時,指向任務的第一條指令。 段不存在故障提供了一個包含引起該故障的段選擇子的出錯代碼。出錯碼的格式如上圖所示。選擇子索引部分為引起段不存在故障的段描述符選擇子的索引。
(7)堆棧段故障(異常0CH)
當處理器檢測到用SS寄存器進行尋址的段有關的某種問題時,就發生堆棧段故障。在進入故障處理程序時,保存的CS及EIP指向發生故障的指令;或者該故障作為任務切換的一部分發生時,指向任務的第一條指令。堆棧段故障提供一個出錯碼,出錯碼的格式也如上圖。 具體地說,當出現下列三種情況時,將引起堆棧段故障: (1)在堆棧操作時,偏移超出段界限所規定的范圍。這種情況下的出錯碼是0。例如PUSH操作時,堆棧溢出。 (2)在由特權級變換所引起的對內層堆棧的操作時,偏移超出段界限所規定的范圍。這種情況下的出錯碼包含有內層堆棧的選擇子。 (3)裝入到SS寄存器(高速緩沖寄存器)的描述符中的存在位為0。這種情況下的出錯碼包含有對應的選擇子。 上述第一種情況是容易辨別的。第二和第三種情況的辨別要通過判斷出錯代碼所含選擇子所指示的描述符中的存在位進行。如果存在位為1,那麼是第二種情況;否則是第三種情況。
(8)通用保護故障(異常0DH)
除了明確列出的段異常外,其它的段異常都被視為通用保護故障。在進入故障處理程序時,保存的CS及EIP指向發生故障的指令;或者該故障作為任務切換的一部分發生時,指向任務的第一條指令。通用保護故障提供一個出錯碼,出錯碼的格式也如上圖所示。 根據處理程序可能作出的響應,通用保護故障可分為如下兩類: (1)違反保護方式,但程序無須中止的異常。這類故障提供的出錯碼為0。這種異常在應用程序執行特權指令或I/O訪問時發生,支持虛擬8086程序的系統或支持虛擬I/O訪問的系統需要模擬這些指令,並在模擬完成產生故障的指令後,重新執行被中斷的程序。 (2)違反保護方式,並導致程序終止的異常。這類故障提供的出錯碼可能為0,也可能不為0(能確定選擇子時)。引起這類故障的一些原因如下: 向某個只讀數據段或代碼段寫; 從某個只能執行的代碼段讀出; 將某個系統段描述符裝入到數據段寄存器DS、ES、FS、GS或SS; 將控制轉移到一個不可執行的段; 在通過段寄存器CS、DS、ES、FS或GS訪問內存時,偏移超出段界限; 當訪問某個描述符表時,超過描述符表段界限; 把PG位為1但PE位為0的控制信息裝入到CR0寄存器; 切換到一個正忙的任務。 對上述兩類通用保護故障的辨別,可通過檢查引起故障的指令和出錯碼進行。如果出錯碼非0,那麼肯定是第二類通用保護故障。如果出錯碼是0,那麼需要進一步檢查引起故障的指令,以確定它是否是系統支持的可以模擬的指令。
(9)頁故障(異常0EH)
關於頁故障的詳細說明請見後面的文章。
(10)協處理器出錯(異常10H)
協處理器出錯故障指示協處理器發生了未被屏蔽的數字錯誤,如上溢或下溢。在引起故障的浮點指令之後的下一條浮點指令或WAIT指令,把協處理器出錯作為一個故障通知給系統。協處理器出錯故障不提供出錯碼。
3.陷阱類異常
(1)調試陷阱(異常1)
調試異常有故障類型,也有陷阱類型。調試程序可以訪問調試寄存器DR6,以確定調試異常的原因和類型。調試異常不提供出錯碼。
(2)單字節INT3(異常3)
INT3是一條特別的單字節“INT n”指令。調試程序可利用該指令支持程序斷點。INT3指令被看成是一種陷阱,而不是一個中斷。當由於執行INT3指令進入異常3處理程序時,被保存的CS和EIP指向緊跟INT3的指令,即INT3後面的字節。INT3陷阱不提供出錯碼。
(3)溢出(異常4)
INTO指令提供條件陷阱。如果OF標志為1,那麼INTO指令產生陷阱;否則不產生陷阱,繼續執行INTO後面的指令。在進入溢出處理程序時,被保存的CS和EIP指向INTO指令的下一條指令。溢出陷阱不提供出錯碼。
4.中止類異常
(1)雙重故障異常(異常8)
當系統正在處理一個異常時,如果又檢測到一個異常,處理器試圖向系統通知一個雙重故障,而不是通知第二個異常。雙重故障屬於中止類異常,所以在轉入雙重故障處理程序時,被保存的CS和EIP可能不指向引起雙重故障的指令,而且指令的重新啟動不支持雙重故障。雙重故障提供的出錯碼為0。 當正處理一個段故障異常時,有可能又產生一個頁故障。在這種情況下,通知給系統的是一個頁故障異常而不是雙重故障異常。但是,如果正處理一個段故障或頁故障時,又一個段故障被檢測到;或者如果正處理一個頁故障時,又一個頁故障被檢測到,那麼就引起雙重故障。 當正處理一個雙重故障時,又一個段或頁故障被檢測到,那麼處理器暫停執行指令,並進入關機方式。關機方式類似於處理器指令一條HLT指令後的狀態:處理器空轉,並維持到處理器接收到一個NMI中斷請求或者被重新啟動為止。在關機方式下,處理器不響應INTR中斷請求。 雙重故障通常指示系統表出現嚴重的問題,例如段描述符表、頁表或中斷描述符表出現問題。雙重故障處理程序在重建系統表後,可能不得不重新啟動操作系統。
(2)協處理器段越界(異常9)
協處理器段越界異常屬於中止類異常,這是因為引起該異常的指令不能被重新啟動。當浮點指令操作數超出段界限時,產生該中止異常。協處理器段越界異常不提供出錯碼。在異常處理程序入口保存的CS及EIP指向被中止的指令。這種中止不是系統的中止,而是只影響檢測到這種異常時正執行的指令所在的程序。