On rappelle qu'un programme assembleur s'écrit dans un fichier portant le suffixe .s et a la forme suivante :
.text .globl main main: ... mov $0, %rax # code de sortie ret .data ...Vous pouvez compiler et exécuter ce fichier de manière non interactive avec la commande suivante :
gcc -g fichier.s -o fichier ./fichier(Ajouter l'option -no-pie si vous utilisez une version de gcc supérieure ou égale à 5.)
Si besoin, on pourra utiliser gdb (installé en salles info) pour exécuter pas à pas le code assembleur. Pour cela, faire
gdb ./fichier (gdb) break main (gdb) runpuis exécuter pas à pas avec la commande step. Plus d'information sur gdb dans ce tutoriel.
Cette page d'Andrew Tolmach donne pas mal de pointeurs pour écrire / débugger du code assembleur x86-64 et en particulier ces notes sur l'assembleur x86-64.
#include <stdio.h> int main() { printf("n = %d\n", 42); return 0; }Pour appeler la fonction de bibliothèque printf, on passe son premier argument (la chaîne de format) dans le registre %rdi et son second argument (ici l'entier 42) dans le registre %rsi, comme le veulent les conventions d'appel. On doit aussi mettre le registre %rax à zéro avant d'appeler printf, car il s'agit d'une fonction variadique (i.e. avec un nombre d'arguments variable) et %rax indique le nombre de paramètres passés dans des registres vecteurs (ici aucun).
La chaîne de format doit être déclarée dans le segment de donnée (zone .data) avec la directive .string qui ajoute le caractère de code 0 à la fin de la chaîne.
#include <stdio.h> int isqrt(int n) { int c = 0, s = 1; while (s <= n) { c++; s += 2*c + 1; } return c; } int main() { int n; for (n = 0; n <= 20; n++) printf("sqrt(%2d) = %2d\n", n, isqrt(n)); return 0; }On essayera notamment d'effectuer les optimisations suivantes :
Le programme C matrix.c contient une solution, qu'on lira attentivement. Cette solution utilise les deux ingrédients suivants :
const int m[N][N] = { { 7, 53, ..., 583 }, { 627, 343, ... }, ... };En mémoire, les entiers sont stockés consécutivement, ligne par ligne. Chaque entier occupe 4 octets et la matrice m occupe donc 900 octets au total. L'entier m[i][j] se trouve en mémoire à l'adresse m + 4 * (15*i + j).
On fournit un fichier matrix.s contenant déjà la déclaration statique de la matrice m, ainsi que la place pour le tableau memo. Comme ce dernier est initialisé avec zéro, il est alloué dans la section .bss pour ne pas occuper inutilement de la place dans l'exécutable.
Attention : pour calculer 1 << j, il faut effectuer un décalage d'une valeur non constante. Pour cela, l'opérande de l'instruction sal, c'est-à-dire la valeur de j ici, doit être placée dans le registre octet %cl. Il pourra donc être intéressant d'allouer la variable j dans le registre %rcx.