2011-02-15 57 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。

花了我一天的时间找到了这个......希望这会有所帮助。