Vous êtes sur la page 1sur 76

Assembleur

Introduction à l’assembleur x86 (suite)


Instructions UAL et directives
Cours 04
Mention légale – enregistrement des séances
de cours
• L’activité d’enseignement en ligne que vous vous apprêtez à visionner sera enregistrée. Si vous ne souhaitez
pas être enregistré, il est de votre responsabilité de désactiver votre microphone et votre caméra.

• À défaut de désactiver votre microphone et votre caméra, vous consentez à l’enregistrement audio ou
audiovisuel, à la conservation, à l’utilisation et à la rediffusion de l’enregistrement de votre nom, de votre
voix et de votre image dans le cadre de l’activité d’enseignement en ligne.

• Pour plus d’information, veuillez consulter la mention relative à la protection des renseignements
personnels sur le site Moodle du cours.

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 2


Plan de la séance
Introduction à l’assembleur x86 (suite);
Appels de fonction
Convention du C
Instructions UAL et directives;
Multiplication et division
Opérations logiques
Directives

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 3


Plan de la séance
Introduction à l’assembleur x86 (suite);
Appels de fonction
Convention du C
Instructions UAL et directives;
Multiplication et division
Opérations logiques
Directives

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 4


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

TEXT

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 5


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: 2021/02/03 INF1600: Architecture des micro-ordinateurs 6


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: 2021/02/03 INF1600: Architecture des micro-ordinateurs 7


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: 2021/02/03 INF1600: Architecture des micro-ordinateurs 8


Appels de fonction
Vue conceptuelle
fct1:

Mais où faut-il revenir? ret


fct2:
ret

main:
call fct1
call fct2
call fct1

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 9


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: 2021/02/03 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: 2021/02/03 INF1600: Architecture des micro-ordinateurs 11


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: 2021/02/03 INF1600: Architecture des micro-ordinateurs 12


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: 2021/02/03 INF1600: Architecture des micro-ordinateurs 13


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: 2021/02/03 INF1600: Architecture des micro-ordinateurs 14


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: 2021/02/03 INF1600: Architecture des micro-ordinateurs 15


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: 2021/02/03 INF1600: Architecture des micro-ordinateurs 16


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: 2021/02/03 INF1600: Architecture des micro-ordinateurs 17


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: 2021/02/03 INF1600: Architecture des micro-ordinateurs 18


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: 2021/02/03 INF1600: Architecture des micro-ordinateurs 19


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: 2021/02/03 INF1600: Architecture des micro-ordinateurs 20


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: 2021/02/03 INF1600: Architecture des micro-ordinateurs 21


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: 2021/02/03 INF1600: Architecture des micro-ordinateurs 22


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: 2021/02/03 INF1600: Architecture des micro-ordinateurs 23


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: 2021/02/03 INF1600: Architecture des micro-ordinateurs 24


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: 2021/02/03 INF1600: Architecture des micro-ordinateurs 25


Plan de la séance
Introduction à l’assembleur x86 (suite);
Appels de fonction
Convention du C
Instructions UAL et directives;
Multiplication et division
Opérations logiques
Directives

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 26


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: 2021/02/03 INF1600: Architecture des micro-ordinateurs 27


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 locale de la fonction sont allouée sur la pile au moment
d’entrer dans la fonction

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 28


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 popl %ebp Old ebp esp ebp
movl %esp, %ebp Return addr.

appelante
1e paramètre ebp + 8

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 29


Convention du C
Valeurs de retour
• Si une fonction retourne un entier (ou type plus petit), celui est
retournée 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: 2021/02/03 INF1600: Architecture des micro-ordinateurs 30


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: 2021/02/03 INF1600: Architecture des micro-ordinateurs 31


Convention du C
Formulation du problème
Considérez ce programme, pour lequel nous avions déterminé qu’il modifiait la section .data comme suit:
.data
p_int: .ascii "%d\n\0"
IT: .int 4
F: .int 0, 1, 0, 0, 0, 0 F: .int 0, 1, 1, 2, 3, 5
.text
.global main

main:
movl IT, %ecx
movl $F, %edx
L1:
movl (%edx), %eax
addl 4(%edx), %eax
movl %eax, 8(%edx);
addl $4, %edx

loop L1
ret

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 32


Convention du C
Formulation du problème
On désire afficher les 4 valeurs calculées (1, 2, 3 et 5) dans la boucle L1 en appelant la fonction printf(…)
.data
p_int: .ascii "%d\n\0"
IT: .int 4
F: .int 0, 1, 0, 0, 0, 0 F: .int 0, 1, 1, 2, 3, 5
.text
.global main

main:
movl IT, %ecx
movl $F, %edx
L1:
movl (%edx), %eax
addl 4(%edx), %eax
movl %eax, 8(%edx);
addl $4, %edx

loop L1
ret

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 33


Convention du C
Formulation du problème
La fonction printf(…) prend un pointeur vers une chaine de caractères comme paramètre et l’affiche
.data
p_int: .ascii "%d\n\0"
IT: .int 4
F: .int 0, 1, 0, 0, 0, 0 F: .int 0, 1, 1, 2, 3, 5
.text
.global main

main:
movl IT, %ecx
movl $F, %edx
L1:
movl (%edx), %eax
addl 4(%edx), %eax
movl %eax, 8(%edx);
addl $4, %edx

loop L1
ret

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 34


Convention du C
Formulation du problème
Si la chaine de caractère contient le formattage "%d", la fonction printf(…) peut prendre un 2e paramètre…
.data
p_int: .ascii "%d\n\0"
IT: .int 4
F: .int 0, 1, 0, 0, 0, 0 F: .int 0, 1, 1, 2, 3, 5
.text
.global main

main:
movl IT, %ecx
movl $F, %edx
L1:
movl (%edx), %eax
addl 4(%edx), %eax
movl %eax, 8(%edx);
addl $4, %edx

loop L1
ret

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 35


Convention du C
Formulation du problème
… un entier qu’elle affiche à la console
.data
p_int: .ascii "%d\n\0"
IT: .int 4
F: .int 0, 1, 0, 0, 0, 0 F: .int 0, 1, 1, 2, 3, 5
.text
.global main

main:
movl IT, %ecx
movl $F, %edx
L1:
movl (%edx), %eax
addl 4(%edx), %eax
movl %eax, 8(%edx);
addl $4, %edx

loop L1
ret

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 36


Convention du C
Formulation du problème
On modifie le programme en ajoutant les lignes suivantes
.data
p_int: .ascii "%d\n\0"
IT: .int 4
F: .int 0, 1, 0, 0, 0, 0 F: .int 0, 1, 1, 2, 3, 5
.text
.global main

main:
movl IT, %ecx
movl $F, %edx
L1:
movl (%edx), %eax
addl 4(%edx), %eax
movl %eax, 8(%edx);
addl $4, %edx
pushl 4(%edx)
pushl $p_int
loop L1
call printf
ret addl $8, %esp

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 37


Convention du C
Exercice 5
En ajoutant les lignes pour afficher les valeurs 1, 2, 3, 5, le programme affiche 0 à l’infini. Que se passe-t-il?
.data
p_int: .ascii "%d\n\0"
IT: .int 4
F: .int 0, 1, 0, 0, 0, 0 F: .int 0, 1, 1, 2, 3, 5
.text
.global main

main:
movl IT, %ecx
movl $F, %edx
L1:
movl (%edx), %eax
addl 4(%edx), %eax
movl %eax, 8(%edx);
addl $4, %edx
pushl 4(%edx)
pushl $p_int
loop L1
call printf
ret addl $8, %esp

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 38


Convention du C
Exercice 5
En ajoutant les lignes pour afficher les valeurs 1, 2, 3, 5, le programme affiche 0 à l’infini. Que se passe-t-il?
.data
p_int: .ascii "%d\n\0"
IT: .int 4
F: .int 0, 1, 0, 0, 0, 0 F: .int 0, 1, 1, 2, 3, 5
.text
.global main

main: Réponse:
movl IT, %ecx
movl $F, %edx
La fonction printf peut
L1: avoir modifié %ecx, qui
movl (%edx), %eax
addl 4(%edx), %eax
sert de compteur de
movl %eax, 8(%edx); boucle à loop. Il faut le
addl $4, %edx sauvegarder d’abord.
pushl %ecx
pushl 4(%edx)
loop L1
pushl $p_int
ret call printf
addl $8, %esp
popl %ecx
Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 39
Convention du C
Exercice 6
En sauvegardant le registre ecx avant d’appeler printf, le programme affiche un 1 puis 3 zéros. Que se passe-t-il?
.data
p_int: .ascii "%d\n\0"
IT: .int 4
F: .int 0, 1, 0, 0, 0, 0 F: .int 0, 1, 1, 2, 3, 5
.text
.global main

main: Exécution
movl IT, %ecx
movl $F, %edx
L1: $> ./a.out
movl (%edx), %eax 1
addl 4(%edx), %eax
movl %eax, 8(%edx);
0
addl $4, %edx 0
pushl %ecx
pushl 4(%edx) 0
loop L1
pushl $p_int
ret call printf
addl $8, %esp
popl %ecx
Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 40
Convention du C
Exercice 6
En sauvegardant le registre ecx avant d’appeler print, le programme affiche un 1 puis 3 zéros. Que se passe-t-il?
.data
p_int: .ascii "%d\n\0"
IT: .int 4
F: .int 0, 1, 0, 0, 0, 0 F: .int 0, 1, 1, 2, 3, 5
.text
.global main

main: Réponse:
movl IT, %ecx
movl $F, %ebx
La fonction printf peut
L1: avoir modifié %edx. Il faut
movl (%ebx), %eax
addl 4(%ebx), %eax
soit le sauvegarder, ou
movl %eax, 8(%ebx); utiliser %ebx à la place.
addl $4, %ebx
pushl %ecx
pushl 4(%ebx)
loop L1
pushl $p_int
ret call printf
addl $8, %esp
popl %ecx
Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 41
Plan de la séance
Introduction à l’assembleur x86 (suite);
Appels de fonction
Convention du C
Instructions UAL et directives;
Multiplication et division
Opérations logiques
Directives

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 42


Multiplication et division
Multiplication non signée
mul source8 # ax  al * source8
mul source16 # dx:ax  ax * source16
mul source32 # edx:eax  eax * source32
Cette notation correspond au
couple de registre eax et edx
Source ne peut pas être immédiat (constante)
CF et OF à 1 si le résultat dépasse la largeur de la source

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 43


Multiplication et division
Multiplication signée
imul source8 # ax  al * source8
imul source16 # dx:ax  ax * source16
imul source32 # edx:eax  eax * source32

Il est possible de spécifier la destination:


imul source, dest # dest  dest * source

Il est possible de multiplier par un immediat (constante):


imul const, source16, dest # dest  const * source16

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 44


Multiplication et division
Exemple 2 .data
unword: .word 20
.text
.global main
main:
mov $3, %ax
mov $5, %bx
mov $10, %dx # la valeur de %dx sera écrasée
mul %bx # dx = 0 : ax = 15 : CF = 0 : OF = 0
mulw unword # dx = 0 : ax = 300 : CF = 0 : OF = 0

mov $255, %bl


mov $2, %al
mul %bl # ax = 1FE16 (ou 51010) : CF = 1 : OF = 1
# (car résultat n’entre pas dans %al)
mov $2, %al # 255 (FF16) sur 8-bits est -1 en signé
imul %bl # ax = 2*-1 = -2 = FFFE16 : CF = 0 : OF = 0
mov $10, %bx
imul %ax, %bx # bx = -20 : CF = 0 : OF = 0
ret

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 45


Multiplication et division
Division non signée
div source8 # al  ax / source8
# ah  ax mod source8
div source16 # ax  dx:ax / source16
# dx  dx:ax mod source16
div source32 # eax  edx:eax / source32
# edx  edx:eax mod source32

Source ne peut pas être immédiat (constante), et edx ne peut pas être source

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 46


Multiplication et division
Division signée
idiv source8 # al  ax / source8
# ah  ax mod source8
idiv source16 # ax  dx:ax / source16
# dx  dx:ax mod source16
idiv source32 # eax  edx:eax / source32
# edx  edx:eax mod source32

Il n’y a pas d’option idiv source, dest

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 47


Multiplication et division
Exemple 3 .data
unword: .word 20
.text
Petite explication pour le cas du .global main
débordement:
Div %bx va résulter en ce qui suit:
main:
- ax <- dx:ax / %bx mov $0, %dx # precaution
mov $78, %ax
(dx:ax a une taille de 32 bit (16bit chaque))
qui sont tous a 1 donc la valeur ici est de
mov $5, %bx
FFFF FFFF que nous essayons de diviser par div %bx # ax = 15 : dx = 3, ((dx#ax)/bx donne 15 reste 3)
bx qui est égale a 2. la résultante de la
division est 7FFF FFFF (équivalent a un
décalage a droite >>1 ) qui se représente
mov $0, %dx # precaution
avec au minimum 32 bits alors que le mov $122, %ax
registre de destination ax ne peut en divw unword # ax = 6 : dx = 2, ((dx#ax)/M16[unword] donne 6 reste 2)
supporter que 16 bits

mov $0xffff, %dx


mov $0xffff, %ax
mov $2,%bx
div %bx # Divide Error (débordement)
ret

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 48


Multiplication et division
Exercice 1
É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: 2021/02/03 INF1600: Architecture des micro-ordinateurs 49


Multiplication et division
Exercice 1 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
# Epilogue n = 3*n + 1;
popl %ebp }
ret # resultat dans %eax
return steps
}

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 50


Multiplication et division
Exercice 1 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 utiliser un registre steps = steps + 1
à la place
if ( n % 2 == 0 )
n = n/2;
else
# Epilogue n = 3*n + 1;
popl %ebp }
ret # resultat dans %eax
return steps
}

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 51


Multiplication et division
Exercice 1 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
# Epilogue n = 3*n + 1;
popl %ebp }
ret # resultat dans %eax
return steps
}

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 52


Multiplication et division
Exercice 1 Réponse….

Écrivez la fonction suivante en assembleur:


count_steps: unsigned int count_steps(unsigned int
# Prologue n){
pushl %ebp Devrait être
movl %esp, %ebp unsigned int steps = 0;
restitué
while( n > 1 ){
movl $0, %ebx # initialise steps steps = steps + 1

if ( n % 2 == 0 )
n = n/2;
# Epilogue else
popl %ebp n = 3*n + 1;
ret # resultat dans %eax }

return steps
}

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 53


Multiplication et division
Exercice 1 Réponse….

Écrivez la fonction suivante en assembleur:


count_steps: unsigned int count_steps(unsigned int
# Prologue n){
pushl %ebp Devrait être
movl %esp, %ebp unsigned int steps = 0;
restitué
pushl %ebx
while( n > 1 ){
movl $0, %ebx # initialise steps steps = steps + 1

if ( n % 2 == 0 )
n = n/2;
popl %ebx else
# Epilogue n = 3*n + 1;
popl %ebp }
ret # resultat dans %eax
return steps
}

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 54


Multiplication et division
Exercice 1 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 )
n = n/2;
movl %ebx, %eax Mettre résultat else
popl %ebx n = 3*n + 1;
# Epilogue dans %eax }
popl %ebp
ret # resultat dans %eax return steps
}

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 55


Multiplication et division
Exercice 1 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;
movl %ebx, %eax sur la pile else
popl %ebx n = 3*n + 1;
# Epilogue }
popl %ebp
ret # resultat dans %eax return steps
}

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 56


Multiplication et division
Exercice 1 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;
Test:
cmp $1, %eax while( n > 1 ){
jbe Fin # quitte si n <= 1 steps = steps + 1

… # corps de boucle On va construire if ( n % 2 == 0 )


la structure de boucle n = n/2;
else
n = 3*n + 1;
}

Fin_boucle: return steps


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

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 57


Multiplication et division
Exercice 1 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;
Test: # teste n > 1 et sort au besoin
while( n > 1 ){
inc %ebx # incrémenter le compte 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: 2021/02/03 INF1600: Architecture des micro-ordinateurs 58


Multiplication et division
Exercice 1 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;
Test: # teste n > 1 et sort au besoin
while( n > 1 ){
inc %ebx # incrémenter le compte steps = steps + 1

# test de parite Structure if/else if ( n % 2 == 0 )


jnz Impair n = n/2;
# n = n/2 else
jmp Fin_boucle n = 3*n + 1;
Impair: }
# n = 3*n + 1
return steps
}
Fin_boucle: # Va vers Test
Fin:
# resultat (steps) est dans %eax

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 59


Multiplication et division
Exercice 1 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;

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


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

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

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 60


Multiplication et division
Exercice 1 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;

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


steps = steps + 1
# test de parite
movl $2, %ecx if ( n % 2 == 0 )
div %ecx %eax est écrasé! n = n/2;
cmp $0, %edx OK si pair! ☺ else
jnz Impair n = 3*n + 1;
Pas OK si impair  }

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

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 61


Multiplication et division
Exercice 1 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;

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


steps = steps + 1
# test de parite
pushl %eax %eax est sauvegardé if ( n % 2 == 0 )
movl $2, %ecx n = n/2;
div %ecx else
cmp $0, %edx n = 3*n + 1;
jnz Impair }

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

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 62


Multiplication et division
Exercice 1 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;

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


steps = steps + 1
# test de parite
pushl %eax if ( n % 2 == 0 )
movl $0, %edx %edx doit être 0 pour n = n/2;
movl $2, %ecx else
div %ecx
effectuer la division! n = 3*n + 1;
cmp $0, %edx }
jnz Impair
… return steps
Fin_boucle: # Va vers Test }
Fin:
# resultat (steps) est dans %eax

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 63


Multiplication et division
Exercice 1 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;

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


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

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

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 64


Multiplication et division
Exercice 1 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;

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


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

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

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 65


Multiplication et division
Exercice 1 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;

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


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

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

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 66


Multiplication et division
Exercice 1 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;

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


steps = steps + 1
# test de parite
jnz Impair if ( n % 2 == 0 )
# n = n/2 n = n/2;
jmp Fin_boucle else
Impair: n = 3*n + 1;
popl %eax }
movl $3, %ecx 3xn+1
mul %ecx return steps
add $1, %eax # n = 3*n + 1 }
Fin_boucle: # Va vers Test
Fin:
# resultat (steps) est dans %eax

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 67
Multiplication et division
Exercice 1 Réponse ☺

Écrivez la fonction suivante en assembleur:


count_steps:
# Prologue pushl %eax
pushl %ebp movl $0, %edx
movl %esp, %ebp movl $2, %ecx
pushl %ebx div %ecx
cmp $0, %edx
movl $0, %ebx # initialise steps jnz Impair
movl 8(%ebp), %eax addl $4, %esp
jmp Fin_boucle
Test: Impair:
cmp $1, %eax popl %eax
jbe Fin # quitte si n <= 1 movl $3, %ecx
mul %ecx
inc %ebx # incrémenter le compte add $1, %eax # n = 3*n + 1
Fin_boucle:
jmp Test
Fin:
movl %ebx, %eax
popl %ebx
# Epilogue
popl %ebp
ret # resultat dans %eax

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 68


Plan de la séance
Introduction à l’assembleur x86 (suite);
Appels de fonction
Convention du C
Instructions UAL et directives;
Multiplication et division
Opérations logiques
Directives

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 69


Opérations logiques
Instructions logiques
and src, dest # souvent utilisé pour forcer des bits à 0
or src, dest # souvent utilisé pour forcer des bits à 1
xor src, dest # souvent utilisé pour inverser des bits ou mettre reg à 0

Ces instructions affectent eFLAGS: OF = 0, CF = 0, SF, ZF, PF

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 70


Opérations logiques
Exemple
.data
nombre: .byte 6
.text
.global main
main:
mov nombre, %al # %al = 6
or $’0’, %al # %al = ‘6’, aurait pu faire add $’0’,%al aussi
and $0xF, %al # %al = 6, prend les 4 bits de poids faible
ret

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 71


Opérations logiques
Instructions de décalage
shr src, dest # dest  dest >> src (décalage logique)
sar src, dest # dest  dest >> src (décalage arithmétique)
shl src, dest # dest  dest << src (décalage logique)
sal src, dest # dest  dest << src (décalage arithmétique, identique à shl)

Ces instructions affectent eFLAGS: CF = dernier bit sorti, SF = changement de signe, ZF, PF

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 72


Opérations logiques
Instructions de rotation
ror src, dest # rotation vers la droite
rol src, dest # rotation vers la gauche
rcr src, dest # rotation vers la droite avec CF
rcl src, dest # rotation vers la gauche avec CF

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 73


Opérations logiques
Exemple
.text
.global main
main:
mov $0b11110111, %al
sar $1, %al # al = 111110112 : CF = 1 : OF = 0
shl $1, %al # al = 111101102 : CF = 1 : OF = 0
shl $5, %al # al = 110000002 : CF = 0 : OF = 0
rol $1, %al # al = 100000012 : CF = 1 : OF = 0

mov $4, %cl


rcl %cl, %al # al = 000111002 : CF = 0

ret

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 74


Plan de la séance
Introduction à l’assembleur x86 (suite);
Appels de fonction
Convention du C
Instructions UAL et directives;
Multiplication et division
Opérations logiques
Directives

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 75


Directives
Directives de remplissage
Remplissage de mémoire
.fill repetitions, nbBytes, valeur(=0)
.skip repetitions, valeur # équivalent à .fill répétitions, 1, valeur
.space # synonyme de .skip

.ascii "HELLO"
.fill 3,2,0xab
'H', 'E', 'L', 'L', 'O', 0, 0xab, 0, 0xab, 0, 0xab, 0, 5, 0, 0, 0, 6
.word 5
|.ASCII | .FILL |.WORD |.LONG |
.long 6

Mise à jour: 2021/02/03 INF1600: Architecture des micro-ordinateurs 76

Vous aimerez peut-être aussi