<一>80386的中斷和異常
8086/8088把中斷分為內部中斷和外部中斷兩大類。為了支持多任務和虛擬存儲器等功能,80386把外部中斷稱為“中斷”,把內部中斷稱為“異常”。與8086/8088一樣,80386通常在兩條指令之間響應中斷或異常。80386最多處理256種中斷或異常。
1.中斷
對80386而言,中斷是由異步的外部事件引起的。外部事件及中斷響應與正執行的指令沒有關系。通常,中斷用於指示I/O設備的一次操作已完成。與8086/8088一樣,80386有兩根引腳INTR和NMI接受外部中斷請求信號。INTR接受可屏蔽中斷請求。NMI接受不可屏蔽中斷請求。在80386中,標志寄存器EFLAGS中的IF標志決定是否屏蔽可屏蔽中斷請求。
外部硬件在通過INTR發出中斷請求信號的同時,還要向處理器給出一個8位的中斷向量。處理器在響應可屏蔽中斷請求時,讀取這個由外部硬件給出的中斷向量號。處理器對這個中斷向量號並沒有規定。但在具體的微機系統中,系統必須通過軟件和硬件的配合設置,使得給出的這個中斷向量號不僅與外部中斷源對應,而且要避免中斷向量號使用沖突情況的出現。可編程中斷控制器芯片8259A可配合80386工作,能夠根據設置向處理器提供上述中斷向量號,還能處理中斷請求的優先級。每個8259A芯片可以支持8路中斷請求信號,如果使用9個8259A芯片(一個主片,8個從片),就可使80386在單個引腳INTR上接受多達64個中斷源的中斷請求信號。
處理器不屏蔽來自NMI的中斷請求。處理器在響應NMI中斷時,不從外部硬件接收中斷向量號。與8086/8088一樣,在80386中,不可屏蔽中斷所對應的中斷向量號固定為2。為了不可屏蔽中斷的嵌套,每當接受一個NMI中斷,處理器就在內部屏蔽了再次響應NMI,這一屏蔽過程直到執行中斷返回指令IRET后才結束。所以,NMI處理程序應以IRET指令結束。
2.異常
異常是80386在執行指令期間檢測到不正常的或非法的條件所引起的。異常與正執行的指令有直接的聯系。例如,執行除法指令時,除數等於0。再如,執行指令時發現特權級不正確。當發生這些情況時,指令就不能成功完成。軟中斷指令“INT n”和“INTO”也歸類於異常而不稱為中斷,這是因為執行這些指令產生異常事件。
80386識別多種不同類別的異常,並賦予每一種類別以不同的中斷向量號。異常發生后,處理器就象響應中斷那樣處理異常。即根據中斷向量號,轉相應的中斷處理程序。把這種中斷處理程序稱為異常處理程序可能更合適。
根據引起異常的程序是否可被恢復和恢復點不同,把異常進一步分類為故障(Fault)、陷阱(Trap)和中止(Abort)。我們把對應的異常處理程序分別稱為故障處理程序、陷阱處理程序和中止處理程序。
故障是在引起異常的指令之前,把異常情況通知給系統的一種異常。80386認為故障是可排除的。當控制轉移到故障處理程序時,所保存的斷點CS及EIP的值指向引起故障的指令。這樣,在故障處理程序把故障排除后,執行IRET返回到引起故障的程序繼續執行時,剛才引起故障的指令可重新得到執行。這種重新執行,不需要操作系統軟件的額外參與。故障的發現可能在指令開始執行之前,也可能在指令執行期間。如果在指令執行期間檢測到故障,那么中止故障指令,並把指令的操作數恢復為指令開始執行之前的值。這可保證故障指令的重新執行得到正確的結果。例如,在一條指令的執行期間,如果發現段不存在,那么停止該指令的執行,並通知系統產生段故障,對應的段故障處理程序可通過加載該段的方法來排除故障,之后,原指令就可成功執行,至少不再發生段不存在的故障。
陷阱是在引起異常的指令之后,把異常情況通知給系統的一種異常。當控制轉移到異常處理程序時,所保存的斷點CS及EIP的值指向引起陷阱的指令的下一條要執行的指令。下一條要執行的指令,不一定就是下一條指令。因此,陷阱處理程序並不是總能根據保存的斷點,反推確定出產生異常的指令。在轉入陷阱處理程序時,引起陷阱的指令應正常完成,它有可能改變了寄存器或存儲單元。軟中斷指令、單步異常是陷阱的例子。
中止是在系統出現嚴重情況時,通知系統的一種異常。引起中止的指令是無法確定的。產生中止時,正執行的程序不能被恢復執行。系統接收中止后,處理程序要重新建立各種系統表格,並可能重新啟動操作系統。硬件故障和系統表中出現非法值或不一致的值是中止的例子。
3.優先級
在一條指令執行期間,入檢測到不只一個中斷或異常,那么按下表所列優先級通知系統。把優先級最高的中斷或異常通知系統,其它優先級較低的異常被廢棄,而優先級較高的中斷則保持懸掛。
80386響應 中斷/異常 的優先級 |
中斷/異常類型 | 優先級 |
調試故障 | 最高 | |
其它故障 | ↓ | |
陷阱指令INT n和INTO | ↓ | |
調試陷阱 | ↓ | |
NMI中斷 | ↓ | |
INTR中斷 | 最低 |
<二>異常類型
象中斷分為多種類型一樣,異常也可分為多種類型。
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指向被中止的指令。這種中止不是系統的中止,而是只影響檢測到這種異常時正執行的指令所在的程序。
<三>中斷和異常的轉移方法
80386實模式下的中斷和異常的轉移方法與8086相同。這里介紹的中斷和異常的轉移方法是指 80386在保護模式下響應中斷和處理異常時所采用的轉移方法。
1.中斷描述符表IDT
與8086/8088一樣,在響應中斷或者處理異常時,80386根據中斷向量號轉對應的處理程序。但是,在保護模式下,80386不使用實模式下的中斷向量表,而是使用中斷描述符表IDT。在保護模式下,80386把中斷向量號作為中斷描述符表IDT中描述符的索引,而不再是中斷向量表中的中斷向量的索引。
象全局描述符表GDT一樣,在整個系統中,中斷描述符表IDT只有一個。中斷描述符表寄存器IDTR指示IDT在內存中的位置。由於80386只識別256個中斷向量號,所以IDT最大長度是2K。
中斷描述符表IDT所含的描述符只能是中斷門、陷阱門和任務門。也就是說,在保護模式下,80386只有通過中斷門、陷阱門或任務門才能轉移到對應的中斷或異常處理程序。
從前文中給出的門描述符的格式可見,門描述符包含由選擇子和偏移構成的48位全指針。另外,雙字計數字段對中斷門、陷阱門和任務門而言無意義。
2.中斷響應和異常處理的步驟
由硬件自動實現的中斷響應和異常處理的步驟如下:
首先,判斷中斷向量號要索引的門描述符是否超出IDT的界限。若超出界限,就引起通用保護故障,出錯碼為中斷向量號乘8再加2。
其次,從IDT中取得對應的門描述符,分解出選擇子、偏移量和描述符屬性類型,並進行有關檢查。描述符只能是任務門、286中斷門、286陷阱門、386中斷門或386陷阱門,否則就引起通用保護故障,出錯碼是中斷向量號乘8再加2。如果是由INT n指令或INTO指令引起轉移,還要檢查中斷門、陷阱門或任務門描述符中的DPL是否滿足CPL<=DPL(對於其它的異常或中斷,門中的DPL被忽略)。這種檢查可以避免應用程序執行INT n指令時,使用分配給各種設備用的中斷向量號。如果檢查不通過,就引起通用保護故障,出錯碼是中斷向量號乘8再加2。門描述符中的P位必須是1,表示門描述符是一個有效項,否則就引起段不存在故障,出錯碼是中斷向量號乘8再加2。
最后,根據門描述符類型,分情況轉入中斷或異常處理程序。
對於異常處理,在開始上述步驟之前,還要根據異常類型確定返回點;如果有出錯代碼,則形成符合出錯碼格式的出錯碼,並在實際執行異常處理程序之前把出錯碼壓入堆棧。為了保證棧的雙字邊界對齊,16位的出錯碼以32位的值壓入,其中高16位的值未作定義,對於16位段也是如此。
3.通過中斷門或陷阱門的轉移
如果中斷向量號所指示的門描述符是386中斷門或386陷阱門,那么控制轉移到當前任務的一個處理程序過程,並且可以變換特權級。與其它調用門的CALL指令一樣,從中斷門和陷阱門中獲取指向處理程序的48位全指針。其中16位選擇子是對應處理程序或代碼段的選擇子,它指示全局描述符表GDT或局部描述符表LDT中的代碼段描述符;32位偏移指示處理程序入口點在代碼段內的偏移量。
通過中斷門或陷阱門的轉移過程如下所示,
該過程由硬件自動進行。
(1)若選擇子為空,則產生通用保護故障;
(2)取對應的描述符;
(3)若非存儲段描述符,則產生通用保護故障;
(4)若非一致代碼段且DPL
(5)調整RPL=0;
(6)把描述符裝入CS;
(7)若入口偏移越界,則產生通用保護故障;
(8)EFLAGS壓入堆棧;
(9)CS壓入堆棧;
(10)EIP壓入堆棧;
(11)使TF=0,NT=0;
(12)若為中斷門,則使IF=0;
(13)若有出錯碼,則把出錯碼壓入堆棧;
(14)轉入處理程序。
由上述轉移過程可見,中斷門或陷阱門中指示處理程序的選擇子必須指向描述一個可執行的代碼段的描述符。如果選擇子為空,就引起通用保護故障,出錯碼是0。如果描述符不是代碼段描述符,就引起通用保護故障,出錯碼含選擇子。
中斷或異常可以轉移到同一特權級或內層特權級。上述指定處理程序代碼段的描述符中的類型及DPL字段,決定了這種同一任務內的轉移是否要發生特權級變換。如果是一個非一致代碼段,並且DPLCPL則產生通用保護異常。
上述轉移過程中的第六步,也就是“把描述符裝入CS”,是指把上述指定處理程序段的描述符裝入CS的高速緩沖寄存器中,在這一步驟中要對描述符進行類似通過調用門進行轉移的其它檢查,包括是否代碼段描述符和代碼段描述符是否存在等,因此可能再發生異常。在對該描述符進行檢查時,通過調整門中選擇子的RPL=0(在處理器內部調整,而不影響存儲器中的選擇子的RPL字段)的方法,實現只考慮代碼段的DPL,而不考慮門中選擇子的RPL。把描述符裝入CS之后,還要檢查門描述符中給出的表示處理程序代碼段入口的偏移是否越界,即是否超出段界限。如果越界,就引起出錯碼為0的通用保護故障。
從轉移過程還可以看出,把標志寄存器和斷點壓入堆棧的做法和順序與實模式是相同的,但這里每一次堆棧操作是一個雙字,CS被擴展成32位。在16位段中亦是如此。
把TF置成0,表示不允許處理程序單步執行。把NT置成0,表示處理程序在利用中斷返回指令IRET返回時,返回到同一任務而不是一個嵌套任務。需要注意的是,任何特權級的程序都可改變NT位,這樣可以利用中斷或陷阱處理程序完成任務切換。
通過中斷門的轉移和通過陷阱門的轉移之間的差別只是對IF標志的處理。對於中斷門,在轉移過程中把IF置為0,使得在處理程序執行期間屏蔽掉INTR中斷(當然,在中斷處理程序中可以人為設置IF標志打開中斷,以使得在處理程序執行期間允許響應可屏蔽中斷);對於陷阱門,在轉移過程中保持IF位不變,即如果IF位原來是1,那么通過陷阱門轉移到處理程序之后仍允許INTR中斷。因此,中斷門最適宜於處理中斷,而陷阱門適宜於處理異常。
在有出錯碼的情況下,轉入處理程序之前還要把出錯碼壓入堆棧。只有異常處理才可能有出錯碼。下圖給出了通過中斷門或陷阱門轉移時的堆棧情況。(a)是沒有變換特權級和沒有出錯碼的情形;(b)是沒有變換特權級有出錯碼的情形;(c)是變換特權級和沒有出錯碼的內層堆棧的情形。(d)是變換特權級和有出錯碼的內層堆棧情形。注意圖中每一項為雙字。

4.通過任務門的轉移
如果中斷向量號所只是的門描述符是任務門描述符,那么控制轉移到一個作為獨立的任務方式出現的處理程序。任務門中的選擇子是指向描述對應處理程序任務的TSS段的選擇子,即該選擇子指示一個可用的286TSS或386TSS。通過任務門的轉移與通過任務門到一個可用的386TSS的段間調用指令CALL的轉移很相似,主要的區別是,對於提供出錯碼的異常處理,在完成任務切換之后,把出錯碼壓入新任務的堆棧中(通過任務門進行轉移時,返回地址和外層棧指針不壓入新任務的堆棧)。
通過任務門的轉移,在進入中斷或異常處理程序時,標志寄存器EFLAGS中的NT位被置為1,表示是嵌套任務,則IRET指令返回時,沿TSS中的鏈接字段返回到最后一個被掛起的任務。
在響應中斷或處理異常時,使用任務門可提供一個處理程序任務的自動調度。這種任務調度由硬件直接執行,並且越過包含在操作系統中的軟件任務切換,這就為處理程序提供了一個快速的任務切換。
5.轉移方法的比較
對中斷的響應和異常的處理,80386允許通過使用中斷門或陷阱門實現由當前任務之內的一個過程進行處理;也允許通過使用任務門實現由另一個任務進行處理。在當前任務之內的處理程序較為簡單,並可以很快地轉移到處理程序,但處理程序要負責保存及恢復處理器的寄存器等內容。轉到不同任務的處理程序要花費較長時間,保存及恢復處理器寄存器內容的開銷作為任務切換的一部分。使用當前任務內的處理程序的方法,在響應中斷或處理異常時,對正執行任務的狀態可直接進行訪問,但是這就要求每一個任務之內都包含一個處理程序。使用獨立任務的處理方法,使處理程序得到較好的隔離,但在響應中斷或處理異常時,對原任務狀態的訪問變得較為復雜。需要注意得是,有些異常必須由中斷門或陷阱門進行處理,如上面提到得異常7。
無效TSS異常必須使用任務門進行處理,以保證處理程序有一個有效得任務環境。其它得異常通常在任務環境之內進行處理。在任務內,異常被檢測並且不必屏蔽中斷,所以,所以使用陷阱門。由陷阱門指示的異常處理程序是一個由所有任務共享的過程,所以該處理程序最好置於全局地址空間之內。如果各個任務要求有不同的處理程序,那么全局異常處理程序可保存一個各處理程序的入口表,並為引起異常的任務調用相應的處理程序。
中斷通常與正執行的任務沒有關系,並可能從使用任務門提供的隔離中獲得好處。要求較快響應的中斷,通過中斷門可以得到較好的處理。因為中斷隨時都可能發生,所以,通過中斷門訪問的中斷處理程序,必須置於全局地址空間中,以便對所有的任務都有效。還需強調的是,80386程序絕不能調用一個低特權級的過程,當處理器調用一個中斷或異常處理程序時,它實施相同的規則,所以,這樣一個過程必須至少具有與在其任務上下文中被調用的、由任務所執行的最高特權級的過程相同的特權級。因此,在使用中斷門時,中斷處理程序通常必須被安排在特權級0,否則若正在特權級0執行時發生中斷,則不能進入中斷處理程序,而會引起通用保護故障(中斷處理程序使用任務門時除外,因為任務切換可以從任何特權級切換到目標任務的任何特權級)。
6.中斷或異常處理后的返回
中斷返回指令IRET用於從中斷或異常處理程序的返回。該指令的執行根據任務嵌套標志NT位是否為1分為兩種情形。
NT位為1,表示是嵌套任務的返回。當前TSS中的鏈接字段保存有前一任務的TSS的選擇子,取出該選擇子進行任務切換就完成了返回。這種情形在由通過任務門轉入的中斷或異常處理程序返回時出現,因為在由中斷門或陷阱門轉入處理程序時,NT位已被清0。
NT位為0,表示當前任務內的返回。這種情形在由通過中斷門或陷阱門轉入的中斷或異常處理程序返回時出現。具體進行的操作包括:從堆棧頂彈出返回指針EIP及CS,然后彈出EFLAGS值。彈出的CS選擇子的RPL字段,確定返回后的特權級。如果返回選擇子的RPL與CPL相同,則不進行特權級改變。若RPL規定了一個外層特權級,則需要特權級改變,從內層堆棧中彈出外層堆棧的指針ESP及SS的值。這些做法與RET指令相似。例如,使用CS選擇子的RPL,而不是由選擇子標識的段的DPL,是為了返回到不在DPL給定特權級的一致代碼段。若彈出的CS的選擇子的RPL規定了一個內層特權級,則產生通用保護故障。需要注意的是,對於IRET指令,保存在當前堆棧中的返回地址中的選擇子字段必須指向代碼段描述符。而不能是系統段或門描述符。否則將引起通用保護故障。
對於提供出錯代碼的異常處理程序,必須先人為地從堆棧中彈出出錯代碼,然后再執行IRET指令,及出錯代碼不會自動被處理器彈出或取消。
中斷返回指令IRET不僅能夠用於由中斷/異常引起的嵌套任務的返回,而且也適用於由段間調用指令CALL通過任務門引起的嵌套任務的返回,如前文所述,在執行通過任務門進行任務切換的段間調用指令CALL時,標志寄存器中的NT位被置為1,表示任務嵌套。而RET指令不能實現此功能。