標籤:style http color 使用 strong io 問題 代碼
第4章斷點和逐步執行
斷點和逐步執行是兩個經常使用的調試功能,也是調試器的核心功能。本章我們將介紹IA-32 CPU是如何支援斷點和逐步執行功能的。前兩節將分別介紹軟體斷點和硬體斷點,第4.3節介紹用於實現逐步執行功能的陷阱標誌。在前三節的基礎上,第 4.4節將分析一個真實的調試器程式,看它是如何?斷點和逐步執行功能的。
4.1 軟體斷點
x86系列處理器從其第一代產品英特爾8086開始就提供了一條專門用來支援調試的指令,即INT 3。簡單地說,這條指令的目的就是使CPU中斷(break)到調試器,以供調試者對執行現場進行各種分析。當我們偵錯工具時,可以在可能有問題的地方插 入一條INT 3指令,使CPU執行到這一點時停下來。這便是軟體調試中經常用到的斷點(breakpoint)功能,因此INT 3指令又被稱為斷點指令。
4.1.1 感受INT 3
下面通過一個小實驗來感受一下INT 3指令的工作原理。在Visual C++ Studio 6.0(以下簡稱為VC6)中建立一個簡單的HelloWorld控制台程式HiInt3,然後在main()函數的開頭通過嵌入式彙編插入一條INT 3指令:
int main(INT argc, char* argv[]) { // manual breakpoint _asm INT 3; printf("Hello INT 3!\n"); return 0; } |
當在VC環境中執行以上程式時,會得到圖4-1所示的對話方塊。點OK按鈕後,程式便會停在INT 3指令所在的位置。由此看來,我們剛剛插入的一行(_asm INT 3)相當於在那裡設定了一個斷點。實際上,這也正是通過注入代碼手工設定斷點的方法,這種方法在調試某些特殊的程式時還非常有用。
|
圖4-1 CPU遇到INT 3指令時會把執行權移交給調試器 |
此時開啟反組譯碼視窗,可以看到記憶體位址00401028處確實是INT 3指令:
10: _asm INT 3; 00401028 int 3 |
開啟寄存器視窗,可以看到程式指標寄存器的值也是00401028。
EAX = CCCCCCCC EBX = 7FFDE000 ECX = 00000000 EDX = 00371588 ESI = 00000000 EDI = 0012FF80 EIP = 00401028 ESP = 0012FF34 EBP = 0012FF80 …… |
根據我們在第3章中的介紹,斷點異常(INT 3)屬於陷阱類異常,當CPU產生異常時,其程式指標是指嚮導致異常的下一條指令的。但是,現在我們觀察到的結果卻是指嚮導致異常的這條指令的。這是為什 麼呢?簡單地說,是作業系統為了支援調試對程式指標做了調整。我們將在後面揭曉答案。