Langages de programmation trop complexes pour le CPU
Les registres sont des emplacements mémoire sur le CPU pouvant contenir une valeur numérique (en général 32 bits ou 64 bits)
Quelques registres courants (32 bits) :
eip : adresse de la prochaine instructionesp, ebpeax, ebx, ecx, edx, esi, edi : registres générauxeflags : bits d'informations sur la dernière opération effectuéeQuelques registres courants (64 bits) :
rip : adresse de la prochaine instructionrsp, rbp : pointeurs de pilerax, rbx, rcx, rdx, rsi, rdi : registres générauxr8, r9, ..., r15 : registres généraux supplémentairesLes instructions assembleur correspondent aux opérations élémentaires du CPU
Quelques instructions courantes :
mov : copie une valeur (ex : mov $14, %esi)add, sub, mul, etc. : opérations arithmétiques (ex : sub $16, %rsp)and, or, xor, etc. : opérations logiques bit à bit (ex : xor %eax, %eax)cmp : comparaison de deux valeurs (ex : cmp $10, -8(%rbp)) → modifie le registre eflagsjmp, jz/jnz, je/jne, etc. : sauts (conditionnels ou non) → modifie le registre rippush, pop : ajout, suppression sur la pilecall, ret : appel de fonction, retour de fonction










rsp (stack pointer) contient l'adresse du haut de pilerbp (base pointer) contient l'adresse du bas du blocChangement de frame :
push %rbp
mov %rsp, %rbp
...
pop %rbp
ebp (base pointer) : début du stack frame courantesp (stack pointer) : haut de la pileint main() {
int x = 12;
int y = x + 14;
return 0;
}
$ gcc -S -o prog.s prog.c
.globl _main ; visible pour linker
_main: ; déclaration de fonction
push %rbp
mov %rsp, %rbp
xor %eax, %eax ; valeur de retour
mov $0, -4(%rbp) ; "
mov $12, -8(%rbp) ; x
mov -8(%rbp), %ecx ; addition
add $14, %ecx ; "
mov %ecx, -12(%rbp) ; y
pop %rbp
ret
int main() {
int a = 12;
if (a > 10) {
return 1;
} else {
return 0;
}
}
.globl _main
_main:
push %rbp
mov %rsp, %rbp
mov $0, -4(%rbp)
mov $12, -8(%rbp) ; a
cmp $10, -8(%rbp) ; test
jle LBB0_2 ; saut si a <= 10
mov $1, -4(%rbp) ; val de retour
jmp LBB0_3
LBB0_2:
mov $0, -4(%rbp) ; val de retour
LBB0_3:
mov -4(%rbp), %eax
pop %rbp
ret
int f(int x, int y) {
return x + y;
}
int main() {
int a = 12;
int b = f(a, 14);
return 0;
}
call _f push %rip
mov _f, %rip
... ...
ret pop %rip
.globl _f
_f:
push %rbp
mov %rsp, %rbp
mov %edi, -4(%rbp) ; x
mov %esi, -8(%rbp) ; y
mov -4(%rbp), %eax ; addition
add -8(%rbp), %eax ; "
pop %rbp
ret
.globl _main
_main:
push %rbp
mov %rsp, %rbp
sub $16, %rsp ; stack frame
mov $0, -4(%rbp)
mov $12, -8(%rbp) ; a
mov -8(%rbp), %edi ; x
mov $14, %esi ; y
call _f ; appel de fonction
xor %ecx, %ecx
mov %eax, -12(%rbp); retour de f
mov %ecx, %eax
add $16, %rsp ; stack frame
pop %rbp
ret
int main() {
int t = 0;
for (int i = 0; i < 10; i++) {
t += i;
}
return t;
}
.globl _main
_main:
push %rbp
mov %rsp, %rbp
mov $0, -4(%rbp)
mov $0, -8(%rbp) ; t
mov $0, -12(%rbp) ; i
LBB0_1:
cmp $10, -12(%rbp) ; test
jge LBB0_4 ; saut si i >= 10
mov -12(%rbp), %eax ; addition
add -8(%rbp), %eax ; "
mov %eax, -8(%rbp) ; -> t
mov -12(%rbp), %eax ; incrémentation
add $1, %eax ; "
mov %eax, -12(%rbp) ; -> i
jmp LBB0_1
LBB0_4:
mov -8(%rbp), %eax ; val retour
pop %rbp
ret