1. 程式人生 > >中斷詳解(四) ——異常與異常處理

中斷詳解(四) ——異常與異常處理

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
把使用者資料段的選擇符拷貝至IJ ds和es暫存器中。
7
呼叫地址在edi中的高階C函式.
被呼叫的函式從eax和edx暫存器而不是從錢中接收引數。我們已經遇見過一個從CPU
暫存器獲取引數的函式__switch_to 僕,在第三章"執行程序切換"一節我們討論過
這個函式.