我注意到EDX包含一些随机的默认值,比如00401000,然后我使用这样的DIV指令:
mov eax,10
mov ebx,5
div ebx
它会导致整数溢出错误。但是,如果我将edx
设置为0,并执行相同的操作,则可以正常工作。我相信使用div
会导致商覆盖eax
,其余的覆盖edx
。
得到这个整数溢出错误真的让我很困惑。
发布于 2016-07-17 00:36:27
做什么?
对于32位/32位=> 32位除法:零或符号-将32位被除数从EAX扩展到64位EDX:EAX。
对于16位,使用cwd
或xor零位将AX转换为DX:AX。
XOR EDX,EDX
、、CDQ
和unsigned另请参阅When and why do we sign extend and use cdq with mul/div?
为什么(TL;DR)
对于DIV
,寄存器EDX
和EAX
形成一个64位值(通常显示为EDX:EAX
),然后除以EBX
。
因此,如果EAX
= 10
或十六进制A
,而EDX
是,比如说20
或十六进制14
,那么它们一起构成了64位值十六进制14 0000 000A
或十进制85899345930
。如果除以5
,则结果为17179869186
或十六进制
4 0000 0002
,是一个不适合32位的值。
这就是为什么你会得到一个整数溢出。
但是,如果EDX
仅为1
,则可以将十六进制1 0000 000A
除以5
,结果是十六进制
3333 3335
。这不是您想要的值,但它不会导致整数溢出。
要真正将32位寄存器EAX
除以另一个32位寄存器,请注意由EDX:EAX
形成的64位值的顶部是0
。
因此,在对单个分区进行之前,通常应该将EDX
设置为0
。
(或者对于签署的部门,cdq
在idiv
之前签署extend EAX
into EDX:EAX
)
但是EDX
不一定要总是0
。它可能不会那么大,结果会导致溢出。
我的BigInteger
代码中的一个示例:
与DIV
相除后,商为EAX
,余数为EDX
。要将BigInteger
之类的东西(由许多DWORDS
组成的数组)除以10
(例如,将值转换为十进制字符串),可以执行类似以下操作:
; ECX contains number of "limbs" (DWORDs) to divide by 10
XOR EDX,EDX ; before start of loop, set EDX to 0
MOV EBX,10
LEA ESI,[EDI + 4*ECX - 4] ; now points to top element of array
@DivLoop:
MOV EAX,[ESI]
DIV EBX ; divide EDX:EAX by EBX. After that,
; quotient in EAX, remainder in EDX
MOV [ESI],EAX
SUB ESI,4 ; remainder in EDX is re-used as top DWORD...
DEC ECX ; ... for the next iteration, and is NOT set to 0.
JNE @DivLoop
在该循环之后,整个数组(即BigInteger
)表示的值除以10
,EDX
包含除法的剩余部分。
另外,在我使用的汇编程序(Delphi的内置汇编程序)中,以@
开头的标签对于函数来说是本地的,即它们不会干扰其他函数中同名的标签。
发布于 2016-07-16 23:39:55
DIV指令将EDX:EAX除以DIV指令后面的r/m32。因此,如果您未能将EDX设置为零,则您正在使用的值将变得非常大。
信任是有帮助的
https://stackoverflow.com/questions/38416593
复制相似问题