2011-02-15 68 views
10

我對EXCEPTION_INT_OVERFLOW和EXCEPTION_INT_DIVIDE_BY_ZERO異常有疑問。Win32 EXCEPTION_INT_OVERFLOW vs EXCEPTION_INT_DIVIDE_BY_ZERO

Windows將捕獲IDIV指令產生的#DE錯誤,並最終以這兩個代碼之一產生SEH異常。

我的問題是如何區分這兩個條件?英特爾手冊中有關idiv的信息表明它將在「除以零」和「下溢情況」中生成#DE。

我簡要介紹了intel手冊第3卷中#DE錯誤的部分,我可以收集的最好的東西是操作系統必須解碼DIV指令,加載除數參數,然後比較它歸零。

雖然這對我來說似乎有點瘋狂。爲什麼芯片設計者不會使用某種標誌來區分錯誤的兩個原因?我覺得我一定會錯過一些東西。

有誰知道操作系統如何區分2種不同的失敗原因?

+1

你有沒有任何文檔指出`IDIV`甚至可以產生`EXCEPTION_INT_OVERFLOW`?我明白'INT_MIN/-1'是有問題的,但'EXCEPTION_INT_OVERFLOW`的描述似乎沒有包含這種情況。 – 2011-02-15 02:59:15

+0

@Ben我通過實驗驗證了它。當我做INT_MIN/-1時,IDIV指令產生EXCEPTION_INT_OVERFLOW,當我做INT_MIN/0時,我得到EXCEPTION_INT_DIVIDE_BY_ZERO。在這兩種情況下,在試圖執行IDIV指令後拋出異常。 – 2011-02-15 03:09:50

回答

6

您的假設似乎是正確的。 #DE上唯一可用的信息是CS和EIP,它提供了說明。由於兩個狀態碼不同,操作系統必須對指令進行解碼才能確定哪一個。

我還建議芯片製造商在這種情況下不需要兩個單獨的中斷,因爲除以零的任何東西都是無窮大,這太大而無法放入目標寄存器。至於「知道肯定」它的區別是什麼,所有那些知道的人可能不被允許透露它,要麼阻止人們利用它(不完全確定如何,但跳入內核模式是一個好地方開始尋找利用),或基於可能在沒有通知的情況下改變的實現細節做出假設。


編輯:已經打了KD我至少可以說,在Windows XP(32位)的特定版本我公司已獲得(和處理器這是上運行)的nt!Ki386CheckDivideByZeroTrap中斷處理程序似乎解碼指令的ModRM值以確定是返回STATUS_INTEGER_DIVIDE_BY_ZERO還是STATUS_INTEGER_OVERFLOW

(顯然這是原創性研究,不被任何地方的任何保證,也恰好匹配可以基於Intel的手冊進行扣除。)

1

Zooba的回答總結Windows的將指令解析,找出提出什麼。

但是你不能依賴例程正確選擇代碼。

我觀察到以下64位Windows 7與64位指令DIV:

  • 如果操作數(除數)爲存儲器操作數它總是引發EXCEPTION_INT_DIVIDE_BY_ZERO,不管參數值的。
  • 如果操作數是一個寄存器,並且較低的dword爲零,則不管上半部分是否爲零,都會引發EXCEPTION_INT_DIVIDE_BY_ZERO。

花了我一天的時間找到了這個......希望這會有所幫助。