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 from edx
(top 32 bits) and eax
(low 32 bits). Furthermore, you also get this exception if your result is out of range. The problem is you are not zeroing edx
so it has some random value which causes the whole division to overflow. You need to clear edx
(zero-extend eax
) before unsigned division, and sign-extend eax
into edx
before signed division.
PS: I hope you are not really using div
to divide by 2
. To divide or multiply by powers of 2
you should use shifts.