Sept euros jusqu’à vingt-cinq ans
L’assembleur x86-64 est le langage des instructions que comprennent la plupart des ordinateurs et des serveurs actuels, ceux à processeur Intel ou AMD. En lire quelques lignes suffit pour voir où un programme prend une décision.
Une piscine municipale fait payer 7 euros jusqu’à 25 ans et 12 euros ensuite. Cette règle tient en six lignes de C, et en peu de lignes d’assembleur. Rappel : seuls les programmes de votre labo se lisent ici.
À la fin de cette leçon
Remarque
Je peux lire quelques lignes d’assembleur x86-64 et dire ce qu’elles font.
Mots-clés
| Mot | Ce que ça veut dire | Exemple |
|---|---|---|
| Registre | une toute petite mémoire à l’intérieur du processeur | eax |
| Instruction | un ordre simple donné au processeur | mov |
| Comparaison | un test de deux valeurs dont le résultat est retenu | cmp |
| Saut conditionnel | une instruction qui change la suite selon la dernière comparaison | jne |
| Syntaxe Intel | une écriture où la destination vient en premier | mov eax, 5 |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Des instructions et des registres
Un processeur n’a presque pas de mémoire à lui. Il utilise quelques registres, de petites cases nommées. eax sert souvent à garder une valeur de retour.
Chaque instruction est un nom et des opérandes. En syntaxe Intel, la destination vient en premier : mov eax, 5 range 5 dans eax. add ajoute, sub retire. cmp compare deux valeurs et n’en change aucune. Elle ne laisse qu’un résultat que l’instruction suivante lit.
Un saut conditionnel lit le résultat de cmp
Un programme décide avec deux instructions : d’abord cmp, ensuite un saut conditionnel. je saute si les valeurs étaient égales, jne si elles étaient différentes, jg si la première était plus grande.
Si la condition est fausse, le processeur passe à la ligne suivante. Presque chaque « si » d’un programme devient ce couple.
Écrire le programme tarif.c
printf '%s\n' '#include <stdio.h>' '#include <stdlib.h>' 'int prix(int age) {' ' int p = 12;' ' if (age < 26) p = 7;' ' return p;' '}' 'int main(int argc, char **argv) {' ' if (argc != 2) return 2;' ' printf("%d euros\n", prix(atoi(argv[1])));' ' return 0;' '}' > tarif.cAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Le compiler avec les réglages du labo
gcc -O0 -no-pie -fno-stack-protector -o tarif tarif.cAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Le tarif pour 20 ans
./tarif 20Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Le tarif pour 30 ans
./tarif 30Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
objdump montre la fonction prix en assembleur
Le Run suivant désassemble la fonction prix en syntaxe Intel et garde trois lignes : la comparaison cmp, le saut jg et le retour ret. Les nombres sont en hexadécimal, le préfixe 0x les marque : 0x19 vaut 25 et 0xc vaut 12.
Notez que gcc n’a pas écrit « moins de 26 » : il a écrit « plus de 25, on saute ». C’est le même test dit à l’envers.
Garder la comparaison, le saut et le retour
objdump -d -M intel tarif --disassemble=prix | grep -E 'cmp|jg|ret'Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Exemple travaillé : la fonction prix, ligne à ligne
| Instruction | Ce qu’elle fait |
|---|---|
| endbr64, push rbp, mov rbp, rsp | Met la fonction en place : à ignorer pour l’instant |
| mov DWORD PTR [rbp-0x14], edi | Range l’argument age, arrivé dans edi, en mémoire |
| mov DWORD PTR [rbp-0x4], 0xc | p = 12, la variable p est en mémoire |
| cmp DWORD PTR [rbp-0x14], 0x19 | Compare age et 25 |
| jg (vers la ligne du retour) | Si age est plus grand que 25, saute le tarif réduit |
| mov DWORD PTR [rbp-0x4], 0x7 | p = 7, seulement si le saut n’a pas eu lieu |
| mov eax, DWORD PTR [rbp-0x4] | Met p dans eax, la valeur rendue |
| pop rbp, ret | Quitte la fonction |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Erreur fréquente
Attention
Beaucoup de gens lisent mov eax, 5 comme « copier eax dans 5 ». C’est faux : la valeur va vers le premier opérande. Gardez ce réflexe tant que vous lisez la syntaxe Intel. D’autres outils écrivent l’inverse, avec des signes % et $. Vérifiez toujours quelle syntaxe un outil affiche.
Pour aller plus loin
Dans tarif.c, remplacez 26 par 18, recompilez, puis relancez la ligne objdump avec grep. Quel nombre hexadécimal voyez-vous après cmp ?
Calculez-le à la main : l’âge limite devient 17 dans le test « plus grand que ». Convertissez 17 en hexadécimal, puis vérifiez votre résultat.