Vous êtes sur la page 1sur 88

Assembleur

Appels de fonction et conventions du C


Cours 05
Plan de la séance
Appels de fonction
Convention du C
Exercices

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 2


Plan de la séance
Appels de fonction
Convention du C
Exercices

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 3


Appels de fonction
Vue conceptuelle
La partie Instructions
Peut contenir plusieurs fonctions
Qui correspondent à des étiquettes

TEXT

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 4


Appels de fonction
Vue conceptuelle
fct1:
La partie Instructions
Peut contenir plusieurs fonctions
Qui correspondent à des étiquettes ret
fct2:
ret

main:
call fct1
call fct2
call fct1

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 5


Appels de fonction
Vue conceptuelle
fct1:

ret
fct2:
ret

main:
Les appels de fonction call fct1
sont des branchements call fct2
call fct1

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 6


Appels de fonction
Vue conceptuelle
fct1:

ret Le programme
sait où il faut
fct2: aller grâce à
ret l’étiquette

main:
call fct1
call fct2
call fct1

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 7


Appels de fonction
Vue conceptuelle
fct1:

Mais où faut-il revenir? ret


fct2:
ret

main:
call fct1
call fct2
call fct1

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 8


Appels de fonction
Vue conceptuelle
fct1:

Mais où faut-il revenir? ret


fct2:
ret

main:
call fct1
Deux options sont call fct2
possibles dans cet call fct1
exemple

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 9


Appels de fonction
Appel de fonction
• Le programme va utiliser la pile pour sauvegarder l’adresse de retour
• L’instruction call va donc empiler l’adresse de retour puis faire un jmp vers
l’étiquette de la fonction
• Au moment de retourner, le programme utilise l’adresse de retour sur la pile
• L’instruction ret va dépiler l’adresse de retour de la pile et faire un jmp vers
cette adresse
• Il importe donc qu’une fonction remette la pile dans l’état où elle l’a trouvée!
Sinon ret fera un branchement à une adresse inconnue.

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 10


Appels de fonction
Appel de fonction
• Le programme va utiliser la pile pour sauvegarder l’adresse de retour
• L’instruction call va donc empiler l’adresse de retour puis faire un jmp vers
l’étiquette de la fonction
• Au moment de retourner, le programme utilise l’adresse de retour sur la pile
• L’instruction ret va dépiler l’adresse de retour de la pile et faire un jmp vers
cette adresse
• Il importe donc qu’une fonction remette la pile dans l’état où elle l’a trouvée!
Sinon ret fera un branchement à une adresse inconnue.

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 11


Appels de fonction
Appel de fonction
• Le programme va utiliser la pile pour sauvegarder l’adresse de retour
• L’instruction call va donc empiler l’adresse de retour puis faire un jmp vers
l’étiquette de la fonction
• Au moment de retourner, le programme utilise l’adresse de retour sur la pile
• L’instruction ret va dépiler l’adresse de retour de la pile et faire un jmp vers
cette adresse
• Il importe donc qu’une fonction remette la pile dans l’état où elle l’a trouvée!
Sinon ret fera un branchement à une adresse inconnue.

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 12


Appels de fonction
Vue conceptuelle
fct1:

Direction des adresses basses


ret
fct2:
ret esp 0xEF04
esp
main: add … eip
PILE
call fct1
eip 0x4000
call fct2
call fct1

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 13


Appels de fonction
Vue conceptuelle
0x2000 fct1:

Direction des adresses basses


0x2FFC ret

0x3000 fct2:
ret esp 0xEF04
0x3FFC
esp
PILE 0x4000 main: add … eip
0x4004 call fct1
eip 0x4000
0x4008 call fct2
0x400C call fct1
0x4010

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 14


Appels de fonction
Vue conceptuelle
0x2000 fct1:

Direction des adresses basses


0x2FFC ret

0x3000 fct2:
0x4008 ret esp 0xEF00
esp 0x3FFC

PILE 0x4000 main: add …


0x4004 call fct1 eip
eip 0x4004
0x4008 call fct2
0x400C call fct1
0x4010

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 15


Appels de fonction
Vue conceptuelle
0x2000 fct1: eip

Direction des adresses basses


0x2FFC ret

0x3000 fct2:
0x4008 ret esp 0xEF00
esp 0x3FFC

PILE 0x4000 main: add …


0x4004 call fct1
eip 0x2000
0x4008 call fct2
0x400C call fct1
0x4010

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 16


Appels de fonction
Vue conceptuelle
0x2000 fct1:

Direction des adresses basses


0x2FFC ret eip

0x3000 fct2:
0x4008 ret esp 0xEF00
esp 0x3FFC

PILE 0x4000 main: add …


0x4004 call fct1
eip 0x2FFC
0x4008 call fct2
0x400C call fct1
0x4010

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 17


Appels de fonction
Vue conceptuelle
0x2000 fct1:

Direction des adresses basses


0x2FFC ret

0x3000 fct2:
0x4008 ret esp 0xEF04
0x3FFC
esp
PILE 0x4000 main: add …
0x4004 call fct1
eip 0x4008
0x4008 call fct2 eip
0x400C call fct1
0x4010

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 18


Appels de fonction
Vue conceptuelle
0x2000 fct1:

Direction des adresses basses


0x2FFC ret

0x3000 fct2:
0x400C ret esp 0xEF00
esp 0x3FFC

PILE 0x4000 main: add …


0x4004 call fct1
eip 0x4008
0x4008 call fct2 eip
0x400C call fct1
0x4010

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 19


Appels de fonction
Vue conceptuelle
0x2000 fct1:

Direction des adresses basses


0x2FFC ret

0x3000 fct2: eip


0x400C ret esp 0xEF00
esp 0x3FFC

PILE 0x4000 main: add …


0x4004 call fct1
eip 0x3000
0x4008 call fct2
0x400C call fct1
0x4010

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 20


Appels de fonction
Vue conceptuelle
0x2000 fct1:

Direction des adresses basses


0x2FFC ret

0x3000 fct2:
0x400C ret eip esp 0xEF00
esp 0x3FFC

PILE 0x4000 main: add …


0x4004 call fct1
eip 0x3FFC
0x4008 call fct2
0x400C call fct1
0x4010

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 21


Appels de fonction
Vue conceptuelle
0x2000 fct1:

Direction des adresses basses


0x2FFC ret

0x3000 fct2:
0x400C ret esp 0xEF04
0x3FFC
esp
PILE 0x4000 main: add …
0x4004 call fct1
eip 0x400C
0x4008 call fct2
0x400C call fct1 eip
0x4010

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 22


Appels de fonction
Vue conceptuelle
0x2000 fct1:

Direction des adresses basses


0x2FFC ret

0x3000 fct2:
esp 0x4010 ret esp 0xEF00
0x3FFC

PILE 0x4000 main: add …


0x4004 call fct1
eip 0x400C
0x4008 call fct2
0x400C call fct1 eip
0x4010

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 23


Appels de fonction
Vue conceptuelle
0x2000 fct1: eip

Direction des adresses basses


0x2FFC ret

0x3000 fct2:
esp 0x4010 ret esp 0xEF00
0x3FFC

PILE 0x4000 main: add …


0x4004 call fct1
eip 0x2000
0x4008 call fct2
0x400C call fct1
0x4010

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 24


Appels de fonction
Vue conceptuelle
0x2000 fct1:

Direction des adresses basses


0x2FFC ret eip

0x3000 fct2:
esp 0x4010 ret esp 0xEF00
0x3FFC

PILE 0x4000 main: add …


0x4004 call fct1
eip 0x2FFC
0x4008 call fct2
0x400C call fct1
0x4010

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 25


Appels de fonction
Vue conceptuelle
0x2000 fct1:

Direction des adresses basses


0x2FFC ret

0x3000 fct2:
0x4010 ret esp 0xEF04
0x3FFC
esp
PILE 0x4000 main: add …
0x4004 call fct1
eip 0x4010
0x4008 call fct2
0x400C call fct1
0x4010 eip

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 26


Plan de la séance
Appels de fonction
Convention du C
Exercices

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 27


Convention du C
Gestion des variables
• Variables globales dans .data
• Variables locales sur la pile
• L’allocation dynamique exploite le tas (non vu dans ce cours)

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 28


Convention du C
Gestion des paramètres
• Les paramètres d’une fonction sont sur la pile
• Les paramètres sont empilés de droite à gauche avant le call
• Les variables locales de la fonction sont allouées sur la pile au
moment d’entrer dans la fonction

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 29


Convention du C
Gestion des paramètres
• Le registre %ebp sert à se remémorer la position de %esp au moment
d’entrer dans la fonction
• Ceci se traduit typiquement par l’ajout d’un prologue et d’un
épilogue dans la définition d’une fonction

appelée
# Prologue # Epilogue
pushl %ebp movl %ebp, %esp Old ebp esp ebp
movl %esp, %ebp popl %ebp Return addr.

appelante
# Epilogue alt. 1e paramètre ebp + 8
leave

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 30


Convention du C
Valeurs de retour
• Si une fonction retourne un entier (ou type plus petit), celui-ci est
retourné dans %eax (%st(0) pour les float)
• La fonction écrase %eax!!!
• Si le type retourné est plus grand qu’un int, %eax contiendra
l’adresse de sa position en mémoire

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 31


Convention du C
Conventions sur les registres
• Une fonction peut modifier %eax, %ecx et %edx
• Il faut les sauvegarder avant d’appeler une fonction si on les utilise

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 32


Convention du C

Appelée (MyFunc)
Exemple illustratif ‘Z’
-8(%ebp) %esp
int MyFunc(int parameter1, char parameter2) { -4(%ebp) 9
int local1 = 9; %ebp
Old %ebp
char local2 = ‘Z’; Ret addr
État de la pile quand on

Appelante (main)
return 0; est là 8(%ebp) 7
} 12(%ebp) ‘8’

int main(int argc, char *argv[]){ PILE


MyFunc(7, ‘8’);
return 0;
}

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 33


Plan de la séance
Appels de fonction
Convention du C
Exercices

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 34


.data

Exemples et exercices A: .int 36


B: .int 24
.text
.globl main
main:
Retour sur l’exercice du Cours 04 movl A, %eax
movl B, %edx
Quelle valeur sera contenue dans %eax à la fin
while_loop:
de l’exécution de ce programme? cmpl $0, %edx
jz bye

%eax %edx movl %edx, %ecx


movl $0, %edx
36 24 div %ecx

24 12 movl %ecx, %eax

12 0 jmp while_loop

bye:
ret

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 35


.data
start_data: .byte 0x12, 0x34, 0x56, 0x78
hex : .ascii "0x%08X\n\0"
end_data :

Exercices .text
.globl main
print_hex:
pushl 4(%esp)
pushl $hex
call printf

Exercice 1 addl
ret
main:
$8, %esp

pushl %esp
Soit le programme assembleur ci-contre. call print_hex

pushl $start_data
Sachant que les trois premiers appels à print_hex ont produit à call print_hex

l’écran ce qui suit: pushl $end_data


call print_hex
0xBFC84C7C # 1
pushl $(end_data - start_data)
0x0804A01C call print_hex

0x0804A028 # 2
subl %eax, %eax
xorl %ebx, %ebx
Donnez le résultat des 3 affichages suivants ainsi que la ligne pushl start_data(%eax, %ebx, 1)
call print_hex
manquante en bas de la fonction.
# 3
pushl %esp
call print_hex

# 4
# Ligne volontairement masquée

ret
Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 36
.data
start_data: .byte 0x12, 0x34, 0x56, 0x78
hex : .ascii "0x%08X\n\0"
end_data :

Exercices .text
.globl main
print_hex:
pushl 4(%esp)
pushl $hex
call printf

Exercice 1 addl
ret
main:
$8, %esp

pushl %esp
Soit le programme assembleur ci-contre. call print_hex

pushl $start_data
Sachant que les trois premiers appels à print_hex ont produit à call print_hex

l’écran ce qui suit: pushl $end_data


call print_hex
0xBFC84C7C # 1
pushl $(end_data - start_data)
0x0804A01C call print_hex

0x0804A028 # 2
subl %eax, %eax
xorl %ebx, %ebx
Donnez le résultat des 3 affichages suivants ainsi que la ligne pushl start_data(%eax, %ebx, 1)
call print_hex
manquante en bas de la fonction.
# 3
pushl %esp
call print_hex

# 4
# Ligne volontairement masquée

ret
Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 37
.data
start_data: .byte 0x12, 0x34, 0x56, 0x78
hex : .ascii "0x%08X\n\0"
end_data :

Exercices .text
.globl main
print_hex:
pushl 4(%esp)
pushl $hex
call printf

Exercice 1 addl
ret
main:
$8, %esp

pushl %esp
Soit le programme assembleur ci-contre. call print_hex
0x0804A028
pushl $start_data
Sachant que les trois premiers appels à print_hex ont produit à call print_hex - 0x0804A01C
l’écran ce qui suit: pushl $end_data
= 0x0000000C
call print_hex
0xBFC84C7C # 1
pushl $(end_data - start_data)
0x0804A01C call print_hex

0x0804A028 # 2
subl %eax, %eax
xorl %ebx, %ebx
Donnez le résultat des 3 affichages suivants ainsi que la ligne pushl start_data(%eax, %ebx, 1)
call print_hex
manquante en bas de la fonction.
# 3
pushl %esp
call print_hex

# 4
# Ligne volontairement masquée

ret
Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 38
.data
start_data: .byte 0x12, 0x34, 0x56, 0x78
hex : .ascii "0x%08X\n\0"
end_data :

Exercices .text
.globl main
print_hex:
pushl 4(%esp)
pushl $hex
call printf

Exercice 1 addl
ret
main:
$8, %esp

pushl %esp
Soit le programme assembleur ci-contre. call print_hex

pushl $start_data
Sachant que les trois premiers appels à print_hex ont produit à call print_hex

l’écran ce qui suit: pushl $end_data


call print_hex 0x78563412
0xBFC84C7C # 1
pushl $(end_data - start_data)
0x0804A01C call print_hex

0x0804A028 # 2
subl %eax, %eax
xorl %ebx, %ebx
Donnez le résultat des 3 affichages suivants ainsi que la ligne pushl start_data(%eax, %ebx, 1)
call print_hex
manquante en bas de la fonction.
# 3
pushl %esp
call print_hex

# 4
# Ligne volontairement masquée

ret
Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 39
.data
start_data: .byte 0x12, 0x34, 0x56, 0x78
hex : .ascii "0x%08X\n\0"
end_data :

Exercices .text
.globl main
print_hex:
pushl 4(%esp)
pushl $hex
call printf

Exercice 1 addl
ret
main:
$8, %esp

pushl %esp
Soit le programme assembleur ci-contre. call print_hex

pushl $start_data 0xBFC84C7C


Sachant que les trois premiers appels à print_hex ont produit à call print_hex
- 0x00000014
l’écran ce qui suit: pushl $end_data
= 0xBFC84C68
call print_hex
0xBFC84C7C # 1
pushl $(end_data - start_data)
0x0804A01C call print_hex

0x0804A028 # 2
subl %eax, %eax
xorl %ebx, %ebx
Donnez le résultat des 3 affichages suivants ainsi que la ligne pushl start_data(%eax, %ebx, 1)
call print_hex
manquante en bas de la fonction.
# 3
pushl %esp
call print_hex

# 4
# Ligne volontairement masquée

ret
Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 40
.data
start_data: .byte 0x12, 0x34, 0x56, 0x78
hex : .ascii "0x%08X\n\0"
end_data :

Exercices .text
.globl main
print_hex:
pushl 4(%esp)
pushl $hex
call printf

Exercice 1 addl
ret
main:
$8, %esp

pushl %esp
Soit le programme assembleur ci-contre. call print_hex

pushl $start_data 0xBFC84C7C


Sachant que les trois premiers appels à print_hex ont produit à call print_hex
- 0x00000014
l’écran ce qui suit: pushl $end_data
= 0xBFC84C68
call print_hex
0xBFC84C7C # 1
pushl $(end_data - start_data)
0x0804A01C call print_hex

0x0804A028 # 2
subl %eax, %eax
xorl %ebx, %ebx
Donnez le résultat des 3 affichages suivants ainsi que la ligne pushl start_data(%eax, %ebx, 1)
call print_hex
manquante en bas de la fonction.
# 3
pushl %esp
call print_hex

# 4
addl $0x18, %esp

ret
Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 41
Exercices
Exercice 2
Donnez l’assembleur équivalent de la fonction suivante
int is_lower_case (const char c){
if ( c >= 'a' && c <= 'z')
return 1;
return 0;
}

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 42


Réponse

Exercices .text
.globl is_lower_case
is_lower_case:
movb 4(%esp), %cl

Exercice 2 movl $0, %eax


cmpb $'a’, %cl
Donnez l’assembleur équivalent de la fonction suivante jb bye

int is_lower_case (const char c){ cmpb $'z’, %cl


if ( c >= 'a' && c <= 'z') ja bye
return 1;
return 0; movl $1, %eax
}
bye:
ret

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 43


Exercices
Exercice 3
Donnez l’assembleur équivalent de la fonction suivante
unsigned int length(const char* src){

unsigned int i = 0;
while(src[i] != 0)
i++;

return i;
}

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 44


Réponse:

Exercices .text
.globl length
length:
pushl %ebp
movl %esp, %ebp
Exercice 3
movl $0, %eax # %eax == i
Donnez l’assembleur équivalent de la fonction suivante movl 8(%ebp), %edx

unsigned int length(const char* src){ test:


cmpb $0, (%edx)
unsigned int i = 0; je end_loop
while(src[i] != 0)
i++; addl $1, %eax
addl $1, %edx
return i;
} jmp test

end_loop:

leave /* Restore ebp and esp */


ret

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 45


Exercices
Exercice 4
Donnez l’assembleur équivalent de la fonction suivante
unsigned int to_integer(const char* src){

unsigned int i = 0, value = 0;


while(src[i] != 0){
value *= 10;
value += ( src[i] & 0xf );
i++;
}

return value;
}

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 46


Réponse:

Exercices .text
.globl to_integer
to_integer:
pushl %ebp
movl %esp, %ebp

Exercice 4 movl $0, %eax # %eax == value


movl 8(%ebp), %edx
Donnez l’assembleur équivalent de la fonction suivante
test:
cmpb $0, (%edx)
unsigned int to_integer(const char* src){ je end_loop

unsigned int i = 0, value = 0; pushl %edx


while(src[i] != 0){ movl $10, %ecx
value *= 10; mul %ecx
popl %edx
value += ( src[i] & 0xf );
i++; movl $0, %ecx # initialize %ecx à 0
} movb (%edx), %cl # lit le char (supp. ‘0’ à ‘9’)
andb $0xF, %cl # convertit en nombre
return value; addl %ecx, %eax # ajoute à %eax
} addl $1, %edx

jmp test

end_loop:
leave
ret

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 47


Exercices
Exercice 5
Donnez l’assembleur équivalent de la fonction suivante
void append(char* dst, const char* src){

unsigned int i = 0, j = 0;

while( dst[j] != 0 ) j++;

while( src[i] != 0 )
dst[j++] = src[i++];

dst[j] = '\0';
}

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 48


Réponse

Exercices append:
movl 4(%esp), %ecx
Note:
# %ecx == dst
movl 8(%esp), %edx # %edx == src

L1:
Exercice 5 cmpb $0, (%ecx)
jz L2
Donnez l’assembleur équivalent de la fonction suivante incl %ecx
jmp L1
void append(char* dst, const char* src){
L2:
unsigned int i = 0, j = 0; cmpb $0, (%edx)
jz fin
while( dst[j] != 0 ) j++; movb (%edx), %al
movb %al, (%ecx)
while( src[i] != 0 ) incl %ecx
dst[j++] = src[i++]; incl %edx
jmp L2
dst[j] = '\0';
} fin:
movb $0, (%ecx)
ret

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 49


Exercices
Exercice 6
Donnez l’assembleur équivalent de la fct suivante:
unsigned int gcd(unsigned int a,
unsigned int b){
unsigned int t;

while( b != 0 ){
t = b;
b = a % b;
a = t;
}
return a;
}
Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 50
.text

Exercices .globl gcd


gcd:
pushl %ebp
movl %esp, %ebp

Exercice 6 movl
movl
8(%ebp), %eax
12(%ebp), %edx
Donnez l’assembleur équivalent de la fct suivante: T:
cmpl $0, %edx
unsigned int gcd(unsigned int a, jz L prologue
unsigned int b){
movl %edx, %ecx
unsigned int t; épilogue
movl $0, %edx
div %ecx
while( b != 0 ){
t = b; movl %ecx, %eax
b = a % b;
jmp T
a = t;
} L:
leave
return a; ret
}
Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 51
.text

Exercices .globl gcd


gcd:
pushl %ebp
movl %esp, %ebp a

Exercice 6 movl
movl
8(%ebp), %eax
12(%ebp), %edx On va rechercher
les paramètres
Donnez un équivalent en assembleur IA-32 de la fonction
T:
suivante
b
cmpl $0, %edx
unsigned int gcd(unsigned int a, jz L
unsigned int b){
movl %edx, %ecx
unsigned int t;
movl $0, %edx
div %ecx
while( b != 0 ){
t = b; movl %ecx, %eax
b = a % b;
jmp T
a = t;
} L:
leave
return a; ret
}
Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 52
.text

Exercices .globl gcd


gcd:
pushl %ebp
movl %esp, %ebp

Exercice 6 movl
movl
8(%ebp), %eax
12(%ebp), %edx
Donnez un équivalent en assembleur IA-32 de la fonction suivante
while_loop:
cmpl $0, %edx
unsigned int gcd(unsigned int a, jz au_revoir
unsigned int b){
movl %edx, %ecx
unsigned int t;
movl $0, %edx
div %ecx
while( b != 0 ){
t = b; movl %ecx, %eax
b = a % b;
jmp while_loop
a = t;
} au_revoir:
leave
return a; ret
}
Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 53
.text

Exercices .globl gcd


gcd:
pushl %ebp
movl %esp, %ebp

Exercice 6 movl
movl
8(%ebp), %eax
12(%ebp), %edx
Donnez un équivalent en assembleur IA-32 de la fonction suivante
while_loop:
cmpl $0, %edx
unsigned int gcd(unsigned int a, jz au_revoir
unsigned int b){
movl %edx, %ecx
unsigned int t;
movl $0, %edx # %eax <- %eax / %ecx
div %ecx # %edx <- mod(%eax,%ecx)
while( b != 0 ){
t = b; movl %ecx, %eax
b = a % b;
jmp while_loop
a = t;
} au_revoir:
leave
return a; ret
}
Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 54
.text

Exercices .globl gcd


gcd:
pushl %ebp
Note:
# La variable t n’a pas
movl %esp, %ebp # été allouée sur la pile

Exercice 6 movl
movl
8(%ebp), %eax
12(%ebp), %edx
Donnez un équivalent en assembleur IA-32 de la fonction suivante
while_loop:
cmpl $0, %edx
unsigned int gcd(unsigned int a, jz au_revoir
unsigned int b){
movl %edx, %ecx
unsigned int t;
movl $0, %edx
div %ecx
while( b != 0 ){
t = b; movl %ecx, %eax
b = a % b;
jmp while_loop
a = t;
} au_revoir:
leave
return a; ret
}
Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 55
Exercices
Exercice 7
Écrivez la fonction suivante en assembleur:
Unsigned int count_steps(unsigned int n){

unsigned int steps = 0;

while( n > 1 ){
steps = steps + 1

if ( n % 2 == 0 )
n = n/2;
else
n = 3*n + 1;
}

return steps
}

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 56


Exercices
Exercice 7 Réponse

Écrivez la fonction suivante en assembleur:


.text
.globl count_steps # si pair
count_steps: addl $4, %esp # n = 2*n
pushl %ebp jmp Fin_boucle
movl %esp, %ebp
pushl %ebx Impair:
# si impair
movl $0, %ebx # initialise steps popl %eax
movl 8(%ebp), %eax movl $3, %ecx
mul %ecx
Test: addl $1, %eax # n = 3*n + 1
cmpl $1, %eax
jbe Fin # quitte si n <= 1 Fin_boucle:
jmp Test
incl %ebx # incrémenter le compte
Fin:
pushl %eax movl %ebx, %eax
movl $0, %edx popl %ebx
movl $2, %ecx leave
div %ecx ret # resultat dans %eax
cmpl $0, %edx
jnz Impair # test de parite

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 57


Note:
Exercices # On omet .text .globl count_steps
# pour sauver de l’espace sur la diapositive

Exercice 7 Réponse….

Écrivez la fonction suivante en assembleur:


count_steps: unsigned int count_steps(unsigned int n){
# Prologue
pushl %ebp unsigned int steps = 0;
movl %esp, %ebp
while( n > 1 ){
steps = steps + 1

if ( n % 2 == 0 )
n = n/2;
else
n = 3*n + 1;
}

# Epilogue return steps


leave }
ret # resultat dans %eax

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 58


Exercices
Exercice 7 Réponse….

Écrivez la fonction suivante en assembleur:


count_steps: unsigned int count_steps(unsigned int n){
# Prologue
pushl %ebp Devrait être unsigned int steps = 0;
movl %esp, %ebp
sur la pile, while( n > 1 ){
on va un registre steps = steps + 1
… à la place
if ( n % 2 == 0 )
n = n/2;
else
n = 3*n + 1;
}

# Epilogue return steps


leave }
ret # resultat dans %eax

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 59


Exercices
Exercice 7 Réponse….

Écrivez la fonction suivante en assembleur:


count_steps: unsigned int count_steps(unsigned int n){
# Prologue
pushl %ebp Devrait être unsigned int steps = 0;
movl %esp, %ebp
sur la pile,
… while( n > 1 ){
on va un registre steps = steps + 1
movl $0, %ebx # initialise steps à la place
if ( n % 2 == 0 )
n = n/2;
… else
n = 3*n + 1;
}

# Epilogue return steps


popl %ebp }
ret # resultat dans %eax

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 60


Exercices
Exercice 7 Réponse….

Écrivez la fonction suivante en assembleur:


count_steps: unsigned int count_steps(unsigned int n){
# Prologue
pushl %ebp Devra être unsigned int steps = 0;
movl %esp, %ebp
restitué
… while( n > 1 ){
steps = steps + 1
movl $0, %ebx # initialise steps
if ( n % 2 == 0 )
n = n/2;
… else
n = 3*n + 1;
}

# Epilogue return steps


leave }
ret # resultat dans %eax

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 61


Exercices
Exercice 7 Réponse….

Écrivez la fonction suivante en assembleur:


count_steps: unsigned int count_steps(unsigned int n){
# Prologue
pushl %ebp Devra être unsigned int steps = 0;
movl %esp, %ebp
restitué
pushl %ebx while( n > 1 ){
steps = steps + 1
movl $0, %ebx # initialise steps
if ( n % 2 == 0 )
n = n/2;
… else
n = 3*n + 1;
}
popl %ebx
# Epilogue return steps
leave }
ret # resultat dans %eax

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 62


Exercices
Exercice 7 Réponse….

Écrivez la fonction suivante en assembleur:


count_steps: unsigned int count_steps(unsigned int n){
# Prologue
pushl %ebp unsigned int steps = 0;
movl %esp, %ebp
pushl %ebx while( n > 1 ){
steps = steps + 1
movl $0, %ebx # initialise steps
if ( n % 2 == 0 )
Sert à mettre le résultat n = n/2;
… else
dans %eax n = 3*n + 1;
movl %ebx, %eax }
popl %ebx
# Epilogue return steps
leave }
ret # resultat dans %eax

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 63


Exercices
Exercice 7 Réponse….

Écrivez la fonction suivante en assembleur:


count_steps: unsigned int count_steps(unsigned int n){
# Prologue
pushl %ebp unsigned int steps = 0;
movl %esp, %ebp
pushl %ebx while( n > 1 ){
steps = steps + 1
movl $0, %ebx # initialise steps
movl 8(%ebp), %eax # lire n if ( n % 2 == 0 )
On va chercher n n = n/2;
… sur la pile else
n = 3*n + 1;
movl %ebx, %eax }
popl %ebx
# Epilogue return steps
leave }
ret # resultat dans %eax

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 64


Exercices
Exercice 7 Réponse….

Écrivez la fonction suivante en assembleur:


count_steps: unsigned int count_steps(unsigned int n){
# n dans %eax, steps dans %ebx
unsigned int steps = 0;

while( n > 1 ){
steps = steps + 1
… # On va construire la boucle
if ( n % 2 == 0 )
n = n/2;
else
n = 3*n + 1;
}

return steps
}
# resultat (steps) est dans %eax

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 65


Exercices
Exercice 7 Réponse….

Écrivez la fonction suivante en assembleur:


count_steps: unsigned int count_steps(unsigned int n){
# n dans %eax, steps dans %ebx
Test: unsigned int steps = 0;
cmpl $1, %eax
jbe Fin # quitte si n <= 1 while( n > 1 ){
steps = steps + 1
… # corps de boucle
On construit if ( n % 2 == 0 )
la structure de boucle n = n/2;
else
n = 3*n + 1;
}

return steps
Fin_boucle: }
jmp Test # Teste si necessaire de boucler
Fin: # resultat (steps) est dans %eax

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 66


Exercices
Exercice 7 Réponse….

Écrivez la fonction suivante en assembleur:


count_steps: unsigned int count_steps(unsigned int n){
# n dans %eax, steps dans %ebx
Test: # teste n > 1 et sort au besoin unsigned int steps = 0;

incl %ebx # incrémenter le compte while( n > 1 ){


steps = steps + 1

On incrément steps if ( n % 2 == 0 )
n = n/2;
else
n = 3*n + 1;
}

return steps
}
Fin_boucle: # Va vers Test
Fin: # resultat (steps) est dans %eax

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 67


Exercices
Exercice 7 Réponse….

Écrivez la fonction suivante en assembleur:


count_steps: unsigned int count_steps(unsigned int n){
# n dans %eax, steps dans %ebx
Test: # teste n > 1 et sort au besoin unsigned int steps = 0;

incl %ebx # incrémenter le compte while( n > 1 ){


steps = steps + 1
# test de parite
jnz Impair Structure if/else if ( n % 2 == 0 )
n = n/2;
# n = n/2 else
n = 3*n + 1;
jmp Fin_boucle }

Impair: return steps


# n = 3*n + 1 }

Fin_boucle: # Va vers Test


Fin: # resultat (steps) est dans %eax
Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 68
Exercices
Exercice 7 Réponse….

Écrivez la fonction suivante en assembleur:


unsigned int count_steps(unsigned int n){

unsigned int steps = 0;

while( n > 1 ){
steps = steps + 1
# test de parite
jnz Impair Structure if/else if ( n % 2 == 0 )
n = n/2;
# n = n/2 else
n = 3*n + 1;
jmp Fin_boucle }

Impair: return steps


# n = 3*n + 1 }

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 69


Exercices
Exercice 7 Réponse….

Écrivez la fonction suivante en assembleur:


unsigned int count_steps(unsigned int n){
# test de parite
jnz Impair unsigned int steps = 0;

# n = n/2 while( n > 1 ){


steps = steps + 1
jmp Fin_boucle
Structure if/else if ( n % 2 == 0 )
Impair: n = n/2;
# n = 3*n + 1 else
n = 3*n + 1;
}

return steps
}

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 70


Exercices
Exercice 7 Réponse….

Écrivez la fonction suivante en assembleur:


unsigned int count_steps(unsigned int n){
# test de parite
unsigned int steps = 0;

movl $2, %ecx while( n > 1 ){


div %ecx steps = steps + 1
cmpl $0, %edx Test de parité?
jnz Impair if ( n % 2 == 0 )
n = n/2;
else
n = 3*n + 1;
}

return steps
}

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 71


Exercices
Exercice 7 Réponse….

Écrivez la fonction suivante en assembleur:


unsigned int count_steps(unsigned int n){
# test de parite
unsigned int steps = 0;

movl $2, %ecx while( n > 1 ){


div %ecx steps = steps + 1
cmpl $0, %edx Test de parité?
jnz Impair if ( n % 2 == 0 )
n = n/2;
%eax est écrasé! else
OK si pair! ☺ n = 3*n + 1;
}
Pas OK si impair 
return steps
}

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 72


Exercices
Exercice 7 Réponse….

Écrivez la fonction suivante en assembleur:


unsigned int count_steps(unsigned int n){
# test de parite
pushl %eax %eax est sauvegardé unsigned int steps = 0;

movl $2, %ecx while( n > 1 ){


div %ecx steps = steps + 1
cmpl $0, %edx
jnz Impair if ( n % 2 == 0 )
n = n/2;
else
n = 3*n + 1;
}

return steps
}

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 73


Exercices
Exercice 7 Réponse….

Écrivez la fonction suivante en assembleur:


unsigned int count_steps(unsigned int n){
# test de parite
pushl %eax unsigned int steps = 0;
movl $0, %edx %edx doit être 0 pour
movl $2, %ecx while( n > 1 ){
div %ecx
effectuer la division! steps = steps + 1
cmpl $0, %edx
jnz Impair if ( n % 2 == 0 )
n = n/2;
else
n = 3*n + 1;
}

return steps
}

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 74


Exercices
Exercice 7 Réponse….

Écrivez la fonction suivante en assembleur:


unsigned int count_steps(unsigned int n){
# test de parite
pushl %eax unsigned int steps = 0;
movl $0, %edx
movl $2, %ecx while( n > 1 ){
div %ecx steps = steps + 1
cmpl $0, %edx
jnz Impair if ( n % 2 == 0 )
n = n/2;
else
n = 3*n + 1;
}

return steps
}

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 75


Exercices
Exercice 7 Réponse….

Écrivez la fonction suivante en assembleur:


unsigned int count_steps(unsigned int n){
# test de parite
jnz Impair unsigned int steps = 0;

# n = n/2 while( n > 1 ){


steps = steps + 1
jmp Fin_boucle
Structure if/else if ( n % 2 == 0 )
Impair: n = n/2;
# n = 3*n + 1 else
n = 3*n + 1;
}

return steps
}

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 76


Exercices
Exercice 7 Réponse….

Écrivez la fonction suivante en assembleur:


unsigned int count_steps(unsigned int n){
# test de parite
jnz Impair unsigned int steps = 0;

# n = n/2 ? while( n > 1 ){


steps = steps + 1
jmp Fin_boucle
Structure if/else if ( n % 2 == 0 )
Impair: n = n/2;
# n = 3*n + 1 else
n = 3*n + 1;
}

return steps
}

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 77


Exercices
Exercice 7 Réponse….

Écrivez la fonction suivante en assembleur:


unsigned int count_steps(unsigned int n){
# test de parite
jnz Impair unsigned int steps = 0;

# n = n/2 while( n > 1 ){


addl $4, %esp steps = steps + 1
jmp Fin_boucle
%eax a déjà été divisé
par 2 if ( n % 2 == 0 )
Impair: On va se débarrasser de n = n/2;
# n = 3*n + 1 else
Sa sauvegarde n = 3*n + 1;
}

return steps
}

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 78


Exercices
Exercice 7 Réponse….

Écrivez la fonction suivante en assembleur:


unsigned int count_steps(unsigned int n){
# test de parite
jnz Impair unsigned int steps = 0;

# n = n/2 while( n > 1 ){


steps = steps + 1
jmp Fin_boucle
Structure if/else if ( n % 2 == 0 )
Impair: n = n/2;
# n = 3*n + 1 ? else
n = 3*n + 1;
}

return steps
}

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 79


Exercices
Exercice 7 Réponse….

Écrivez la fonction suivante en assembleur:


unsigned int count_steps(unsigned int n){
# test de parite
jnz Impair unsigned int steps = 0;

# n = n/2 while( n > 1 ){


steps = steps + 1
jmp Fin_boucle
if ( n % 2 == 0 )
Impair: n = n/2;
# n = 3*n + 1 ? else
popl %eax n = 3*n + 1;
movl $3, %ecx }
mul %ecx
add $1, %eax return steps
}

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 80


Exercices
Exercice 8 Réponse….

Écrivez la fonction suivante en assembleur:


unsigned int count_steps(unsigned int n){
# test de parite
jnz Impair unsigned int steps = 0;

# n = n/2 while( n > 1 ){


steps = steps + 1
jmp Fin_boucle
if ( n % 2 == 0 )
Impair: n = n/2;
# n = 3*n + 1 ? On récupère la valeur de else
popl %eax n = 3*n + 1;
movl $3, %ecx %eax avant la division }
mul %ecx par 2
add $1, %eax return steps
}

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 81


Exercices
Exercice 7 Réponse….

Écrivez la fonction suivante en assembleur:


unsigned int count_steps(unsigned int n){
# test de parite
jnz Impair unsigned int steps = 0;

# n = n/2 while( n > 1 ){


steps = steps + 1
jmp Fin_boucle
if ( n % 2 == 0 )
Impair: n = n/2;
# n = 3*n + 1 ? else
popl %eax n = 3*n + 1;
movl $3, %ecx }
mul %ecx
On multiplie %eax
add $1, %eax par 3 return steps
}

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 82


Exercices
Exercice 7 Réponse….

Écrivez la fonction suivante en assembleur:


unsigned int count_steps(unsigned int n){
# test de parite
jnz Impair unsigned int steps = 0;

# n = n/2 while( n > 1 ){


steps = steps + 1
jmp Fin_boucle
if ( n % 2 == 0 )
Impair: n = n/2;
# n = 3*n + 1 ? else
popl %eax n = 3*n + 1;
movl $3, %ecx }
mul %ecx
addl $1, %eax return steps
On ajoute 1 }

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 83


Exercices
Exercice 7 Réponse ☺

Écrivez la fonction suivante en assembleur:


.text
.globl count_steps # si pair
count_steps: addl $4, %esp # n = 2*n
pushl %ebp jmp Fin_boucle
movl %esp, %ebp
pushl %ebx Impair:
# si impair
movl $0, %ebx # initialise steps popl %eax
movl 8(%ebp), %eax movl $3, %ecx
mul %ecx
Test: addl $1, %eax # n = 3*n + 1
cmpl $1, %eax
jbe Fin # quitte si n <= 1 Fin_boucle:
jmp Test
incl %ebx # incrémenter le compte
Fin:
pushl %eax movl %ebx, %eax
movl $0, %edx popl %ebx
movl $2, %ecx leave
div %ecx ret # resultat dans %eax
cmpl $0, %edx
jnz Impair # test de parite

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 84


Exercices
Exercice 8
Donnez l’assembleur équivalent de la fonction suivante
int is_prime(unsigned int n){

int p = 0;

for(; p<2; p++) if( n == p ) return 0;


for(; p<4; p++) if( n == p ) return 1;
if( n % 2 ) return 0;

for(p = 3; p*p <= n; p += 2)


if( ( n % p ) == 0 )
return 0;

return 1;
}

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 85


Réponse (1):

Exercices .text
.globl is_prime
is_prime:
Note:
# %ebx == n
pushl %ebp
movl %esp, %ebp
pushl %ebx
Exercice 8
movl 8(%ebp), %ebx
Donnez l’assembleur équivalent de la fonction suivante
cmpl $0, %ebx
je not_prime
int is_prime(unsigned int n){
cmpl $1, %ebx Nous aurons plus loin…
int p = 0; je not_prime
prime:
cmpl $2, %ebx movl $1, %eax
for(; p<2; p++) if( n == p ) return 0; jmp bye
je prime
for(; p<4; p++) if( n == p ) return 1;
if( n % 2 ) return 0; cmpl $3, %ebx not_prime:
je prime movl $0, %eax
for(p = 3; p*p <= n; p += 2)
movl %ebx, %eax bye:
if( ( n % p ) == 0 ) popl %ebx
return 0; andl $1, %eax
cmpl $0, %eax leave
je not_prime ret
return 1;
}

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 86


Réponse (2, suite et fin):

Exercices movl

test:
$3, %ecx Note:
# %ebx == n
movl %ecx, %eax # %ecx == p
mul %ecx # %eax == p*p

Exercice 8 cmpl %ebx, %eax


ja prime
Donnez l’assembleur équivalent de la fonction suivante
movl $0, %edx
movl %ebx, %eax
int is_prime(unsigned int n){ div %ecx # %edx == n % p
cmp $0, %edx
int p = 0; je not_prime

for(; p<2; p++) if( n == p ) return 0; addl $2, %ecx # p += 2


for(; p<4; p++) if( n == p ) return 1; jmp test
if( n % 2 ) return 0;
prime:
for(p = 3; p*p <= n; p += 2) movl $1, %eax
if( ( n % p ) == 0 ) jmp bye
return 0;
not_prime:
movl $0, %eax
return 1;
} bye:
popl %ebx
leave
ret
Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 87
Exercices
Exercice 9:
À faire à la maison.
Donnez un équivalent en assembleur de la fonction suivante:

unsigned int gcd(unsigned int a, unsigned int b){

if( a == 0 ) return b;

return gcd(b%a, a);


}

Mise à jour: 2022/02/09 INF1600: Architecture des micro-ordinateurs 88

Vous aimerez peut-être aussi