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 : Sélectionner tout - Visualiser dans une fenêtre à part
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 : Sélectionner tout - Visualiser dans une fenêtre à part
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 :

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)