为什么在使用DIV指令之前EDX要为0? [英] Why should EDX be 0 before using the DIV instruction?

查看:14
本文介绍了为什么在使用DIV指令之前EDX要为0?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我注意到当 EDX 包含一些随机默认值时,如 00401000,然后我使用了这样的 DIV 指令:

I noticed when EDX contains some random default value like 00401000, and I then use a DIV instruction like this:

mov eax,10
mov ebx,5
div ebx

它会导致整数溢出错误.但是,如果我将 edx 设置为 0 并执行相同的操作,则它会起作用.我相信使用 div 会导致商覆盖 eax 而余数覆盖 edx.

it causes an INTEGER OVERFLOW ERROR. However, if I set edx to 0 and do the same thing it works. I believed that using div would result in the quotient overwriting eax and the remainder overwriting edx.

得到这个整数溢出错误真的让我很困惑.

Getting this INTEGER OVERFLOW ERROR really confuses me.

推荐答案

做什么

对于 32 位/32 位 => 32 位除法:将 32 位除数从 EAX 零或符号扩展为 64 位 EDX:EAX.
对于 16 位,使用 cwd 或 xor-zeroing 将 AX 转换为 DX:AX.

What to do

For 32-bit / 32-bit => 32-bit division: zero- or sign-extend the 32-bit dividend from EAX into 64-bit EDX:EAX.
For 16-bit, AX into DX:AX with cwd or xor-zeroing.

  • 无符号:XOR EDX,EDX 然后 DIV 除数
  • 签名:CDQ然后IDIV除数
  • unsigned: XOR EDX,EDX then DIV divisor
  • signed: CDQ then IDIV divisor

另见当为什么我们签署扩展并使用带有 mul/div 的 cdq?

对于DIV,寄存器EDXEAX 形成一个单一的 64 位值(通常显示为 EDX:EAX),然后被划分,在这种情况下,由 EBX.

For DIV, the registers EDX and EAX form one single 64 bit value (often shown as EDX:EAX), which is then divided, in this case, by EBX.

所以如果 EAX = 10 或十六进制 AEDX 是,说 20 或十六进制 14,然后它们一起形成 64 位值十六进制 14 0000 000A 或十进制 85899345930.如果除以5,结果是17179869186或hex
4 0000 0002这是一个不适合32位的值.

So if EAX = 10 or hex A and EDX is, say 20 or hex 14, then together they form the 64 bit value hex 14 0000 000A or decimal 85899345930. If this is divided by 5, the result is 17179869186 or hex
4 0000 0002, which is a value that does not fit in 32 bits.

这就是整数溢出的原因.

然而,如果 EDX 只是 1,你可以将十六进制 1 0000 000A 除以 5,结果是十六进制
3333 3335.这不是您想要的值,但它不会导致整数溢出.

If, however, EDX were only 1, you would divide hex 1 0000 000A by 5, which results in hex
3333 3335. That is not the value you wanted, but it does not cause an integer overflow.

要真正将 32 位寄存器 EAX 除以另一个 32 位寄存器,请注意 EDX:EAX 形成的 64 位值的顶部是 0.

To really divide 32 bit register EAX by another 32 bit register, take care that the top of the 64 bit value formed by EDX:EAX is 0.

因此,单个划分之前,您应该一般EDX设置为0.

So, before a single division, you should generally set EDX to 0.

(或者对于有符号的除法,cdqEAX 符号扩展到idiv 之前的EDX:EAX)

(Or for signed division, cdq to sign extend EAX into EDX:EAX before idiv)

但是EDX 不一定总是0.结果导致溢出的情况不可能那么大.

But EDX does not have always have to be 0. It can just not be that big that the result causes an overflow.

我的 BigInteger 代码中的一个示例:

One example from my BigInteger code:

DIV相除后,商在EAX中,余数在EDX中.将诸如 BigInteger 之类的内容除以 10(例如将值转换为十进制字符串)),您可以执行以下操作:

After a division with DIV, the quotient is in EAX and the remainder is in EDX. To divide something like a BigInteger, which consists of an array of many DWORDS, by 10 (for instance to convert the value to a decimal string), you do something like the following:

    ; 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包含该部门的剩余部分.

After that loop, the value represented by the entire array (i.e. by the BigInteger) is divided by 10, and EDX contains the remainder of that division.

FWIW,在我使用的汇编器(Delphi 的内置汇编器)中,以 @ 开头的标签是函数的局部标签,即它们不会干扰其他函数中的同名标签功能.

FWIW, in the assembler I use (Delphi's built-in assembler), labels starting with @ are local to the function, i.e. they don't interfere with equally named labels in other functions.

这篇关于为什么在使用DIV指令之前EDX要为0?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆