Division in x86 Assembly GAS
Im not quite sure yet how division works in x86 assembly (GAS AT&T syntax). What i wanna do is to divide two longs, and then multiply the quotient with the divisor to see if the new number is equal to the initial number (n/m * m = n).
movl %ebx, %eax
movl %ecx, %edx
idivl %edx
imull %ebx, %edx
cmp %edx, %ebx
je .equal
The code above is a snippet where i do the division. ebx and ecx are two counters that i want to divide, is it correct that the eax register is used as divisor? so when i write idivl %edx i am dividing edx with eax, and i get the integer closest 0? Like 7/2 = 3? I read one place that the quotient is stored in the edx register and the remainder in the ah register, but i was also told that the quotient is stored in the eax register and the remainder in the edx register, which has gotten me confused.
Though the main question here is: i want to divide the value of the ebx register with the value of the ecx register, how should i proceed?
Thanks!
EDIT: the code above yields an floating point exception
The idiv
instruction takes 2 arguments in 3 registers.
The first implicit argument is the dividend, a 64-bit argument in edx:eax
The low 32 bits are in eax
, the high 32 bits are in edx
.
The second explicit argument is the divisor, a 32 bit argument in a single register.
For obvious reasons the divisor should not be edx
or eax
.
The result is returned in eax = Quotient, edx = Remainder.
Knowing this the proper setup should be:
Intel syntax pdp-11 syntax
--------------------------------------------------------
.intel_syntax noprefix
mov ebx, dividend
mov ecx, divisor
mov eax,ebx movl %ebx, %eax
cdq cdq //edx:eax = 32 bit dividend
idiv ecx idivl %ecx //divide edx:eax by ecx
imul eax, ecx imull %ecx, %eax //multiply result by dividend
cmp ebx, eax cmpl %eax, %ebx
je .equal je .equal
add eax,edx addl %edx, %eax //add remainder
cmp ebx,eax cmpl %eax,%ebx //should be equal now
je .equal2 je .equal2
You should keep in mind that div/idiv
performs an integer divide!
The result is always an integer with a remainder (which may be zero).
It does not do any floating point. It only generates an exception if the result is too large to fit in 32 bits or if you're dividing by zero, in which case you get a #DE Division error.
The reason you are getting an integer division error is that you are mistakenly using edx
as the divisor and because your dividend is 32-bit the higher 32 bits (stored in edx
) are always zero and thus you have a division by zero.
Never use the same registers for dividend and divisor!
You'll get this same error if the edx:eax idiv ecx
does not fit in 32 bits (ie if edx:eax
is too large relative to ecx
).
See: http://www.felixcloutier.com/x86/IDIV.html and http://www.felixcloutier.com/x86/DIV.html
I have a burning hate for ATT aka PDP syntax which is nonsensical and broken.
You can restore sanity and use Intel syntax in Gas by using the .intel_syntax noprefix
pseudo instruction.
See: Can I use Intel syntax of x86 assembly with GCC?
上一篇: 在MASM中向斐波那契数列输出错误
下一篇: x86装配GAS部门