装配中的划分溢出(8086)

时间:2018-12-24 15:09:46

标签: assembly x86-16

我不知道分区中溢出的确切定义是什么。您可以先解释一下,然后再通过以下示例进行说明吗?

例如,我的书中写道,这段代码导致溢出。我不知道为什么?

mov dx,0087h
mov ax,6002h
mov bx,10h
div bx

但是这段代码是正确的,不会导致溢出:

mov dx,0087h
mov ax,6000h
mov bx,100h
div bx

那么为什么第一个结果溢出但第二个没有什么区别呢?

2 个答案:

答案 0 :(得分:3)

寄存器DXAX中的红利实际上是一个32位数字,在您的示例中是00876002h
它将除以除数BX,结果(商)应适合寄存器AX。无符号除法后的余数将被放入寄存器DX

当您尝试将00876002h除以BX10h)的内容时,结果为87600h,余数为2。现在您应该了解触发它的原因错误:商87600h太大,无法放入16位寄存器AX中。

除数过小(除数)会发生除法溢出(别名除以零)。当BX低于DX时,示例将溢出。

答案 1 :(得分:1)

float,因此0x00876002 / 0x10 = 0x87600的商不适合AX,因此会出现#DE异常。英特尔的指令参考手册(x86 SDM第2卷)具有每条指令的详细说明,DX:AX / BX的条目对此进行了说明。 div entry here的HTML摘录。有关英特尔文档和其他内容的链接,请参见the x86 tag wiki

除以10h就是向右移1个十六进制数字,但是输入的高半部分DX有2个有效的十六进制数字。

x86 Assembly: Division Floating Point Exception dividing by 11基本上是该命令的重复,@ rcgldr的答案使用扩展精度除法代码(例如32位/ 16位产生32位商和16位余数),使用{{ 1}}适用于任意16位除数。


在您的特定情况下,您需要除以2的幂。对于div,这非常效率低。

对于这些2次幂的除法,您应该使用

div

如果需要余数,则为原始AX的低4位,应使用div / ; input in DX:AX shrd ax, dx, 4 ; right shift AX, shifting in bits from DX shr dx, 4 ; separately right shift DX ; DX:AX = 0008:7600 = 0x87600 = 32-bit quotient 获得。

SHRD仅修改其目的地,而不修改源,因此您需要DX上的第二个mov cl, al。这对于较大的扩展精度移位是有意义的:您想使用一串SHRD指令将位依次移入每个元素的顶部,而不想移零。

或者,如果您不能使用shrd之类的386条指令,则可以通过左右移位和OR来模拟SHRD。原始的8086也没有立即计数移位,因此您需要在CL中计数。

and cl, 0Fh

或者,如果您知道结果不会溢出,例如分频shr(右移8),则可以只使用一个SHRD。