Premiers programmes⚓︎
VisUAL
Afin de programmer en assembleur, nous allons utiliser le logiciel VisUAL qui est un simulateur de processeur ARM. Il a l'avantage d'être multi-plateforme, simple, plutôt joli et dispose de plusieurs fonctionnalités utiles pour comprendre ce qui se passe.
Le logiciel est disponible dans le dossier du groupe dans Echange
.
Vous pouvez consulter la page de présentation du logiciel et la liste des commandes supportées.
Les processeurs ARM
Le premier processeur ARM a été conçu par Sophie Wilson en 1985.
Les processeurs ARM sont de plus en plus répandus. Ils sont utilisés dans les Raspberry Pi, la Nintendo Switch, les ordinateurs et téléphones Apple ou encore la plupart des smartphones.
En fait, on parle de processeurs ARM, mais ce sont généralement des SoC (System on Chip), c'est-à-dire des systèmes complets (processeur, mémoire, processeurs graphique et sonore). Les SoC sont au programme de Tle NSI.
Pour réaliser ce TP
Il est conseillé de sauvegarder chacun de vos fichiers avec un nom explicite afin de les retrouver facilement.
Ne perdez pas trop de temps à mettre les indentations. Elles sont ajoutées automatiquement lorsqu'on exécute le programme.
Vous pouvez régler l'affichage des valeurs des registres pour qu'elles soient en décimal en allant dans Settings. Ou alors vous pouvez le faire pour chaque registre en cliquant sur Dec
à côté de la valeur.
Un bug sous Windows fait qu'il n'est pas possible d'écrire #
dans le logiciel. Il faut donc utiliser le copier-coller pour les rajouter.
Instructions de base
Syntaxe | Signification | Explication |
---|---|---|
MOV dest, op1 |
dest = op1 |
op1 peut être une valeur immédiate |
ADD dest, op1, op2 |
dest = op1 + op2 |
|
SUB dest, op1, op2 |
dest = op1 - op2 |
|
AND dest, op1, op2 |
dest = op1 et op2 |
Le et est fait bit à bit |
OR dest, op1, op2 |
dest = op1ou op2 |
Le ou est fait bit à bit |
EOR dest, op1, op2 |
dest = op1 xor op2 |
Le xor est fait bit à bit |
dest
etop1
sont des registres (R0
àR12
).op2
peut être un registre ou une valeur immédiate.
Les valeurs immédiates sont toujours précédées d'un #
et peuvent être :
- un entier en base 10 :
#92
- un entier en binaire précédé par
#0b
:#0b00101
- un entier en hexadécimal précédé par par
#0x
:#0xF3
Exercice 1 : exercice 1 de la feuille
Recopier le programme ci-dessous et observer le résultat obtenu en appuyant sur Execute
. Vous pouvez aussi utiliser Step Forwards
pour regarder ce qui se passe étape par étape..
MOV R0, #10
MOV R1, #3
ADD R2, R0, R1
ADD R2, R0, R2
Vous pouvez observer les valeurs des registres à droite de la fenêtre.
Solution
À la fin de l'exécution, R0
vaut 10, R1
vaut 3 et R2
vaut 23
.
Cela correspond au programme Python suivant :
R0 = 10
R1 = 3
R2 = R0 + R1
R2 = R0 + R2
Exercice 2 : exercice 2 de la feuille
Écrire un programme en assembleur correspondant au programme suivant :
a = 9
b = a + 5
c = b - 3
a = b + c
On pourra utiliser R0
, R1
et R2
à la place de a
, b
et c
.
Solution
MOV R0, #9
ADD R1, R0, #5
SUB R2, R1, #3
ADD R0, R1, R2
Tests et bits spéciaux
Après certaines opérations, il y a 4 bits spéciaux qui sont modifiés :
N
vaut 1 si le résultat est négatif et 0 sinon ;Z
vaut 1 si le résultat est nul et 0 sinon ;C
vaut 1 s'il y a une retenue et 0 sinon ;V
vaut 1 s'il y a un dépassement (overflow) et 0 sinon.
Ces bits sont modifiés après les opérations suivantes :
Syntaxe | Signification | Explication |
---|---|---|
CMP op1, op2 |
op1 = op2 ? |
Met à jour NZCV en faisant op1 - op2 |
CMN op1, op2 |
op1 = -op2 ? |
Met à jour NZCV en faisant op1 + op2 |
TST op1, op2 |
Met à jour NZ en faisant op1 et op2 |
|
TEQ op1, op2 |
Met à jour NZ en faisant op1 xor op2 |
On peut par exemple tester la parité d'un nombre en faisant TST op1, #1
.
Les valeurs NZCV
peuvent également être modifiées par les opérations arithmétiques et logiques en rajoutant S
à la fin de l'instruction.
Ainsi :
SUBS R1, R2, #7
Est équivalent à :
SUB R1, R2, #7
CMP R1, #0
Sauts
Les bits spéciaux sont utilisés pour réaliser des sauts. C'est-à-dire qu'au lieu de lire l'instruction suivante, on saute directement à un autre endroit du programme. Ce saut peut servir à aller plus loin ou au contraire à revenir à une ligne précédente. Afin de déterminer à quelle ligne aller, on place des labels dans le programme. Pour faire un saut, on indique à quel label on veut aller.
Syntaxe | Signification | Explication |
---|---|---|
B label |
Saut inconditionnel | Le saut est toujours exécuté |
BEQ label |
Saut si Z=1 |
Cas d'égalité |
BNE label |
Saut si Z=0 |
Cas d'inégalité |
BPL label |
Saut si N=0 |
Valeur positive ou nulle |
BGE label |
Saut si N=V |
Cas supérieur ou égal |
BGT label |
Saut si N≠V et Z=0 |
Cas strictement supérieur |
BLE label |
Saut si N=V $ et Z=1 |
Cas inférieur ou égal |
BLT label |
Saut si N≠V |
Cas strictement inférieur |
Pour la plupart des opérations arithmétiques et logiques, il est possible d'exécuter l'opération uniquement si un des cas ci-dessus est vérifié, en rajoutant le suffixe correspondant. Par exemple MOVEQ
ne sera exécuté que si Z=1
.
Exercice 3 : exercice 3 de la feuille
-
Recopier le programme suivant et observer le résultat obtenu.
Langage assembleurMOV R0, #10 MOV R1, #3 CMP R0, R1 BGE label2 label1 SUB R2, R1, R0 END label2 SUB R2, R0, R1 END
Vous pouvez utiliser le bouton
Step Forwards
pour exécuter les instructions une par une. Il est aussi possible de placer un point d'arrêt en cliquant juste à droite du numéro d'une ligne. Cela met un point rouge au début de cette ligne. Lors de l'exécution, le programme fera toujours une pause à cet endroit pour que vous puissiez voir la valeur des différents registres.Il faut bien regarder la valeur du registre
PC
qui augmente normalement de 4 après chaque instruction, mais qui fait un saut après l'instructionBGE
.Solution
On peut observer que le programme saute à la ligne
label2
sans passer parlabel1
. C'est parce que on aR0 > R1
et que le saut est effectué si la première des valeurs comparées est supérieure ou égale à la deuxième (BGE
). -
Modifier la deuxième ligne du programme pour passer par le label
label1
.Solution
Il suffit de mettre une valeur strictement plus grande que 10.
Exercice 4 : exercice 4 de la feuille
Écrire un programme en assembleur correspondant au programme Python ci-dessous, en assignant chaque variable à un registre.
x = 4
y = 8
if x == 10:
y = 9
else :
x = x + 1
z = 6
Solution
Il y a deux façons de gérer une instruction conditionnelle. On peut soit décider de continuer l'exécution si la contidion du if
est vérifiée et faire un saut si elle ne l'est pas. Ou alors on fait le saut si la condition est vérifiée et on continue si elle ne l'est pas.
On peut également mettre l'affectation de z
après les deux blocs ou le mettre à la fin du programme en faisant un saut si c'est nécessaire.
MOV R0, #4
MOV R1, #8
CMP R0, #10
BEQ alors ; Saut en cas d'égalité
sinon ADD R0, R0, #1
B fin
alors MOV R1, #6
fin MOV R3, #6
MOV R0, #4
MOV R1, #8
CMP R0, #10
BNE sinon ; Saut en cas de non égalité
alors MOV R1, #6
B fin
sinon ADD R0, R0, #1
fin MOV R3, #6
Exercice 5 : premier exemple de boucle de la feuille
-
Recopier et tester le programme suivant :
Langage assembleurinit MOV R0, #4 ; R0 = 4 MOV R1, #5 ; R1 = 5 MOV R2, #0 ; R2 = 0, le résultat boucle CMP R1, #0 ; Si R1 = 0, on a fini BEQ fin ; On passe à la fin si R1 = 0 ADD R2, R0, R2 ; Sinon, R2 = R2 + R0 SUB R1, R1, #1 ; R1 = R1 - 1 B boucle ; On recommence fin END ; Fin du programme
Vous pouvez remarquer que les commentaires se mettent après un
;
.Vérifier que
R2
est bien égal au produit des valeurs initiales deR0
et deR1
, à condition queR1
soit positif ou nul. -
Compléter le code de la fonction Python
multiplication
qui prend deux entiers positifsa
etb
et qui renvoit le produit deæ
et deb
en utilisant le même algorithme que dans le programme assembleur. Vous ne devez pas utiliser la multiplication.Indices
Indice 1
Ce programme fait une boucle tant qu'une certaine condition n'est pas vérifiée.
Inidce 2
En Python, il faut faire une boucle tant qu'une certaine condition est vérifiée.
Indice 3
Dans le programe, le saut a lieu lorsque que
R1 = 0
.Indice 4
En Python, il faut donc continuer tant que
b > 0
(parce qu'on suppose queb
est positif).Indice 5
Il faut utiliser
while b > 0
.Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)43908.43996.43997.43980.43993.43985.43988.43979.43928.43995.43988.43993.43979.43979.43909.43930.43980.43985.43976.43930.43910.43954.43908.43979.43981.43989.43989.43993.43978.43969.43910.44011.43991.43988.43981.43980.43985.43991.43990.43928.43934.43993.43989.43976.43907.43928.44010.43997.43989.43993.43978.43977.43981.43997.43979.43908.43927.43979.43981.43989.43989.43993.43978.43969.43910.43954.43908.43996.43985.43982.43928.43989.43993.43978.43987.43996.43991.43983.43990.43909.43930.43913.43930.43928.43979.43980.43969.43988.43997.43909.43930.43989.43993.43978.43999.43985.43990.43906.43913.43926.43919.43997.43989.43928.43913.43997.43989.43930.43928.43910.43954.43908.43996.43985.43982.43928.43995.43988.43993.43979.43979.43909.43930.43984.43985.43999.43984.43988.43985.43999.43984.43980.43930.43910.43908.43980.43993.43994.43988.43997.43928.43995.43988.43993.43979.43979.43909.43930.43984.43985.43999.43984.43988.43985.43999.43984.43980.43980.43993.43994.43988.43997.43930.43910.43908.43980.43978.43910.43908.43980.43984.43928.43995.43991.43988.43979.43976.43993.43990.43909.43930.43914.43930.43928.43995.43988.43993.43979.43979.43909.43930.43998.43985.43988.43997.43990.43993.43989.43997.43930.43910.43908.43979.43976.43993.43990.43928.43995.43988.43993.43979.43979.43909.43930.43998.43985.43988.43997.43990.43993.43989.43997.43930.43910.90037.43928.44008.43978.43991.43976.43991.43979.43985.43980.43985.43991.43990.43928.43996.43997.43928.43995.43991.43978.43978.43997.43995.43980.43985.43991.43990.43908.43927.43979.43976.43993.43990.43910.43908.43927.43980.43984.43910.43908.43927.43980.43978.43910.43908.43980.43978.43910.43908.43980.43996.43928.43995.43988.43993.43979.43979.43909.43930.43988.43985.43990.43997.43990.43991.43979.43930.43910.43908.43996.43985.43982.43928.43995.43988.43993.43979.43979.43909.43930.43988.43985.43990.43997.43990.43991.43996.43985.43982.43930.43910.43908.43976.43978.43997.43910.43908.43979.43976.43993.43990.43910.43908.43927.43979.43976.43993.43990.43910.43908.43979.43976.43993.43990.43928.43995.43988.43993.43979.43979.43909.43930.43990.43991.43978.43989.43993.43988.43930.43910.43913.43908.43927.43979.43976.43993.43990.43910.43954.43908.43979.43976.43993.43990.43928.43995.43988.43993.43979.43979.43909.43930.43990.43991.43978.43989.43993.43988.43930.43910.43914.43908.43927.43979.43976.43993.43990.43910.43954.43908.43979.43976.43993.43990.43928.43995.43988.43993.43979.43979.43909.43930.43990.43991.43978.43989.43993.43988.43930.43910.43915.43908.43927.43979.43976.43993.43990.43910.43954.43908.43979.43976.43993.43990.43928.43995.43988.43993.43979.43979.43909.43930.43990.43991.43978.43989.43993.43988.43930.43910.43916.43908.43927.43979.43976.43993.43990.43910.43954.43908.43979.43976.43993.43990.43928.43995.43988.43993.43979.43979.43909.43930.43990.43991.43978.43989.43993.43988.43930.43910.43917.43908.43927.43979.43976.43993.43990.43910.43954.43908.43979.43976.43993.43990.43928.43995.43988.43993.43979.43979.43909.43930.43990.43991.43978.43989.43993.43988.43930.43910.43918.43908.43927.43979.43976.43993.43990.43910.43908.43927.43976.43978.43997.43910.43908.43927.43996.43985.43982.43910.43908.43927.43980.43996.43910.43908.43980.43996.43928.43995.43988.43993.43979.43979.43909.43930.43995.43991.43996.43997.43930.43910.43908.43996.43985.43982.43910.43908.43976.43978.43997.43910.43908.43979.43976.43993.43990.43910.43908.43927.43979.43976.43993.43990.43910.43908.43995.43991.43996.43997.43910.43908.43979.43976.43993.43990.43928.43995.43988.43993.43979.43979.43909.43930.43987.43930.43910.43996.43997.43998.43908.43927.43979.43976.43993.43990.43910.43928.43908.43979.43976.43993.43990.43928.43995.43988.43993.43979.43979.43909.43930.43990.43998.43930.43910.43989.43981.43988.43980.43985.43976.43988.43985.43995.43993.43980.43985.43991.43990.43908.43927.43979.43976.43993.43990.43910.43908.43979.43976.43993.43990.43928.43995.43988.43993.43979.43979.43909.43930.43976.43930.43910.43920.43908.43927.43979.43976.43993.43990.43910.43908.43979.43976.43993.43990.43928.43995.43988.43993.43979.43979.43909.43930.43990.43930.43910.43993.43908.43927.43979.43976.43993.43990.43910.43908.43979.43976.43993.43990.43928.43995.43988.43993.43979.43979.43909.43930.43976.43930.43910.43924.43908.43927.43979.43976.43993.43990.43910.43928.43908.43979.43976.43993.43990.43928.43995.43988.43993.43979.43979.43909.43930.43990.43930.43910.43994.43908.43927.43979.43976.43993.43990.43910.43908.43979.43976.43993.43990.43928.43995.43988.43993.43979.43979.43909.43930.43976.43930.43910.43921.43906.43908.43927.43979.43976.43993.43990.43910.43954.43928.43928.43928.43928.43908.43979.43976.43993.43990.43928.43995.43988.43993.43979.43979.43909.43930.43990.43930.43910.43978.43997.43979.43981.43988.43980.43993.43980.43908.43927.43979.43976.43993.43990.43910.43928.43908.43979.43976.43993.43990.43928.43995.43988.43993.43979.43979.43909.43930.43991.43930.43910.43909.43908.43927.43979.43976.43993.43990.43910.43928.43908.43979.43976.43993.43990.43928.43995.43988.43993.43979.43979.43909.43930.43989.43985.43930.43910.43912.43908.43927.43979.43976.43993.43990.43910.43954.43928.43928.43928.43928.43908.43979.43976.43993.43990.43928.43995.43988.43993.43979.43979.43909.43930.43987.43930.43910.43983.43984.43985.43988.43997.43908.43927.43979.43976.43993.43990.43910.43928.43908.43979.43976.43993.43990.43928.43995.43988.43993.43979.43979.43909.43930.43990.43930.43910.43994.43908.43927.43979.43976.43993.43990.43910.43928.43908.43979.43976.43993.43990.43928.43995.43988.43993.43979.43979.43909.43930.43991.43930.43910.43934.43999.43980.43907.43908.43927.43979.43976.43993.43990.43910.43928.43908.43979.43976.43993.43990.43928.43995.43988.43993.43979.43979.43909.43930.43989.43985.43930.43910.43912.43908.43927.43979.43976.43993.43990.43910.43908.43979.43976.43993.43990.43928.43995.43988.43993.43979.43979.43909.43930.43976.43930.43910.43906.43908.43927.43979.43976.43993.43990.43910.43954.43928.43928.43928.43928.43928.43928.43928.43928.43908.43979.43976.43993.43990.43928.43995.43988.43993.43979.43979.43909.43930.43990.43930.43910.43978.43997.43979.43981.43988.43980.43993.43980.43908.43927.43979.43976.43993.43990.43910.43928.43908.43979.43976.43993.43990.43928.43995.43988.43993.43979.43979.43909.43930.43991.43930.43910.43909.43908.43927.43979.43976.43993.43990.43910.43928.43908.43979.43976.43993.43990.43928.43995.43988.43993.43979.43979.43909.43930.43990.43930.43910.43978.43997.43979.43981.43988.43980.43993.43980.43908.43927.43979.43976.43993.43990.43910.43928.43908.43979.43976.43993.43990.43928.43995.43988.43993.43979.43979.43909.43930.43991.43930.43910.43923.43908.43927.43979.43976.43993.43990.43910.43928.43908.43979.43976.43993.43990.43928.43995.43988.43993.43979.43979.43909.43930.43990.43930.43910.43993.43908.43927.43979.43976.43993.43990.43910.43954.43928.43928.43928.43928.43928.43928.43928.43928.43908.43979.43976.43993.43990.43928.43995.43988.43993.43979.43979.43909.43930.43990.43930.43910.43994.43908.43927.43979.43976.43993.43990.43910.43928.43908.43979.43976.43993.43990.43928.43995.43988.43993.43979.43979.43909.43930.43991.43930.43910.43909.43908.43927.43979.43976.43993.43990.43910.43928.43908.43979.43976.43993.43990.43928.43995.43988.43993.43979.43979.43909.43930.43990.43930.43910.43994.43908.43927.43979.43976.43993.43990.43910.43928.43908.43979.43976.43993.43990.43928.43995.43988.43993.43979.43979.43909.43930.43991.43930.43910.43925.43908.43927.43979.43976.43993.43990.43910.43928.43908.43979.43976.43993.43990.43928.43995.43988.43993.43979.43979.43909.43930.43989.43985.43930.43910.43913.43908.43927.43979.43976.43993.43990.43910.43954.43928.43928.43928.43928.43908.43979.43976.43993.43990.43928.43995.43988.43993.43979.43979.43909.43930.43987.43930.43910.43978.43997.43980.43981.43978.43990.43908.43927.43979.43976.43993.43990.43910.43928.43908.43979.43976.43993.43990.43928.43995.43988.43993.43979.43979.43909.43930.43990.43930.43910.43978.43997.43979.43981.43988.43980.43993.43980.43908.43927.43979.43976.43993.43990.43910.43954.43908.43927.43995.43991.43996.43997.43910.43908.43927.43976.43978.43997.43910.43908.43927.43996.43985.43982.43910.43908.43927.43980.43996.43910.43908.43927.43980.43978.43910.43908.43927.43980.43993.43994.43988.43997.43910.43908.43927.43996.43985.43982.43910.43954.43908.43976.43910.43908.43979.43976.43993.43990.43928.43995.43988.43993.43979.43979.43909.43930.43978.43997.43989.44007.43998.43993.43987.43997.44007.43984.43915.43930.43910.44010.43997.43989.43993.43978.43977.43981.43997.43979.43928.43906.43908.43927.43979.43976.43993.43990.43910.43908.43927.43976.43910.43954.43908.43976.43910.43988.43985.43999.43990.43997.43928.43982.43985.43996.43997.43908.43927.43976.43910.43954.43908.43976.43910.44020.43993.43928.43998.43991.43990.43995.43980.43985.43991.43990.43928.43990.43997.43928.43996.43991.43990.43990.43997.43928.43976.43993.43979.43928.43988.43997.43928.43978.43857.43979.43981.43988.43980.43993.43980.43928.43993.43980.43980.43997.43990.43996.43981.43928.43979.43985.43928.43908.43995.43991.43996.43997.43910.43994.43908.43927.43995.43991.43996.43997.43910.43928.43997.43979.43980.43928.43990.43857.43999.43993.43980.43985.43998.43924.43928.43976.43981.43985.43979.43977.43981.43935.43997.43988.43988.43997.43928.43982.43993.43928.43978.43997.43990.43982.43991.43969.43997.43978.43928.43912.43928.43996.43993.43990.43979.43928.43995.43997.43928.43995.43993.43979.43926.43908.43927.43976.43910.43954.43908.43976.43910.44028.43935.43993.43985.43988.43988.43997.43981.43978.43979.43924.43928.43985.43988.43928.43997.43979.43980.43928.43986.43981.43996.43985.43980.43985.43997.43981.43968.43928.43996.43935.43981.43980.43985.43988.43985.43979.43997.43978.43928.43988.43997.43928.43980.43997.43979.43980.43928.43908.43995.43991.43996.43997.43910.43994.43928.43934.43999.43980.43907.43928.43912.43908.43927.43995.43991.43996.43997.43910.43928.43993.43981.43928.43988.43985.43997.43981.43928.43996.43997.43928.43908.43995.43991.43996.43997.43910.43994.43928.43929.43909.43928.43912.43908.43927.43995.43991.43996.43997.43910.43924.43928.43976.43993.43978.43995.43997.43928.43977.43981.43997.43928.43986.43981.43979.43980.43997.43989.43997.43990.43980.43924.43928.43979.43985.43928.43908.43995.43991.43996.43997.43910.43994.43908.43927.43995.43991.43996.43997.43910.43928.43997.43979.43980.43928.43990.43857.43999.43993.43980.43985.43998.43928.43996.43993.43990.43979.43928.43988.43997.43928.43976.43978.43997.43989.43985.43997.43978.43928.43995.43993.43979.43924.43928.43991.43990.43928.43978.43997.43990.43980.43978.43997.43928.43996.43993.43990.43979.43928.43981.43990.43997.43928.43994.43991.43981.43995.43988.43997.43928.43985.43990.43998.43985.43990.43985.43997.43926.43908.43927.43976.43910.43954.43908.43976.43910.43988.43985.43999.43990.43997.43928.43982.43985.43996.43997.43908.43927.43976.43910.43954.43908.43927.43996.43985.43982.43910.43954.43908.43927.43996.43997.43980.43993.43985.43988.43979.43910
Exercice 6 : exercice 6 de la feuille
Écrire un programme en assembleur correspondant au programme Python ci-dessous, en associant x
avec R0
.
x = 0
while x < 3:
x = x + 1
Indices
Indice 1
En assembleur, il faut continuer tant que R0 < 3
n'est pas vérifié.
Indice 2
Il faut donc faire le saut lorsque R0
est supérieur ou égal à 3.
Indice 3
Il faut utiliser BGE
pour le saut.
Solution
init MOV R0, #0
boucle CMP R0, #3
BGE fin ; On passe à la fin si R0 >= 0
ADD R0, R0, #1 ; Sinon, R0 = R0 + 1
B boucle ; On recommence
fin END ; Fin du programme
Exercice 7 : exercice 7 de la feuille
Recopier le programme ci-dessous et observer le résultat obtenu.
init MOV R0, #16
MOV R1, #3
MOV R2, #0
boucle CMP R0, R1
BLT fin
SUB R0, R0, R1
ADD R2, R2, #1
B boucle
fin END
À quoi correspondent R0
et R2
par rapport aux valeurs initiales de R0
et R1
?
Vous pouvez traduire l'algorithme en Python pour mieux comprendre.
# Tests
(insensible à la casse)(Ctrl+I)
Solution
Ce programme fait la division euclidienne de R0
par R1
. À la fin, R0
est le reste et R2
le quotient.
Dans l'exemple, on fait la division de 16 par 3. Le reste est donc 1 et le quotient 5, car \(16 = 5\times 3 + 1\).
L'équivalent en Python est :
def division(a, b):
reste = a
quotient = 0
while reste >= b:
reste = reste - b
quotient = quotient + 1
return quotient, reste # On peut renvoyer 2 valeurs
>>> division(16, 3)
(5, 1)
>>> division(389, 127)
(3, 8)
# Tests
(insensible à la casse)(Ctrl+I)