Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

X86 assembly - Handling the IDIV instruction

Tags:

I am currently writing a simple C compiler, that takes a .c file as input and generates assembly code (X86, AT&T syntax). Everyting is good, but when I try to execute a IDIVQ instruction, I get a floating-point exception. Here's my input:

int mymain(int x){   int d;   int e;   d = 3;   e = 6 / d;   return e; } 

And here is my generated code:

mymain: .LFB1:     .cfi_startproc     pushq   %rbp     .cfi_def_cfa_offset 16     movq    %rsp, %rbp     .cfi_offset 6, -16     .cfi_def_cfa_register 6     movq    %rdi, -40(%rbp)     movq    $3, -8(%rbp)     movq    $6, %rax     movq    -8(%rbp), %rdx     movq    %rdx, %rbx     idivq   %rbx     movq    %rax, -16(%rbp)     movq    -16(%rbp), %rax     leave     .cfi_def_cfa 7, 8     ret     .cfi_endproc .LFE1:     .size mymain, .-mymain 

According to http://www.cs.virginia.edu/~evans/cs216/guides/x86.html, idivq %rbx should produce 6/d (the quotient) in %rax. But I'm getting a floating-point exception, and I can't seem to find the problem.

Any help will be much appreciated!

like image 370
elyas-bhy Avatar asked Apr 27 '12 00:04

elyas-bhy


People also ask

What does IDIV do in assembly?

idiv executes signed division. idiv divides a 16-, 32-, or 64-bit register value (dividend) by a register or memory byte, word, or long (divisor). The size of the divisor (8-, 16- or 32-bit operand) determines the particular register used as the dividend, quotient, and remainder.

What is the difference between div and IDIV?

The DIV instruction divides unsigned numbers, and IDIV divides signed numbers. Both return a quotient and a remainder.

What is CQTO?

“longword”is 32 bits, a quadword” is 64. d) Do a cqto instruction (with no operands) to sign-extend it to. rdx. cqto stands for “convert quadword to octword.”

Where is the return address on the stack x86?

The return address is just the address directly after the parameters to the call instruction. To see what the return address is in your example above, you'd have to look at the stack as soon as the program gets into the procedure at 0x4012d0.


1 Answers

The first part of Mysticials answer is correct, idiv does a 128/64 bit division, so the value of rdx, which holds the upper 64 bit from the dividend must not contain a random value. But a zero extension is the wrong way to go.

As you have signed variables, you need to sign extend rax to rdx:rax. There is a specific instruction for this, cqto (convert quad to oct) in AT&T and cqo in Intel syntax. AFAIK newer versions of gas accept both names.

movq    %rdx, %rbx cqto                  # sign extend rax to rdx:rax idivq   %rbx 
like image 74
Gunther Piez Avatar answered Sep 21 '22 13:09

Gunther Piez