Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Division in x86 Assembly GAS

Tags:

x86

assembly

att

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

like image 616
mmoe Avatar asked Sep 23 '16 10:09

mmoe


People also ask

What does Div do in assembly?

Unsigned Divide (div) 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.

WHAT IS EBX in x86?

EBX,BX,BH,BL : Called the Base register It is used as a base pointer for memory access Gets some interrupt return values ECX,CX,CH,CL : Called the Counter register It is used as a loop counter and for shifts Gets some interrupt values EDX,DX,DH,DL : Called the Data register It is used for I/O port access, arithmetic, ...

What is BH in assembly?

( bh is the upper 8 bits of bx , which is itself the lower 16 bits of ebx . So the value you need is the original value shifted left by 8, which we get by adding two hex 0 digits). why people always use xor instead of mov XXX,0 ? To put it simply: because it's shorter and faster.


1 Answers

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 (i.e. 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?

like image 71
Johan Avatar answered Sep 22 '22 21:09

Johan