Questions à choix multiples¶
Cette semaine, la matière porte sur l’organisation de la mémoire et sur le langage assembleur IA32. La matière couverte se trouve dans les sections suivantes du syllabus :
Question 1. Instruction mov
¶
Les instructions de la famille mov
permettent de déplacer des données entre registres ou d’initialiser des registres. Considérons le fragment de code C suivant (dans lequel g
, g2
et s
sont des variables globales de type int
) :
g=1234;
g2=5678;
s=g;
g=g2;
g2=s;
movl $1234, g
movl $5678, g2
movl g, %ecx
movl %ecx, s
movl g2, %ecx
movl %ecx, g
movl s, %ecx
movl %ecx, g2
movl $1234, g
movl $5678, g2
movl g, %eax
movl %eax, s
movl g2, %eax
movl %eax, g
movl s, %eax
movl %eax, g2
movl g, $1234
movl g2, $5678
movl %eax, g
movl s, %eax
movl %eax, g2
movl g, %eax
movl s, %eax
movl g2, %eax
movl $1234, g
movl $5678, g2
movl g2, %eax
movl %edx, s
movl g, %eax
movl %edx, g2
movl s, %eax
movl %eax, g2
movw $1234, g
movw $5678, g2
movb g2, %eax
movb %eax, s
movb g, %eax
movb %eax, g2
movb s, %eax
movb %eax, g2
movw $1234, g
movw $5678, g2
movb g2, %edx
movb %edx, s
movb g, %edx
movb %edx, g2
movb s, %edx
movb %edx, g2
Question 2. Opérations arithmétiques¶
Considérons le fragment de programme C ci-dessous :
a=a+b; b=b+b; c=b-a;
movl a, %eax
addl b, %eax
movl %eax, a
movl b, %eax
addl b, %eax
movl %eax, b
movl b, %eax
subl a, %eax
movl %eax, c
movl b, %eax
addl a, %eax
movl %eax, a
movl b, %eax
addl b, %eax
movl %eax, b
movl b, %eax
subl a, %eax
movl %eax, c
movl b, %eax
addl a, %eax
movl %eax, a
movl b, %eax
movl %eax, %ecx
addl $1, %ecx
movl %ecx, b
movl %eax, b
movl a, %eax
subl b, %eax
movl %eax, c
movl b, %eax
addl a, %eax
movl %eax, c
movl b, %eax
movl %eax, %ecx
addl $1, %ecx
movl %ecx, b
movl %eax, b
movl a, %eax
subl b, %eax
movl %eax, a
movl b, %eax
addl a, %eax
movl %eax, b
movl b, %eax
movl %eax, %ecx
addl $1, %ecx
movl %ecx, b
movl %eax, a
movl b, %eax
subl a, %eax
movl %eax, c
Question 3. Instructions conditionnelles¶
Les instructions conditionnelles sont fréquemment utilisées en langage C et en assembleur. Considérons le fragment de programme C ci-dessous (a
et b
sont des variables globales de type int
):
if(b<4) a++;
begin:
cmpl $4, b
jge end
movl a, %eax
addl $1, %eax
movl %eax, a
end:
begin:
cmpl $4, b
jl next
jmp end
next:
movl a, %eax
addl $1, %eax
movl %eax, a
end:
begin:
cmpl $4, b
jg end
movl a, %eax
addl $1, %eax
movl %eax, a
end:
begin:
cmpl $4, b
je end
movl a, %eax
addl $1, %eax
movl %eax, a
end:
begin:
cmpl $4, b
jl end
movl a, %eax
addl $1, %eax
movl %eax, a
end:
begin:
cmpl $4, b
jl end
movl a, %eax
addl $1, %eax
movl %eax, a
end:
Question 4. Instructions conditionnelles¶
Les instructions conditionnelles sont fréquemment utilisées en langage C et en assembleur. Considérons le fragment de programme C ci-dessous :
if(a<=b) c++;
if:
movl a, %eax
cmpl b, %eax
jg next
movl c, %eax
addl $1, %eax
movl %eax, c
next:
if:
movl b, %eax
cmpl a, %eax
jl next
movl c, %eax
addl $1, %eax
movl %eax, c
next:
if:
movl a, %eax
cmpl b, %eax
jne next
movl c, %eax
addl $1, %eax
movl %eax, c
next:
if:
movl a, %eax
cmpl b, %eax
jle next
movl c, %eax
addl $1, %eax
movl %eax, c
next:
if:
movl a, %eax
cmpl b, %eax
jge next
movl c, %eax
addl $1, %eax
movl %eax, c
next:
.. comment::
Ceci est l'implémentation de :
.. code-block:: c
if(a<b)
c++;
if:
movl a, %eax
cmpl b, %eax
je next
movl c, %eax
addl $1, %eax
movl %eax, c
next:
Question 5. Instructions conditionnelles¶
L’instruction conditionnelle if() ... else
se retrouve dans de nombreux programmes en langage C. Considérons l’instruction if() ... else
simple ci-dessous dans laquelle a
et b
sont des variables globales de type int
:
if(a>=b)
a++;
else
b++;
movl a, %eax
cmpl b, %eax
jl label
movl a, %eax
addl $1, %eax
movl %eax, a
jmp end
label:
movl b, %eax
addl $1, %eax
movl %eax, b
end:
movl b, %eax
cmpl a, %eax
jg label
movl a, %eax
addl $1, %eax
movl %eax, a
jmp end
label:
movl b, %eax
addl $1, %eax
movl %eax, b
end:
movl a, %eax
cmpl b, %eax
jl label
movl b, %eax
addl $1, %eax
movl %eax, b
jmp end
label:
movl a, %eax
addl $1, %eax
movl %eax, a
end:
movl b, %eax
cmpl a, %eax
jge label
movl a, %eax
addl $1, %eax
movl %eax, a
jmp end
label:
movl b, %eax
addl $1, %eax
movl %eax, b
end:
movl b, %eax
cmpl a, %eax
jle label
movl b, %eax
addl $1, %eax
movl %eax, b
jmp .LBB4_3
label:
movl a, %eax
addl $1, %eax
movl %eax, a
end:
movl a, %eax
cmpl b, %eax
jl label
movl a, %eax
addl $1, %eax
movl %eax, a
label:
movl b, %eax
addl $1, %eax
movl %eax, b
end:
Question 6. Boucles while
¶
Les boucles while
sont fréquemment utilisées dans des programmes C. Considérons la boucle suivante qui utilise des variables globales (toutes de type int
):
while(a!=c) { a++; b=b+c; }
while
. Laquelle ?begin:
movl a, %eax
cmpl c, %eax
je end
movl a, %eax
addl $1, %eax
movl %eax, a
movl b, %eax
addl c, %eax
movl %eax, b
jmp begin
end:
begin:
movl c, %eax
cmpl a, %eax
je end
movl a, %eax
addl $1, %eax
movl %eax, a
movl b, %eax
addl c, %eax
movl %eax, b
jmp begin
end:
begin:
movl c, %eax
cmpl a, %eax
jle end
movl a, %eax
addl $1, %eax
movl %eax, a
movl b, %eax
addl c, %eax
movl %eax, b
jmp begin
end:
begin:
movl a, %eax
addl $1, %eax
movl %eax, a
movl b, %eax
addl c, %eax
movl %eax, b
movl c, %eax
cmpl a, %eax
jne begin
end:
begin:
movl c, %eax
cmpl a, %eax
jne end
movl a, %eax
addl $1, %eax
movl %eax, a
movl b, %eax
addl c, %eax
movl %eax, b
jmp begin
end:
Question 7. Boucles for
¶
Rares sont les programmes C qui ne contiennent pas de boucles for
. Considérons la boucle ci-dessous qui utilise uniquement des variables globales (de type int
) :
for(a=0;a<c;a++) {
b=b-c;
}
for
ci-dessus. Laquelle ?begin:
movl $0, a
loop:
movl a, %eax
cmpl c, %eax
jge end
movl b, %eax
subl c, %eax
movl %eax, b
movl a, %eax
addl $1, %eax
movl %eax, a
jmp loop
end:
begin:
movl $0, a
loop:
movl c, %eax
cmpl a, %eax
jle end
movl b, %eax
subl c, %eax
movl %eax, b
movl a, %eax
addl $1, %eax
movl %eax, a
jmp loop
end:
begin:
movl a, %eax
addl $1, %eax
movl %eax, a
loop:
movl c, %eax
cmpl a, %eax
jle end
movl b, %eax
subl c, %eax
movl %eax, b
movl $0, a
jmp loop
end:
begin:
movl $0, a
loop:
movl a, %eax
cmpl c, %eax
jg end
movl b, %eax
subl c, %eax
movl %eax, b
movl a, %eax
addl $1, %eax
movl %eax, a
jmp loop
end:
begin:
movl $0, a
movl a, %eax
cmpl c, %eax
jge end
movl b, %eax
subl c, %eax
movl %eax, b
movl a, %eax
addl $1, %eax
movl %eax, a
end:
begin:
loop:
movl a, %eax
cmpl c, %eax
jge end
movl $0, a
movl b, %eax
subl c, %eax
movl %eax, b
movl a, %eax
addl $1, %eax
movl %eax, a
jmp loop
Question 8. Fonctions¶
Un programme C contient en général de nombreuses fonctions. Considérons une fonction simple qui effectue un calcul en utilisant un argument et une variable globale (a
) :
int f(int i)
{
return i+a;
}
pushl %eax
movl 8(%esp), %eax
movl %eax, (%esp)
movl (%esp), %eax
addl a, %eax
popl %edx
ret
subl $8, %esp
movl 12(%esp), %eax
movl %eax, 4(%esp)
movl a, %eax
movl %eax, (%esp)
movl (%esp), %eax
addl 4(%esp), %eax
addl $8, %esp
ret
subl $8, %esp
movl 12(%esp), %eax
movl %eax, 4(%esp)
movl 4(%esp), %eax
addl a, %eax
movl %eax, (%esp)
addl $8, %esp
ret
pushl %eax
movl (%esp), %eax
addl a, %eax
popl %edx
ret
pushl %eax
movb 8(%esp), %al
movb %al, 3(%esp)
movsbl 3(%esp), %ecx
addl a, %ecx
movl %ecx, %eax
popl %edx
ret
pushl %eax
movb 8(%esp), %al
movb %al, 3(%esp)
movsbl 3(%esp), %ecx
addl a, %ecx
movb %cl, %al
movsbl %al, %eax
popl %edx
ret
Question 9. Fonction max
¶
Considérons la fonction C qui calcule le maximum entre deux entiers :
int max(int i, int j) {
if (i>j)
return i;
else
return j;
}
max:
subl $12, %esp
movl 20(%esp), %eax
movl 16(%esp), %ecx
movl %ecx, 4(%esp)
movl %eax, (%esp)
movl 4(%esp), %eax
cmpl (%esp), %eax
jle next
movl 4(%esp), %eax
movl %eax, 8(%esp)
jmp label
next:
movl (%esp), %eax
movl %eax, 8(%esp)
label:
movl 8(%esp), %eax
addl $12, %esp
ret
max2:
subl $12, %esp
movl 20(%esp), %eax
movl 16(%esp), %ecx
movl %ecx, 4(%esp)
movl %eax, (%esp)
movl 4(%esp), %eax
cmpl (%esp), %eax
jge label1
movl (%esp), %eax
movl %eax, 8(%esp)
jmp label2
label1:
movl 4(%esp), %eax
movl %eax, 8(%esp)
label2:
movl 8(%esp), %eax
addl $12, %esp
ret
max:
subl $8, %esp
movl 12(%esp), %eax
movl %eax, (%esp)
movl (%esp), %eax
cmpl (%esp), %eax
jge label1
movl (%esp), %eax
movl %eax, 4(%esp)
jmp label2
label1:
movl (%esp), %eax
movl %eax, 4(%esp)
label2:
movl 4(%esp), %eax
addl $8, %esp
ret
max:
subl $12, %esp
movl 20(%esp), %eax
movl 16(%esp), %ecx
movl %ecx, 4(%esp)
movl %eax, (%esp)
movl 4(%esp), %eax
cmpl (%esp), %eax
jge label1
movl (%esp), %eax
movl %eax, 8(%esp)
jmp label2
label1:
movl (%esp), %eax
movl %eax, 8(%esp)
label2:
movl 8(%esp), %eax
addl $12, %esp
ret
max:
subl $12, %esp
movl 20(%esp), %eax
movl 16(%esp), %ecx
movl %ecx, 4(%esp)
movl %eax, (%esp)
movl 4(%esp), %eax
cmpl (%esp), %eax
jge label1
movl 4(%esp), %eax
movl %eax, 8(%esp)
jmp label2
label1:
movl (%esp), %eax
movl %eax, 8(%esp)
label2:
movl 8(%esp), %eax
addl $12, %esp
ret
Question 10. Fonctions récursives¶
Les fonctions récursives sont parfois utilisées en langage C. Lors de leur exécution, la pile permet de stocker temporairement les valeurs des variables et les adresses de retour. Considérons la fonction récursive suivante (où a
est une variable globale) :
int f(int i)
{
return a+f(i-1);
}
f:
pushl %ebp
movl %esp, %ebp
subl $12, %esp
movl 8(%ebp), %eax
movl %eax, -4(%ebp)
movl a, %eax
movl -4(%ebp), %ecx
subl $1, %ecx
movl %ecx, (%esp)
movl %eax, -8(%ebp)
calll f
movl -8(%ebp), %ecx
addl %eax, %ecx
movl %ecx, %eax
addl $12, %esp
popl %ebp
ret
f:
pushl %ebp
movl %esp, %ebp
subl $12, %esp
movl 8(%ebp), %eax
movl %eax, -4(%ebp)
movl -4(%ebp), %eax
subl $1, %eax
movl %eax, (%esp)
calll f
movl %eax, -8(%ebp)
movl -8(%ebp), %eax
addl a, %eax
addl $12, %esp
popl %ebp
ret
f:
pushl %ebp
movl %esp, %ebp
subl $12, %esp
movl 8(%ebp), %eax
movl %eax, -4(%ebp)
movl a, %eax
movl -4(%ebp), %ecx
movl %ecx, (%esp)
movl %eax, -8(%ebp)
calll f
movl -8(%ebp), %ecx
addl %eax, %ecx
movl %ecx, %eax
addl $12, %esp
popl %ebp
ret
f:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
movl 8(%ebp), %eax
movl %eax, -4(%ebp)
movl -4(%ebp), %eax
addl a, %eax
movl %eax, (%esp)
calll f
addl $8, %esp
popl %ebp
ret
pushl %ebp
movl %esp, %ebp
subl $12, %esp
movl 8(%ebp), %eax
movl %eax, -4(%ebp)
movl -4(%ebp), %eax
subl $1, %eax
movl %eax, (%esp)
calll f
movl %eax, -8(%ebp)
movl a, %eax
addl $12, %esp
popl %ebp
ret
Question 10. Pointeurs en assembleur¶
Pour comprendre le fonctionnement des pointeurs en C, il est parfois utile de se ramener à la traduction en assembleur de fragments de code C. Considérons les lignes suivantes :
int a=1252; int * ptr; int main(int argc, const char *argv[]) { ptr=&a; }
a
au pointeur ptr
. Laquelleleal a, %eax
movl %eax, ptr
movl a, %eax
movl ptr, %ecx
movl %eax, (%ecx)
movl a, %eax
movl %eax, ptr
pushl %eax
leal (%esp), %eax
movl a, %ecx
movl %ecx, (%esp)
movl %eax, ptr
popl %eax
leal a, %eax
addl $4, %eax
movl %eax, ptr
mov
prend comme premier argument la source et comme second la destination.