我不知道分区中溢出的确切定义是什么。您可以先解释一下,然后再通过以下示例进行说明吗?
例如,我的书中写道,这段代码导致溢出。我不知道为什么?
mov dx,0087h
mov ax,6002h
mov bx,10h
div bx
但是这段代码是正确的,不会导致溢出:
mov dx,0087h
mov ax,6000h
mov bx,100h
div bx
那么为什么第一个结果溢出但第二个没有什么区别呢?
答案 0 :(得分:3)
寄存器DX
和AX
中的红利实际上是一个32位数字,在您的示例中是00876002h
。
它将除以除数BX
,结果(商)应适合寄存器AX
。无符号除法后的余数将被放入寄存器DX
。
当您尝试将00876002h
除以BX
(10h
)的内容时,结果为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。