中斷詳解(四) ——異常與異常處理
阿新 • • 發佈:2019-01-10
ENTRY(divide_error)
RING0_INT_FRAME
pushl $0 # no error code
CFI_ADJUST_CFA_OFFSET 4
pushl $do_divide_error
CFI_ADJUST_CFA_OFFSET 4
jmp error_code
CFI_ENDPROC
END(divide_error)
當異常發生時,如果控制單元沒有自動地把一個硬體出錯程式碼插入到戰中,相應的組合語言片段會包含一條pushl $0指令,在戰中墊上一個空值.然後,把高階C函式的地址壓進枝中,它的名字由異常處理程式名與do一前強組成.
標號為error_code的組合語言片段對所有的異常處理程式都是相同的,除了"Oevicenot avaiJabJe" 這一個異常。這段程式碼執行以下步驟:1)把高階C函式可能用到的暫存器儲存在戰中.
2)產生一條cld指令來清eflags的方向標誌DF, 以確保呼叫字串指令時會自動增加edi 和esi暫存器的值。
3)把校中位於espi36處的硬體出錯碼拷貝到edx中,給戰中這一位置存上值-1 ,正如我們將在第十一章的"系統 呼叫的重新執行"一節中所看到的那樣,這個值用來把Ox80異常與其他異常隔離開.
4)把儲存在戰中esp+32位置的do_handler_name() 高階C函式的地址裝入edi暫存器中.然後,在栓的這個位置與入es的值。
5)把核心戰的當前錨頂拷貝到eax暫存器.這個地址表示記憶體單元的地址,在這個單元中存放的是第1 步所儲存的最後一個客存器的值。
6
7)呼叫地址在edi中的高階C函式.
被呼叫的函式從eax和edx暫存器而不是從錢中接收引數。我們已經遇見過一個從CPU
暫存器獲取引數的函式__switch_to 僕,在第三章"執行程序切換"一節我們討論過
這個函式.