0 前言
基于王爽《匯編語言》和Coursera的《計算機組成》課程。
1 中斷分類
CPU在執行指令的過程中,產生了一個異常/中斷,因為CPU只能同時執行一條指令,所以需要暫停該指令的執行,轉而去處理異常/中斷信息。
這個異常可以來源于
- 內部中斷
- 指令執行本身:例如 0號中斷(除法錯中斷
自動檢測
、INT 0
)、4號中斷(溢出中斷INTO
、INT 4
) - 程序調試,例如1號中斷(單步中斷
INT 1
)、3號中斷(斷點中斷INT 3
)
- 指令執行本身:例如 0號中斷(除法錯中斷
- 外部中斷:與CPU相關的信號有關
- 可屏蔽中斷
- 不可屏蔽中斷
2 內中斷實例分析:除法錯中斷
我們來看一看除法錯中斷發生的完整過程,來理解中斷的相關概念。
2.0 來源
程序實例
assume cs:datasg
datasg segment
start:mov ax,1000hmov bh,1div bhmov ax,4c00hint 21h
datasg ends
end start
2.1 產生 & 檢測
很明顯,1000h / 1
得到的商超過了8位(AL的范圍),會產生溢出。從而被CPU內部的中斷檢測部件檢測出來,觸發中斷機制。
2.2 觸發 & 執行
中斷機制被觸發后,會做出一系列動作,先執行中斷程序,再回來繼續執行原程序,注意,這里的說明相對抽象。
- 識別中斷源,觸發對應的中斷信息(這里是
0號中斷
) - 保存現場
- 標志寄存器入棧 pushf
- 修改標志寄存器:
IF = 0
、TF = 0
(不接收可屏蔽中斷,不進行單步中斷) - CS:IP入棧(老大CS先入棧,然后是IP)
- 根據中斷向量表中,相應中斷源的值,修改CS:IP,執行中斷服務程序
- 執行完后,執行
iret
,依次出棧,恢復現場。 - 接著執行下面的指令(可能是出現異常的指令,也可能是下一條指令,與實際情況有關)
2.3 修改0號中斷
0號中斷是存儲在8086CPU內存的中斷向量表中,0x0000 ~ 0x03ff
,共400H,也就是1MB的空間。
寫一段程序,然后將其拷貝到被保護的內存區域(指令和數據都要),然后,將中斷向量表對應的地址修改,這樣,這段程序就成為了中斷服務程序,可以被動調用,也可以主動調用。
3 對中斷的理解
3.1 中斷是什么?
指令執行過程中,有其他事務要優先處理,需要放下當前執行的指令,執行完其他事務再回來執行。
這就好比,你在寫作業,突然你媽媽讓你去買醬油,你就需要先放下作業,買完醬油回來,再寫作業。這里買醬油就是一個中斷。
3.2 中斷來源于哪?
- 程序內部出現異常
- 程序內部主動請求中斷
- 外部設備請求中斷
外部中斷分為可屏蔽(可以不理會!)和不可屏蔽中斷(必須執行!不可忽略!)。
3.3 中斷何時發生?
查看中斷向量表即可。
3.4 中斷執行過程是什么?
- 檢測到中斷
- 保存現場,屏蔽外界中斷,屏蔽單步中斷
- 根據中斷向量表的地址,修改CS:IP
- 執行中斷服務程序
- 恢復現場
- 繼續執行
3.5 中斷服務程序是什么?
普通的一段程序,如果其入口地址被放在了中斷向量表的某個中斷中,這個程序就是【中斷服務程序】。
發生中斷時,系統給出的解決方案,就是中斷服務程序。其入口地址存放在中斷向量表中,程序系統默認有,也可以自己編寫。
3.6 中斷服務程序如何編寫和安裝?
- 編寫一段普通的程序(指令 + 數據)
- 將其拷貝到特殊的內存位置(指令和數據都要一起拷貝)
- 將其入口地址寫入到中斷向量表中
3.7 中斷的功能是什么?
3.7.1 自動調用:(Checked)異常處理
比如除法錯中斷,就是系統自動檢測并處理的。
3.7.2 手動調用:(Unchecked)異常處理
比如溢出中斷,需要手動寫INTO
(Interrupt Overflow)指令,才會進行處理,否則運算溢出的時候不做任何處理。
3.7.3 手動調用:系統調用(System Call)
主動使用中斷,能夠幫助程序員快速實現一些功能,這也就是基于中斷機制的功能調用,極大提高了開發效率。
4 單步中斷 & 斷點中斷
這兩個中斷類型,就是單步調試和斷點調試背后的實現機制,方便程序員調試程序。
4.1 單步中斷
TF標志位為1的時候,發生單步中斷,然后就被置0,防止無限嵌套中斷發生。
單步中斷是為了方便調試程序和查看寄存器等相關內容的值。
4.2 斷點中斷
對于INT n
。n一共是256個,占1個字節,INT指令碼占1個字節,共2個字節,而**斷點中斷(INT 3)**特殊,占1個字節,其編碼是1100_1100B
,這與其實現機制有關。
斷點中斷是通過INT 3
指令主動調用的,執行的時候,該指令會臨時替換斷點處的1個字節,遇到了就發生中斷,顯示寄存器和其他相關內容的值,便于程序員調試。
x86指令系統中,指令最少1個字節,因此INT 3也是1個字節,這樣INT 3的替換,至多影響1條指令。 如果不是1個字節,可能影響2條指令,發生錯誤。
4.3 應用
例如debug的t
命令,還有插入斷點等,都是基于單步中斷和斷點中斷機制實現,它們的出現是為了方便程序調試,并且在debug程序中已經能夠實現中斷觸發,對著這種指令,不要寫在程序中,調試程序直接讓程序運行在調試模式下就好了。