Assembleur ARM - Université Laval

publicité
Ordinateurs, Structure
et Applications
GIF-1001
Cours 8, Assembleur ARM
ARM, MOV, LDR et ADD
Etienne Tremblay
Université Laval, Hiver 2014
GIF-1001
Cours 8, p.1
Contenu de la présentation
•
•
•
•
•
•
•
•
Comme tout langage de programmation, l’assembleur ARM permet
d’effectuer les opérations suivantes:
Déclarer des variables et leur affecter des valeurs
Effectuer des opérations mathématiques et logiques
Gérer la séquence des opérations avec des énoncés conditionnels
et des boucles
Appeler des fonctions (diviser une tâche en sous-tâches)
Gérer les évènements et les exceptions
Cette présentation présente les deux premiers points. Les autres points
sont vus dans les cours qui suivent.
De nombreux documents sont disponibles sur internet et présentent
l’assembleur ARM en détail (voir les références à la fin).
GIF-1001
Cours 8, p.2
L’assembleur: des instructions en mots
•
•
•
Comme vu dans les cours précédents, le microprocesseur lit et exécute
des instructions. Chaque instruction, en mémoire, est constituée d’un
opcode et de paramètres qui dépendent de l’opcode.
Il est donc possible d’écrire un programme en binaire si on sait comment
représenter les instructions avec des « 0 » et des « 1 ». Toutefois, le
processus est très pénible: qui voudrait écrire 0x23AB435F4EE7832FFA
pour effectuer l’opération « a = b + c »?
Un assembleur est un programme qui traduit des mots, en anglais, dans
un fichier texte, en instructions. Il y a un mot, ou mnémonique, associé à
chaque instruction. Pour effectuer a = b + c, il est beaucoup plus facile
d’écrire:
•
•
•
•
LDR R0, b
LDR R1, c
ADD R2, R0, R1
STR R2, a
; Lire la variable b dans le registre R0
; Lire la variable c dans le registre R1
; Registre R2 = R0 + R1
; Écrire le registre R2 dans la variable a
GIF-1001
Cours 8, p.3
Plus que des instructions en mots
•
Le langage assembleur fait plus que traduire des mots/mnémoniques en binaire. Il
interprète aussi le texte de plusieurs façons:
•
L’assembleur permet d’associer des mots du programmeur à des adresses
de mémoire.
•
L’assembleur permet au programmeur de déclarer des variables et il
gère l’adresse de ces variables à travers les instructions du programme.
•
L’assembleur permet au programmeur d’identifier des fonctions ou des
sections de codes avec des étiquettes (labels). Lorsque l’assembleur
décode un appel de fonction ou un branchement (saut) dans le
programme, il remplace les étiquettes par les adresses ou
déplacements (offset) appropriées.
•
L’assembleur supporte des directives qui lui disent comment placer le code
en mémoire, comment gérer plusieurs fichiers, comment précompiler le code
–modifier le code avant de le traduire en binaire-, et plus. Les directives sont
des mots réservés qui ne génèrent pas de code en binaire, mais dirige la
création du code exécuté.
•
L’assembleur permet d’insérer des commentaires dans le code, ce qui est
plus que nécessaire!
GIF-1001
Cours 8, p.4
Un exemple de programme
NAME
main
;Nom du fichier/module
PUBLIC __iar_program_start
;Rend l'étiquette __iar_program_start disponible pour d'autres fichiers
SECTION .intvec : CODE (2)
;Le texte qui suit doit être assemblé dans la mémoire FLASH
CODE32
;Les instructions qui suivent sont sur 32 bits
__iar_program_start
B
main
;Étiquette __iar_program_start: IAR commence le programme ici
;Saut/Branchement vers l'étiquette main
;MaVarA = MaVarB + MaVarC
main LDR R0, MaVarB
;Lecture de mémoire, met MaVarB, 0x000000BB, dans R0
LDR R1, MaVarC
;Lecture de mémoire, met MaVarC, 0x000000CC, dans R1
ADD R2, R0, R1
;R2 = R0 + R1
LDR R3,=MaVarA
STR R2, [R3]
;Écriture de mémoire, met R2 (MaVarB + MaVarC) dand MaVarA
B main
;Boucle infinie: retour à l'étiquette main
DATA
;Le texte qui suit doit être assemblé comme des constantes en FLASH
MaVarB DC32 0x000000BB
MaVarC DC32 0x000000CC
; Déclaration de MaVarB, sur 32 bits, valeur initiale = 0xBB
;Déclaration de MaVarC sur 32 bits, valeur initiale = 0xCC
SECTION `.noinit`:DATA(2)
;Variables en mémoire RAM!
MaVarA DS32 1
;Déclaration de MaVarA comme une variable de 1*32 bits
END
;Fin du fichier/module
GIF-1001
Cours 8, p.5
Types d’instructions
•
•
•
•
•
•
•
Il y a six types d’instructions dans l’assembleur ARM:
Déplacement de données: Transfert de données ou de constante impliquant
des registres seulement.
Accès à la mémoire: l’instruction, un load ou store, lit ou écrit la mémoire. La
valeur lue est mise dans un registre. La valeur écrite provient d’un registre.
Opération arithmétique: addition, soustraction, multiplication, division et plus.
Les calculs s’effectuent sur des registres et peuvent changer les drapeaux de
l’unité d’arithmétique et de logique (ALU).
Opération logique: ET, OU, NON-OU, OU EXCLUSIF et plus. Les calculs
s’effectuent sur des registres et peuvent changer les drapeaux de l’unité
d’arithmétique et de logique (ALU).
Gestion de la séquence d’instructions: saut et branchements. Peuvent être
conditionnels ou inconditionnels, à des adresses directes ou indirectes.
Comprend les appels de fonctions.
Contrôle du système: Comprend toutes les autres instructions contrôlant le
microprocesseur. Permet de gérer le temps, le format des instructions,
l’exécution en pipeline, les interruptions et plus.
GIF-1001
Cours 8, p.6
Déplacement de Données: MOV
•
•
•
•
•
•
•
•
•
•
•
•
L’instruction MOV Rn, Op1 met l’opérande de type 1 dans le registre visé:
Rn = Op1
Op1 est une opérande de type 1: il s’agit d’une constante ou d’un registre.
S’il s’agit d’un registre, il est possible de faire des décalages de bits
(avec le « Barrel Shifter » de l’ALU) sur la valeur de l’opérande avant de
faire l’affectation. Cinq opérations sont possibles: LSL, LSR, ASR, ROR
et RRX. Ces opérations sont détaillées en Annexe A.
Une constante (immédiate) est toujours précédée du symbole #
Il existe deux options possibles pour MOV: exécution conditionnelle et
changement des drapeaux. L’instruction MOVcc s’exécutera seulement si la
condition décrite par cc est rencontrée (voir prochaine page). L’instruction
MOVS change les drapeaux
Exemples:
MOV R0, #1234
; R0 = 1234
MOV R0, R1
; R0 = R1
MOV R0, R1, ASR #2 ; R0 = R1 / 4
MOVEQ R0, R1
; R0 = R1 seulement si le drapeau Z est 1
MOVS R0, R1
; R0 = R1, change les drapeaux de l’ALU
GIF-1001
Cours 8, p.7
Code de Condition (CC)
•
•
•
Plusieurs instructions s’exécutent si une condition est rencontrée.
Toutes les conditions sont évaluées à partir des drapeaux de L’ALU et
assument que ceux-ci ont été déterminés auparavant. Par exemple, la
condition EQ (equal) assume qu’une soustraction ou comparaison a été faite
avant: si le résultat de l’opération est 0, le drapeau Z sera à 1 et la condition
EQ sera rencontrée.
•
Les drapeaux N (Negative), Z (Zero), C (Carry) et V (Overflow) servent
à évaluer toutes les conditions.
•
Les drapeaux et les conditons à évaluer changent si les nombres
comparés son signés ou s’ils ne le sont pas.
Voici la liste des codes de condition de l’assembleur ARM:
Mnemonic
CS
EQ
VS
GT
GE
PL
HI
HS
Condition
Carry Set
Equal (Zero Set)
Overflow Set
Greater Than
Greater Than or Equal
Plus (Positive)
Higher Than
Higher os Same (aka CS)
Mnemonic
CC
NE
VC
LT
LE
MI
LO
LS
Condition
Carry Clear
Not Equal (Zero Clear)
Overflow Clear
Less Than
Less Than or Equal
Minus (Negative)
Lower Than (aka CC)
Lower or Same
GIF-1001
Cours 8, p.8
Déclaration de variables
•
•
•
Une variable est un nom donné à une adresse de mémoire. Il n’existe pas
d’instruction pour créer ou manipuler des variables. Il n’existe que des
instructions pour manipuler la mémoire.
Les variables sont des créations du langage assembleur afin de faciliter la
création d’un programme: Il est plus facile de retenir un nom qu’une adresse
de mémoire!!!
Avec l’assembleurs de ARM, la syntaxe pour déclarer une variable est:
– nom DSss NombreDeMots pour déclarer une variable/tableau de taille ss ayant
NombreDeMots. Exemple: MaTable DS32 3 réserve 3*32 bits de mémoire à
l’adresse qui sera allouée à « MaTable ».
– nom DCss valeur pour déclarer une constante de taille ss dont la valeur initiale
est valeur et le nom est nom.
• ss peut être 8, 16, 32, B, W, D…
•
•
•
La directive DC sert à un insérer des bytes dans la mémoire ROM du
système. L’adresse de ces bytes est l’adresse de la constante. Il est
possible, si l’on connaît les opcodes et les opérandes des instructions ARM,
décrire un programme avec des DC!
L’assembleur s’occupera de remplacer tous les noms des variables par les
adresses correspondant à ces nom.
Exemples:
–
–
MonInt DC32 0x11223344
MonOctet
DB 0x22
GIF-1001
Cours 8, p.9
Déclaration de variables: Tableaux
•
•
Les tableaux peuvent être vus comme des chaînes de variables.
Une chaîne texte est un exemple de tableau d'octets, chaque
caractère est présenté comme un élément de code ASCII (0 à 255).
Voici quelques exemples de définition d'un tableau de constantes:
a DCB 48h, 65h, 6Ch, 6Ch, 6Fh, 00h
b DCB 'Hello', 0
b est la copie exacte de a. Lorsque le compilateur voit une chaîne
entourée par des guillemets, il la convertit automatiquement en un
ensemble d'octets.
•
Voici quelques exemples de définition d'un tableau de données:
MaTable DS32 8
MaTable2
DS8
Tiré du didacticiel de EMU8086
(MaTable aure 8 mots/int de 32 bits)
64
(MaTable2 aura 64 octets)
GIF-1001
Cours 8, p.10
Accès Mémoire: Load/Store
•
•
•
•
Les accès à la mémoire d’un processeur ARM se font avec deux
instructions: LDR et STR. LDR (LoaD Register) lit la mémoire et met la
valeur lue dans un registre. STR (STore Register) met la valeur d’un registre
dans la mémoire.
Ces instructions ont le format: LDR Rd, Op2 et STR Rs, Op2
– Rd et Rs décrivent le registre de destination ou de source
– Op2 décrit l’adresse de mémoire ou de périphérique visée par
l’instruction. Voir la prochaine acétate pour le détail.
Les symboles « [ x ] » indiquent qu’il s’agit d’une adresse.
Exemples:
– LDR R1, [R2]
;R1 = Mémoire[R2] (l’adresse de mémoire désignée
par R2)
– LDR R1, [R2, #4] ;R1 = Mémoire[R2+4]
– LDR R1, [R2, R3] ;R1 = Mémoire[R2+R3]
GIF-1001
Cours 8, p.11
Opérande de type 2
•
•
•
•
Op2 symbolise tous les modes d’adressage du microprocesseur, c’est-à-dire
toutes les façons permises pour désigner une adresse de la mémoire.
LDR Rd, Op2 se découpe ainsi: LDR Rd, [Rb, Offset]
– Rb est le registre de base
– Offset est soit une constante, soit un registre, soit une opérande de type
Op1 (un regisitre avec des bits décalés –voir précédemment-)
• LDR R0, [R1, #123]
;Offset = constante
• LDR R0, [R1, R2]
;Offset = Registre
• LDR R0, [R1, R2 LSL #2]
;Offset = Op1
Rb et l’Offset s’additonnent toujours pour former l’adresse visée.
Pour faciliter les accès aux tableaux, il est possible de changer le registre de
base (Rb) avant ou après le calcul d’accès à la mémoire (pre-indexing ou
post-indexing). Le symbole “!” indique du pre-indexing. Le post-indexing se
fait en dehors des [].
–
–
LDR R0, [R1, #4]!
LDR R0, [R1], #4
;R0 = Mem[R1 + 4] et R1 = R1 + 4
;R0 = Mem[R1] et R1 = R1 + 4
GIF-1001
Cours 8, p.12
Accès Mémoire: Load/Store Multiple
•
•
•
•
•
•
Les instructions LDM (LoaD Multiple) et STM (Store Multiple) permettent de
lire des mots de mémoire contigus et de mettre les valeurs lues dans
plusieurs registres. Une seule instruction LDM peut remplacer plusieurs
instructions LDR si les adresses visées se suivent.
Les instructions LDM et STM sont utilisés pour lire/écrire des données de
tableaux ou pour sauvegarder/récupérer de l’information sur la pile (voir les
prochains cours).
Comme LDM et STM sont des instructions longues à exécuter par rapport
aux autres instructions, elles sont traitées spécialement lors d’interruptions
ou dans l’exécution en pipeline.
LDM et STM peuvent s’exécuter conditionnellement, avec un mode
d’exécution (comment incrémenter/décrémenter l’adresse entre chaque mot
lu) et permettent de mettre à jour le registre décrivant l’adresse (symbole !).
Syntaxe: LDMccmm Ra{!}, {Liste de registres}, mm = Decrement Before,
Decrement After, Increment Before or Increment After
Exemples:
– STMDB SP!, {R0, R1} ;R0 = Mem[SP-4], R1 = Mem[SP-8], SP = SP-8
– LDMIA SP!, {R0, R1} ;R0 = Mem[SP], R1 = Mem[SP+4], SP = SP+8
GIF-1001
Cours 8, p.13
Accès Mémoire et Variables
•
•
•
Les instrctions LDR et STR sont utilisée avec la syntaxe suivante pour
accéder aux variables:
– LDR Rd, NomDeVariable
;Met la valeur de la variable dans Rd
– LDR Rd, =NomDevariable ;Met l’adresse de la variable dans Rd
Le symbole « = » utilisé dans l’instruction LDR ou STR indique « l’adresse
de ».
L’assembleur traduit la ligne « LDR Rd, NomDeVariable » ou « LDR Rd,
=NomDeVariable » en plusieurs instructions du processeur:
– Toutes les adresses sont sur 32 bits et toutes les instructions sont sur
16 bits ou 32 bits. Une instruction 32 bits ne peut pas contenir un
opcode, un numéro de registre et une adresse de 32 bits…
– Lors d’un LDR R0, MaVar, l’assembleur placera les items suivants en
mémoire:
• L’adresse de MaVar sera en mémoire code, définie comme une constante
• Une instruction LDR Rd, [PC+Offset] mettra l’adresse de MaVar dans Rd. Ici, Offset est
une constante qui dépend de la distance entre l’instruction LDR et l’adresse de MaVar
(constante en code).
• Une autre instruction LDR R0, [Rd] mettra la valeur de Mavar dans R0…
GIF-1001
Cours 8, p.14
Instructions arithmétiques et logiques: principe
•
•
•
•
•
Les opérations mathématiques et logiques fonctionnent avec un registre de
destination et deux opérandes. Le premier opérande est un registre et le
deuxième est un opérande de type Op1 (une constante ou un registre
décalé).
Le format de l’instruction Add, par exemple, est:
– Add Rd, Rs, Op1
Les instructions arithmétiques et logiques changent les drapeaux de l’ALU,
lorsque l’option S est ajoutée (voir registre CSPR du cours 6).
Les instructions arithmétiques et logiques peuvent s’exécuter
conditionnellement.
Exemples:
– ADD R0, R1, R2 ;R0 = R1 + R2
– ADC R0, R1, #123 ;R0 = R1 + 123 + Carry
– MVNS R0, R1
;R0 = ~R1 ; Met à jour les drapeaux
– EORLO R0, R1, R1
;Si LOwer, R0 = R1 XOR R1 = 0
– ORRHI
R0, R1, R2, ASR #1 ; Si HIgher, R0 = R1 OU (R2/2)
GIF-1001
Cours 8, p.15
Exemple: Addition de variables sur 64 bits
NAME
Addition64bits
;Nom du fichier/module; Addition sur 64 bits en little endian
PUBLIC Additonne64Bits
;Rend l'étiquette/fonction Additonne64Bits disponible pour d'autres fichiers
SECTION .intvec : CODE (2)
;Le texte qui suit doit être assemblé dans la mémoire FLASH
CODE32
;Les instructions qui suivent sont sur 32 bits
Additonne64Bits
LDR R0, =MaVarOp1
;Met l'adresse de MaVarOp1 dans R0
LDR R1, [R0]
;Met les 4 octets les moins signification d'Op1 dans R1
LDR R2, [R0,#4]
;Met les 4 octets les plus signification d'Op1 dans R2
LDR R0, =MaVarOp2
;Met l'adresse de MaVarOp2 dans R0
LDR R3, [R0]
;Met les 4 octets les moins signification d'Op2 dans R3
LDR R4, [R0,#4]
;Met les 4 octets les plus signification d'Op2 dans R4
ADDS R5, R1,R3
;R5 = R1 + R3, additionne les octets les moins significatifs et met à jour Carry
ADC R6, R2,R4
;Additionne les octets les plus significatifs avec la retenue
LDR R0, =MaVarRes
;Met l'adresse du résultat dans R0
STR R5, [R0]
;Sauvegarde le résultat: bit les moins significatifs
STR R6, [R0,#4]
;Sauvegarde le résultat: bit les plus significatifs
BX
LR
;Return
DATA
;Le texte qui suit doit être assemblé dans la mémoire FLASH, constantes
MaVarOp1 DCW
MaVarOp2 DCW
0x11111111, 0x22222222
0x33333333, 0x44444444
;Déclaration de l'opérande 1 sur 2 fois 32bits
;Déclaration de l'opérande 2 sur 2 fois 32bits
SECTION `no_init`: DATA (2)
;Le texte qui suit doit être assemblé dans la mémoire RAM
MaVarRes DS32 2
;Déclaration du resultat sur 2 fois 32 bits
END
;Fin du fichier/module
GIF-1001
Cours 8, p.16
Références et exercices
• Références pour l’assembleur
– ARM Architecture Reference Manual, ARMv7-M_ARM.pdf
– ARM, Assembly Langage Programming
http://www.eng.auburn.edu/~nelson/courses/elec5260_6260/AR
M_AssyLang.pdf
– ARM, IAR Assembler
http://supp.iar.com/FilesPublic/UPDINFO/005832/arm/doc/EWA
RM_AssemblerReference.ENU.pdf
GIF-1001
Cours 8, p.17
Annexe 1: Décalage de bits
•
•
•
•
•
LSL, Logical Shift Left, décale les bits vers la gauche et met des zéros à droite. Décaler un bit vers la
gauche équivaut à multiplier par 2. Carry devient égal au bit le plus significatif.
LSR, Logical Shift Right, décale les bits vers la droite et met des 0 à gauche. Décaler un bit vers la
droite équivaut à diviser un nombre non-signé par 2. Carry devient égal au bit le moins significatif.
ASR, Arithmetical Shift Right, décale les bits vers la droite et copie le bit le plus significatif à gauche.
Décaler un bit vers la droite en conservant le bit de signe équivaut à diviser un nombre signé par 2.
Carry devient égal au bit le moins significatif.
ROR, Rotate Right, décale les bits vers la droite et met le Carry à gauche. Carry devient égal au bit le
moins significatif.
RRX, Rotate Right eXtended équivaut à ROR #1.
GIF-1001
Cours 8, p.18
Téléchargement