I'm learning ia-32 and everything was going fine on 32bit Ubuntu, but I switched to 64bit and started using the flag -m32 and now i can't use DIV anywhere, no matter the content of the registers, it gives me always Floating Point Exception... And I'm sure I'm not dividing by zero. I'm using gcc and gdb.
This is the closest question to my problem: FPU IA-32 SIGFPE, Arithmetic exception
I tried to put the instructions fldcw with 0x220 but makes no difference.
My source code:
.section .text
Division:
.int 0x220
str:
.asciz "%d"
.global binario # void binario(int)
binario:
pushl %ebp # prologo
movl %esp,%ebp #
finit
fldcw Division
pushl %ebx
pushl %ecx
pushl %edx
movl 8(%ebp),%eax # param x to eax
cmpl $0,%eax # compare x with 0
je fim # return recursive call
movl $2,%ecx # prepare division
divl %ecx # divide eax with 2
movl $0,%ecx # clean ecx
movb %al,%cl # put division result on cl
pushl %ecx # push x/2
call binario # recursive call
add $8,%esp # clean esp
movl $0,%ecx # clean ecx
movb %ah,%cl # put division rest on cl
pushl %ecx # push division rest
pushl $str # push string
call printf # call printf function
addl $8,%esp # clean esp
fim:
pushl %edx
pushl %ecx
pushl %ebx
movl %ebp,%esp # epilogo
popl %ebp #
ret
GDB log:
28 divl %ecx # divide eax with 2
2: $ecx = 2
1: $eax = 33
(gdb)
Program received signal SIGFPE, Arithmetic exception.
binario () at ex08.s:28
28 divl %ecx # divide eax with 2
2: $ecx = 2
1: $eax = 33
+1 for searching SO and using a debugger, -1 for not reading the instruction set reference ;)
The
div r/m32
variant that you are using divides the 64 bit quantity formed fromedx
(top 32 bits) andeax
(low 32 bits). Furthermore, you also get this exception if your result is out of range. The problem is you are not zeroingedx
so it has some random value which causes the whole division to overflow. You need to clearedx
(zero-extendeax
) before unsigned division, and sign-extendeax
intoedx
before signed division.PS: I hope you are not really using
div
to divide by2
. To divide or multiply by powers of2
you should use shifts.