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
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.
div executes unsigned division. div divides a 16-, 32-, or 64-bit register value (dividend) by a register or memory byte, word, or long (divisor). The quotient is stored in the AL, AX, or EAX register respectively. The remainder is stored in AH, Dx, or EDX.
mov [edx],eax stores the value of eax in memory, to the address given in edx (in little-endian byte order). mov eax,[edx] does exactly the reverse, reads a value stored from the memory, from the address given in edx , and stores it in eax . [reg] always means indirect addressing, it's just like a pointer *reg in C.
Unsigned divide AX by r/m8, with result stored in AL = Quotient, AH = Remainder. Unsigned divide DX:AX by r/m16, with result stored in AX = Quotient, DX = Remainder. Unsigned divide EDX:EAX by r/m32, with result stored in EAX = Quotient, EDX = Remainder.
4.3. Figure 4.1 illustrates the use of the Y register during a multiplication operation. The integer division operations divide a 32-bit value into a 64-bit value and produce a 32-bit result. The Y register provides the most significant 32 bits of the 64-bit dividend.
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
then DIV divisor
CDQ
then IDIV divisor
See also When and why do we sign extend and use cdq with mul/div?
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
.
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 hex4 0000 0002
, which is a value that does not fit in 32 bits.
That is why you get an integer overflow.
If, however, EDX
were only 1
, you would divide hex 1 0000 000A
by 5
, which results in hex3333 3335
. That is not the value you wanted, but it does not cause an integer overflow.
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
.
So, before a single division, you should generally set EDX
to 0
.
(Or for signed division, cdq
to sign extend EAX
into EDX:EAX
before idiv
)
But EDX
does not have always have to be 0
. It can just not be that big that the result causes an overflow.
One example from my BigInteger
code:
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
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, 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.
The DIV instruction divides EDX:EAX by the r/m32 that follows the DIV instruction. So, if you fail to set EDX to zero, the value you are using becomes extremely large.
Trust that helps
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With