[runtime exception] Floating point exception
Bonjour à tous,
je suis un cours de compiler design dans lequel on doit créer un compilateur de a à z.
Le langage à implémenter est un sous-set de C.
La cible principale du langage est l'architecture x86-64.
Je n'ai malheureusement pas beaucoup de connaissances en assembleur et ça me pose pas mal de problèmes par ailleurs. En voici un pour lequel je ne comprends pas l'erreur :
Le code original est bêtement :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13
| int main()
{
int x1;
x1 = 80;
x1 /= 3; // 26
x1 *= 4; // 104
x1 -= 4; // 100
x1 += -17; // 83
x1 %= 10; // 3
return x1;
} |
que mon compilateur traduit en assembleur :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| .section .text
.type _start, @function
.globl _start
_start:
pushq %rbp
movq %rsp, %rbp
movl $80, %eax
movl $3, %edx
cltd
idivl %edx
imull $4, %eax
subl $4, %eax
addl $-17, %eax
movl $10, %edx
cltd
idivl %edx
movl %edx, %eax
leave
ret
.size _start, .-_start |
Le problème semble venir de la division que j'effectue (deux fois).
L'erreur à l'exécution est :
Citation:
14880 Floating point exception(core dumped) ./a.out 2>&1 >a.result
Execution of binary unexpectedly failed with exception 8.
Que fais-je de faux ?
La valeur retournée devrait être 3 à la fin, mais le programme ne s'exécute pas jusqu'à la fin : il lève cette exception avant.
En passant, j'ai trouvé l'ABI d'AMD64, mais c'est affreux à lire, et ça sous-entend qu'on connaît déjà toutes les informations à propos de l'assembleur x86 32bits... avez-vous des ressources plus intéressantes pour comprendre comment faire telle ou telle opération en assembleur ?
Ajout : à noter que toutes les opérations sont à effectuer sur des entiers signés 32bits, soit de -2^31 à 2^31-1. La multiplication et la division (ainsi que le modulo) sont signés. Les opérations sont toutes des opérations entières.
Les under-overflows par additions/soustraction/multiplication ne doivent pas lever d'exception (à la place, on utilise la modulo 2^32.
e.g. -(2^31)=>-(-2^31)=>2^31=>-2^31
e.g. -2^31-1=>2^31-1
Les seules exceptions qui doivent être levées sont lors des divisions / modulos :
1. si on divise par zero
2. si le signe de la division cause un overflow (-2^31 / -1, ou -2^31%-1)