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;
Parmi les traductions en assembleur ci-dessus, une seule est correcte. Laquelle ?
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;
Une seule des séquences d’instructions assembleur ci-dessous est une traduction correcte de cette séquence d’instructions. Laquelle ?
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++;
Une seule des séquences d’instructions assembleur ci-dessous est une traduction correcte de cette séquence d’instructions. Laquelle ?
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++;
Une seule des séquences d’instructions en assembleur ci-dessous correspond à ce fragment de code C. Laquelle ?
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++;
Parmi les séquences d’assembleur ci-dessous, une seule est une traduction correcte de cette instruction conditionnelle. Laquelle ?
  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;
}
Parmi les séquences d’assembleur ci-dessous, une seule est une traduction correcte de cette boucle 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;
}
Parmi les séquences d’instructions en assembleur ci-dessous, une seule traduit correctement la boucle 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;
}
Parmi les séquences d’instructions en assembleur ci-dessous, une seule traduit correctement la fonction ci-dessus. Laquelle ?
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;
}
Parmi les groupes d’instructions ci-dessous, un seul est la traduction de cette fonction. Lequel ?
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);
}
Parmi les séquences d’instructions assembleur ci-dessous, une seule est une traduction correctement de cette fonction. Laquelle ?
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;
}
Parmi les séquences d’instructions en assembleur ci-dessous, une seule est la traduction de l’assignation de l’adresse de a au pointeur ptr. Laquelle
leal    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

Verifiez vos réponses