Informatique 3 - BFH

Transcription

Informatique 3 - BFH
Haute école spécialisée bernoise
Technique et informatique
Section Electricité et systèmes de communication
Laboratoire d’informatique technique
Informatique 3
Microordinateur
Programmation assembleur
Interface C / Assembleur
© 2008 HESB-TI / Dr E. FIROUZI
Dernier changement :
Auteur :
Version :
Juin 2008
Dr E FIROUZI
3.1
Informatique 3
Avant propos
Avant propos
Ce manuscrit est distribué aux étudiants du module « Informatique 3 » de la section Electricité et système de
communication de la Haute école spécialisée bernoise. Il est complété par des exercices, qui sont distribués en
supplément durant le cours, et un projet, qui est réalisé à la fin du semestre.
La première partie du manuscrit traite la structure d’un microordinateur. Cette partie comprend l’organisation de
la CPU et sa connexion avec les composants externes. La seconde partie du manuscrit introduit la
programmation en assembleur. Cette introduction s’effectue avec des exemples, qui se basent sur un
microcontrôleur RISC à 32 bits : le PXA270 de Intel. La dernière partie du manuscrit traite l’interface C –
assembleur, en se référant aux cours de C (modules informatiques 1 et 2).
Toutes les exercices et le projet sont réalisés avec le kit de développement CARME, qui est introduit au
deuxième semestre.
Des information supplémentaires sont mises à disposition sur le site: http://prof.hti.bfh.ch/fue1
A la fin de ce module, les étudiants sont en mesure de :
1) Concevoir un schéma hardware contenant un microcontrôleur, de la mémoire externe et des composants
périphériques
2) Réaliser un projet en C et assembleur
Un grand remerciement à G. KRUGER et R. WEBER pour définition de la version originale du manuscrit en
allemand ; ainsi qu’à M. MÜHLEMANN et E. STUCKI pour la mise en place de l’environnement de
développement.
Bienne, septembre 2008
E. FIROUZI
Version 3.1, juin 2008
Page I
Informatique 3
Table des matières
Table des matières
1
Architecture d’un microordinateur standard ....................................................................................................1
1.1
Les catégories des ordinateurs................................................................................................................. 1
1.1.1
La classification selon Flynn........................................................................................................... 1
1.1.2
La communication chez les ordinateurs MIMD .............................................................................. 2
1.2
Les architectures des microordinateurs ................................................................................................... 3
1.2.1
L’architecture de Von Neumann ..................................................................................................... 3
1.2.2
L’Architecture de Harvard .............................................................................................................. 4
1.3
La CPU.................................................................................................................................................... 4
1.4
Le système de bus ................................................................................................................................... 5
1.4.1
Les bus d’adresse, de données et de contrôle .................................................................................. 5
1.4.2
Le plan de mémoire......................................................................................................................... 7
1.4.3
Le décodeur d’adresse..................................................................................................................... 8
1.5
La mémoire ............................................................................................................................................. 9
1.5.1
Les technologies.............................................................................................................................. 9
1.5.2
L’organisation de la mémoire........................................................................................................ 10
1.5.3
Les architectures............................................................................................................................ 10
1.5.4
La documentation.......................................................................................................................... 12
1.6
La hiérarchie de la mémoire.................................................................................................................. 13
1.7
La MMU ............................................................................................................................................... 14
1.7.1
Les adresses physiques et virtuelles .............................................................................................. 14
1.7.2
Pages et trames, Tableau de pages ................................................................................................ 15
1.7.3
Les tampons auxiliaires de traduction ........................................................................................... 16
1.8
DMA ..................................................................................................................................................... 17
1.9
La périphérie ......................................................................................................................................... 18
1.9.1
Les amplificateurs de sortie........................................................................................................... 18
1.9.2
Digital Input / Output .................................................................................................................... 19
1.9.3
L’interface sérielle ........................................................................................................................ 20
1.9.4
Le timer ......................................................................................................................................... 25
1.9.5
Les convertisseurs A/D ................................................................................................................. 26
1.9.6
Les convertisseurs D/A ................................................................................................................. 26
1.10 Les types de processeur......................................................................................................................... 27
1.10.1 Les microprocesseurs .................................................................................................................... 27
1.10.2 Les microcontrôleurs..................................................................................................................... 27
1.10.3 Les DSP......................................................................................................................................... 27
1.10.4 CISC / RISC27
1.11 Exemple de famille de microcontrôleur ................................................................................................ 27
1.12 Les critères pour le choix d'un microcontrôleur .................................................................................... 28
2 Le microcontrôleur PXA270..........................................................................................................................30
2.1
L’architecture ARM .............................................................................................................................. 30
2.2
Intel XScale........................................................................................................................................... 33
2.2.1
L’architecture XScale.................................................................................................................... 33
2.2.2
Le coeur d’exécution du XScale ................................................................................................... 34
2.2.3
Le super pipeline du XScale.......................................................................................................... 35
2.3
Le PXA270 de XScale .......................................................................................................................... 37
2.3.1
Les propriétés ................................................................................................................................ 37
2.3.2
Le diagramme de bloc ................................................................................................................... 38
2.4
Les modes de fonctionnement............................................................................................................... 39
2.5
Le modèle des registres......................................................................................................................... 39
2.6
CPSR Current Program Status Register ................................................................................................ 41
2.7
Les bits d’état ........................................................................................................................................ 41
Version 3.1, juin 2008
Page II
Informatique 3
Table des matières
2.8
Les modèles de mémoire et les format de données ............................................................................... 43
2.9
Le plan de mémoire du PXA270........................................................................................................... 44
2.10 Le plan de mémoire du CARME........................................................................................................... 45
2.11 Le schéma des pins................................................................................................................................ 46
2.12 Connexion des composants Flash et SDRAM....................................................................................... 46
2.13 Schéma hardware avec le PXA270 & la mémoire ................................................................................ 48
3 La programmation en assembleur ..................................................................................................................49
3.1
Introduction........................................................................................................................................... 49
3.2
Les niveaux des langages de programmation........................................................................................ 49
3.3
La structure d’un fichier en assembleur ................................................................................................ 50
3.4
La syntaxe assembleur .......................................................................................................................... 51
3.4.1
La structure d’une ligne assembleur.............................................................................................. 51
3.4.2
Les symboles................................................................................................................................. 53
3.4.3
Les constantes ............................................................................................................................... 53
3.4.4
Les opérateurs et les opérandes ..................................................................................................... 54
3.5
L’environnement de développement ..................................................................................................... 55
3.5.1
L’éditeur........................................................................................................................................ 56
3.5.2
L’assembler ................................................................................................................................... 57
3.5.3
Le compilateur .............................................................................................................................. 57
3.5.4
Le relieur / locateur ....................................................................................................................... 58
3.5.5
Le débuggeur................................................................................................................................. 58
3.5.6
La gestion du projet....................................................................................................................... 58
4 Jeu d’instruction du processeur ARM V5 ......................................................................................................60
4.1
Les instructions ..................................................................................................................................... 60
4.1.1
La syntaxe des instructions ARM ................................................................................................. 62
4.1.2
La syntaxe de la notation............................................................................................................... 62
4.1.3
Exécution d’instruction conditionnelle.......................................................................................... 63
4.1.4
Le jeu d’instruction Thumb........................................................................................................... 64
4.1.5
Les coprocesseurs.......................................................................................................................... 65
4.2
La vue d’ensemble du jeu d’instructions............................................................................................... 65
4.3
Les transferts de données ...................................................................................................................... 65
4.3.1
Les instruction de transfert de données entre registres MOV, MVN................................................. 66
4.3.2
Le décalage à barilier (barrel shifter) ............................................................................................ 67
4.3.3
Les instructions de chargement de données LDR et STR ......................................................... 68
4.3.4
Modes d’adressage pour les instructions de chargement et de stockage ....................................... 69
4.3.5
L’instruction SWP.......................................................................................................................... 71
4.3.6
Chargement et stockage multiple LDM et STM .............................................................................. 72
4.3.7
Les instructions de la pile.............................................................................................................. 74
4.3.8
Les instructions d’état MRS et MSR ............................................................................................... 75
4.3.9
Les instructions du coprocesseur LDC, STC, MRC, MCR et CDP ................................................... 76
4.4
Les instructions arithmétiques et logiques ............................................................................................ 77
4.4.1
L’arithmétique des entiers............................................................................................................. 78
4.4.2
Les instruction logiques ................................................................................................................ 81
4.4.3
Les instructions de décalage et de rotation.................................................................................... 82
4.5
Saut de programme ............................................................................................................................... 82
4.5.1
Généralité ...................................................................................................................................... 82
4.5.2
Les sauts de programme inconditionnels ...................................................................................... 83
4.5.3
Les sauts de programmes conditionnels ........................................................................................ 85
4.6
Les autres instructions ARM................................................................................................................. 86
4.6.1
Les interruptions software SWI..................................................................................................... 86
4.6.2
Les points d’arrêt BKPT ................................................................................................................ 87
4.6.3
Le comptage des zéros CLZ .......................................................................................................... 87
5 Les directives de l’assembleur .......................................................................................................................89
Version 3.1, juin 2008
Page III
Informatique 3
Table des matières
5.1
Introduction........................................................................................................................................... 89
5.2
Aperçu................................................................................................................................................... 89
5.3
.arm, .thumb..................................................................................................................................... 90
5.4
.global, .extern ........................................................................................................................... 91
5.5
.align.................................................................................................................................................. 91
5.5.1
.balign ....................................................................................................................................... 92
5.5.2
.p2align.................................................................................................................................... 93
5.6
.ascii, .asciz ................................................................................................................................ 93
5.7
.byte................................................................................................................................................... 94
5.7.1
.2byte, .hword ........................................................................................................................ 94
5.7.2
.word, .4byte .......................................................................................................................... 95
5.8
.space ................................................................................................................................................ 95
5.9
.include ........................................................................................................................................... 96
5.10 .equ, .set, = ..................................................................................................................................... 96
5.11 .org ..................................................................................................................................................... 97
5.12 .section ........................................................................................................................................... 97
5.13 .end ................................................................................................................................................... 101
5.14 Les opérations assembleur .................................................................................................................. 101
5.15 Les structures de contrôle en assembleur ............................................................................................ 102
5.15.1 L’assemblage conditionnel avec .if ......................................................................................... 102
5.15.2 L’assemblage conditionnel avec .ifdef .................................................................................. 103
5.15.3 L’assemblage conditionnel avec .ifndef ................................................................................. 103
5.16 La définition de macro avec .macro................................................................................................. 103
5.17 Les structures de répétitions en assembleur ........................................................................................ 104
5.17.1 La répétition avec .rept ........................................................................................................... 105
5.17.2 La répétition paramétrée avec .irp........................................................................................... 106
6 Les sous routines..........................................................................................................................................107
6.1
Introduction......................................................................................................................................... 107
6.2
Appel et retour de sous routine ........................................................................................................... 107
6.2.1
Appel de sous routine.................................................................................................................. 107
6.2.2
Appel emboîté de sous routine, pile ............................................................................................ 108
6.3
La sauvegarde du contenu des registres .............................................................................................. 111
6.4
Le transfert des paramètres ................................................................................................................. 112
6.4.1
Le transfert de paramètres à l’aide de registre............................................................................. 112
6.4.2
Le transfert de paramètres avec la pile ........................................................................................ 113
6.5
APCS................................................................................................................................................... 114
6.6
Définition de variable locaux .............................................................................................................. 115
6.7
Sources d’erreurs................................................................................................................................. 116
6.8
Comparaison entre sous routine et macro ........................................................................................... 117
7 Les interruptions et les exceptions ...............................................................................................................118
7.1
Introduction......................................................................................................................................... 118
7.2
Les propriétés des interruptions .......................................................................................................... 119
7.3
La priorité des exceptions et les modes du processeur........................................................................ 119
7.4
Les interruptions ................................................................................................................................. 120
7.5
Le masquage des interruptions............................................................................................................ 121
7.6
Le Tableau des vecteurs d’exception .................................................................................................. 122
7.7
Déroulement d’une requête d’interruption .......................................................................................... 123
7.8
Comportement temporel des interruptions .......................................................................................... 125
7.9
Le contrôleur d’interruption du PXA270 ............................................................................................ 126
7.10 Les variante pour le contrôleur d’interruption..................................................................................... 129
8 Les Structures de contrôle en assembleur ....................................................................................................131
8.1
Introduction......................................................................................................................................... 131
Version 3.1, juin 2008
Page IV
Informatique 3
Table des matières
8.2
La ramification simple ........................................................................................................................ 132
8.3
La ramification multiple...................................................................................................................... 133
8.4
La boucle avec évaluation de la condition au début............................................................................ 135
8.5
La boucle avec évaluation de la condition à la fin .............................................................................. 135
8.6
La boucle itérative............................................................................................................................... 136
9 Les structures de données en assembleur .....................................................................................................138
9.1
Introduction......................................................................................................................................... 138
9.2
Les Tableaux unidimensionnels .......................................................................................................... 138
9.3
Les Tableaux multidimensionnels....................................................................................................... 139
9.4
Les chaîne de caractères...................................................................................................................... 140
9.5
Les structures ...................................................................................................................................... 140
9.6
La pile (stack)...................................................................................................................................... 141
9.7
Queues et anneaux de tampons (Queue / Ring buffers) ...................................................................... 142
10
Le démarrage d’un programme C ............................................................................................................145
10.1 Le processus de démarrage d’un programme C .................................................................................. 145
10.2 Le reset................................................................................................................................................ 145
10.3 Le code de démarrage du système (bootloader) .................................................................................. 145
10.4 Le code de démarrage de l’application................................................................................................ 146
10.5 Le programme principale .................................................................................................................... 148
11
L’interface C et assembleur .....................................................................................................................151
11.1 Introduction......................................................................................................................................... 151
11.2 Les appels des sous routines assembleur depuis le C.......................................................................... 151
11.3 Transmission de paramètres aux sous routines assembleur................................................................. 152
11.4 Les registres utilisés par le compilateur .............................................................................................. 152
11.5 L’utilisation de variables en commun ................................................................................................. 152
11.6 L’assembleur en ligne ......................................................................................................................... 153
12
L’adressage des registres en C .................................................................................................................155
12.1 L’adressage avec #define ............................................................................................................... 155
12.2 La définition de sections absolues....................................................................................................... 155
12.3 L’utilisation de mots clés spécifiques du fabriquant ........................................................................... 156
Annexe A: Stockage des nombres........................................................................................................................157
Annexe B: Les format des nombres .....................................................................................................................158
Complément à deux ........................................................................................................................................ 158
Nombre à virgule flottante .............................................................................................................................. 158
Annexe C: La documentation...............................................................................................................................159
Annexe D: Tableau des valeurs ASCII ................................................................................................................160
Index ....................................................................................................................................................................161
Version 3.1, juin 2008
Page V
Architecture d’un microordinateur standard
Informatique 3
1 Architecture d’un microordinateur standard
Ce chapitre traite l’architecture des microprocesseurs et le principe de fonctionnement du matériel (hardware),
qui comprend la CPU (Central Processing Unit), la MMU (Memory Management Unit), le DMA (Direct
Memory Access), la mémoire externe et les composants périphériques. Ce chapitre traite le sujet de manière très
générale, sans distinction entre les différentes familles de CPU.
1.1 Les catégories des ordinateurs
1.1.1 La classification selon Flynn
Selon Michael J. Flynn, les ordinateurs peuvent être répartis en quatre catégories. Cette classification se base sur
la structure des instructions du programme et des jeux de données. En effet, ces derniers peuvent être soit
« simples » ou « multiples ».
SISD
Single Instruction, Single Data
Ordinateur séquentiel
SIMD
Single Instruction, Multiple Data
Ordinateur vectoriel en pipeline
MISD
Multiple Instruction, Single Data
Tableau systolique
MIMD
Multiple Instruction, Multiple Data
Multiprocesseur et multi ordinateurs
Tableau 1 : Les catégories des ordinateurs
SISD:
Les ordinateurs SISD travaillent de façon séquentielle. Ces
derniers traitent un seul jeu de donnée en fonction d’une seule
instruction :
Single instruction veut dire, qu’une instruction est exécutée par
cycle d’horloge.
Single Data veut dire, qu’un jeu de donnée est traité par cycle
d’horloge.
Les ordinateurs SISD sont les ordinateurs les plus répandus,
comme par exemple les ordinateurs personnels (PC) ou les
stations de travail.
Toutefois, avec l’introduction des processeurs multi corps, les
systèmes MIMD seront bientôt plus nombreux.
Version 3.1, juin 2008
t
store C
CPU
load A1
load B1
C1 = A1 + B1
load A2
load B2
C2 = A2 + B2
store C1
store C2
CPU 1
CPU 2
t
SIMD:
Les ordinateurs SIMD permettent d’exécuter la même instruction
sur plusieurs jeux de données. Ces derniers sont utilisés par
exemple pour le traitement des images (JPEG, MPEG).
Single Instruction veut dire, que tous les CPU exécutent la même
instruction à un cycle d’horloge donné.
Multiple Data veut dire, que chaque CPU traite un jeu de donnée
différent.
De nombreux microprocesseur, comme par exemple les PowerPC
ou les x86, possèdent des extensions SIMD avec des instructions
supplémentaires. La CPU peut ainsi traiter simultanément
plusieurs jeux de données, en fonction d’une seule instruction.
load A
load B
C=A+B
Page 1
MISD:
Un seul jeu de donnée est traité simultanément par plusieurs
CPU, avec des instructions différentes.
Multiple Instruction veut dire, que chaque CPU exécute une
instruction différentes.
Single Data veut dire, que chaque CPU traite le même jeu de
donnée.
Les ordinateurs MISD ne sont presque plus utilisés aujourd’hui.
MIMD:
Aujourd’hui presque tous les ordinateurs multiprocesseurs se
basent sur l’architecture MIMD.
Multiple Instruction veut dire, que chaque CPU exécute une
instruction différente par cycle d’horloge. Des programmes
entiers ou des partitions de ces derniers (process, thread, task)
sont souvent répartis entre les différents CPU.
Multiple Data veut dire, que chaque CPU traite un jeu de données
différent.
load A1
load B1
C1 = A1 + B1
load A1
load B1
C2 = A1 * B1
store C1
store C2
CPU 1
CPU 2
load A1
load B1
C1 = A1 + B1
load D
E = func1(D)
F=D/2
store C1
func2()
CPU 1
CPU 2
t
Architecture d’un microordinateur standard
t
Informatique 3
1.1.2 La communication chez les ordinateurs MIMD
Dans les systèmes MIMD, la communication entre les différents CPU s’effectue selon plusieurs principes :
a) Les systèmes fortement couplés (shared memory)
Plusieurs CPU partagent la même zone de mémoire
(shared memory).
Tous les CPU travaillent indépendamment. Mais ils
sont avertis, lorsqu’un CPU accède à une autre zone
de mémoire.
L’accès à la mémoire doit être synchronisé. Car
plusieurs CPU ne peuvent pas accéder simultanément
à la mémoire.
b) Les systèmes faiblement couplés (distributed memory)
Plusieurs CPU communiquent à l’aide d’un réseau.
Les CPU travaillent indépendamment et chaque CPU
possède sa propre zone de mémoire. Les échanges de
données entre les CPU ont lieu à l’aide du réseau.
Ces systèmes peuvent être composés de plusieurs
systèmes SISD, reliés par un réseau.
Mémoire
Bus
CPU 1
CPU 2
CPU 3
Figure 1 : Les systèmes fortement couplés
Réseau
CPU 1
CPU 2
CPU 3
Mémoire 1
Mémoire 2
Mémoire 3
Figure 2 : Les systèmes faiblement couplés
Comparaison entre les systèmes fortement et faiblement couplés :
Les systèmes faiblement couplés sont plus facilement extensibles. L’accès mémoire y est beaucoup plus rapide.
Par contre l’échange des données à travers le réseau est plus lent et plus complexe.
c) Combinaison de systèmes fortement et faiblement couplés :
Aujourd’hui, les ordinateurs les plus rapides sont souvent un mélange de systèmes fortement et faiblement
Version 3.1, juin 2008
Page 2
Informatique 3
Architecture d’un microordinateur standard
couplés. Cela découle des avantages et des désavantages de ces systèmes.
CPU CPU
Mémoire
Mémoire
CPU CPU
CPU CPU
CPU CPU
Réseaux
CPU CPU
Mémoire
Mémoire
CPU CPU
CPU CPU
CPU CPU
Figure 3 : Combinaison de systèmes fortement et faiblement couplés
1.2 Les architectures des microordinateurs
Il existe deux variantes pour le transfert des données entre la CPU et la mémoire : l’architecture de « Von
Neumann » et celle de « Harvard ». Les deux architectures appartiennent à la catégorie des systèmes SISD.
1.2.1 L’architecture de Von Neumann
CPU
Bus pour les instructions et les données
Actuellement, l’architecture de la plus grande partie des ordinateurs est basée sur celle de Von Neumann,
nommé selon le mathématicien hongrois János Von Neumann (1903 – 1957). Dans cette architecture les
instructions du programme, ses structures de données et les composants périphériques partagent la même zone de
mémoire. La CPU accède ainsi aux instructions, aux données et à la périphérie avec un seul system de bus. Par
conséquent, les instructions et les données ne peuvent être chargées que séquentiellement. C'est-à-dire qu’il faut
au moins deux cycles d’horloge pour lire une instruction et les données à traiter.
Mémoire
programme
Mémoire des
données
Périphérie
Figure 4 : Architecture de Von Neumann
La mémoire programme, comme son nom l’indique, contient les instructions du programme. Cette dernière est
en générale non volatile, c’est à dire que son contenu n’est pas perdu lorsque l’alimentation est coupée. Quant à
la mémoire des données, elle contient les variables du programme et est en générale volatile. La CPU lit les
instructions dans la mémoire programme et traite (lecture et écriture) les variables, qui sont stockées dans la
mémoire des données ou les composants périphériques, en fonction de ces dernières.
Le goulot de Von Neumann désigne la limitation du transfert des informations entre la CPU et la mémoire
(programme et données). Ce goulot résulte du système de bus unique.
Version 3.1, juin 2008
Page 3
Architecture d’un microordinateur standard
Informatique 3
1.2.2 L’Architecture de Harvard
Dans l’architecture de Harvard les instructions et les données sont déposées dans deux zones mémoire distinctes.
Dans cette structure deux systèmes de bus (bus des instructions et bus de données) permettent l’accès aux
différentes zones mémoire. Les instructions et les données peuvent ainsi être lues simultanément (c’est à dire en
parallèle). La largeur des buses (instructions et données) peut être différente.
Bus des instructions
Bus de données
Mémoire du
programme
Mémoire des
données
CPU
Périphérie
Figure 5 : L’architecture de Harvard
L’architecture de Harvard est souvent utilisée dans les DSP (Digitale Signal Processor). L’avantage de cette
architecture réside dans la lecture simultanée des instructions et des données du programme. Cette architecture
est donc plus rapide que celle de Von Neumann, mais elle est également plus complexe, ce qui influence
forcément le prix.
Dans les chapitres suivant nous nous limiterons à l’architecture de Von Neumann.
1.3 La CPU
La CPU (Central Processing Unit) est le coeur de l’ordinateur. Il contrôle l’exécution du programme et traite les
données. La Figure 6 illustre la structure générale de la CPU. Cette dernière varie en fonction du type et du
fabriquant de l’ordinateur.
Bus d’adresse
Bus de contrôle
Bus des données
Interface du bus
Register
Program-Counter
Bus interne
Opérande
Instruction
Unit
ALU
Résultat
Unité de contrôle
Unité de calcul
Figure 6 : Structure de la CPU
L’unité de contrôle est responsable de l’exécution du programme. Il est composé des éléments suivants :
• Instruction Unit (dispositif de commande) : Il interprète et exécute les instructions du programme.
Version 3.1, juin 2008
Page 4
Informatique 3
Architecture d’un microordinateur standard
• Program-Counter (PC): Il contient l’adresse de la prochaine instruction du programme à exécuter.
Les tâches de l’unité de contrôle sont les suivantes :
• Chargement des instructions du programme à partir de la mémoire programme (fetch), qui sont adressées par
le compteur de programme.
• Décodage des instructions programme (decode).
• Exécution des instructions programme (execute) en quatre étapes :
− Génération des signaux de contrôle pour l’ALU ou les autres unités de calcul.
− Adressage et chargement des opérandes.
− Stockage du résultat.
− Adaptation du compteur de programme.
L’unité de calcul est responsable du traitement des données. Il contient les composants suivants :
• ALU (Arithmetic Logical Unit), qui exécute les opérations arithmétiques et logiques. L’ALU n’exécute que
des opérations avec des nombres entiers. Pour des instructions à virgule flottante ou des instructions
mathématiques plus complexes on emplois souvent un FPU (Floating Point Unit). Les opérations typiques
sont les suivantes :
− Les opérations de transfert (chargement et stockage)
− Les opérations logiques (AND, OR, EXOR et NON)
− Les opérations arithmétiques (addition, soustraction, multiplication)
− Comparaison et décision (compare et réalise le saut de programme si la condition est réalisée)
− Les opérations de décalage (shift left, shift right)
• Les registres de données, qui sont destinés aux stockages des opérandes et du résultat des opérations
(accumulateur). Un registre est une case mémoire rapide, qui se trouve à l’intérieure du processeur. Ce
dernier peut être accédé directement, c’est à dire sans système de bus, par la CPU.
Le bus interne relie l’unité de contrôle, celle de calcul et l’interface du bus. L’unité de contrôle gère les
opérations, qui doivent être exécutées dans l’unité de calcul. Cette dernière retourne des informations concernant
son état à l’unité de contrôle. L’interface du bus gère la communication avec des composants externes (mémoire
et périphérie).
1.4 Le système de bus
1.4.1 Les bus d’adresse, de données et de contrôle
Différents bus relient la CPU aux composants externes. Ces bus permettent d’échanger des informations
concernant l’adresse et les données. Remarque : ce chapitre se limite à l’architecture de « Von Neumann ».
Version 3.1, juin 2008
Page 5
Architecture d’un microordinateur standard
Informatique 3
Bus de contrôle
Bus d’adresse
CPU
Mémoire
programme
Mémoire des
données
Périphérie
Bus de données
Figure 7: Bus d’adresse, de données et de contrôle
Le bus d’adresse permet de transmettre les adresses (pour la sélection des cases mémoires)
aux composants externes (mémoire et périphérie), qui sont connectés à la CPU. Ces adresses
sont déterminées par l’unité de contrôle de la CPU. Souvent des décodeurs d’adresse
supplémentaire doivent être utilisés, afin de pouvoir sélectionner un des composants externes
(voir chapitre 1.4.3).
Avec qui?
Le bus de données permet de transmettre les instructions et les données du programme. Ces
dernières sont
a) lues par la CPU à partir des composants de stockage externes (RAM ou ROM) ou
périphériques.
b) générées par la CPU et écrites dans les composants de stockage externes ou
périphériques.
quoi?
Le bus de contrôle permet de transmettre des informations supplémentaires pour la gestion de
la communication (read/write, reset, interrupts, requests et acknowledge, handshake etc.).
comment?
Exemple :
Le fonctionnent du système de bus peut être illustré plus en détail, à l’aide d’un transfert de données depuis la
périphérie, en passant par la CPU, à la mémoire des données. Exemple : lecture de la température à l’aide d’une
sonde x (périphérie) et stockage de cette dernière dans la variable "temp", qui se situe dans le RAM. En C cella
serait définie de la manière suivante :
int temp = Temperatur_Sensor_x;
1)
2)
3)
4)
5)
6)
7)
8)
9)
La CPU dépose l’adresse de l’instruction à lire sur le bus d’adresse. Cette adresse est stockée dans le
compteur de programme (Program counter).
La CPU fixe le sens du transfert « lecture », à l’aide du bus de contrôle.
La mémoire programme fournit l’instruction stockée dans la case mémoire, qui est sélectionnée par le bus
d’adresse, sur le bus de donnée.
La CPU lit cette instruction.
La CPU fournit l’adresse du composant périphérique, à partir de laquelle les données doivent être lues, sur
le bus d’adresse.
La CPU fixe le sens du transfert « lecture », à l’aide du bus de contrôle.
La périphérie fournit l’information, contenue dans la case mémoire sélectionnée, sur le bus de données.
La CPU lit les données.
La CPU sélectionne la case de destination « temp » dans la mémoire de donnée, à l’aide du bus d’adresse.
Version 3.1, juin 2008
Page 6
Architecture d’un microordinateur standard
Informatique 3
10) La CPU fournit les données sur le bus de données.
11) La CPU fixe le sens du transfert « écriture », à l’aide du bus de contrôle.
12) La mémoire des données saisit les données sur le bus de données, et les stocke dans la case mémoire
sélectionnée par le bus d’adresse.
Bus
d’adresse
AMP
APE
Bus de
données
AMD
DMP
Bus de
contrôle
DPE
RD
1)
2)
DMD
RD
3)
4)
5)
6)
WR
7)
8)
9)
10)
11)
12)
Figure 8 : Le timing du bus
Les abréviations suivantes ont été utilisées dans la Figure précédente :
AMP :
Adresse de la mémoire programme
APE :
Adresse de la périphérie
AMD : Adresse de la mémoire des données
DMP :
Donnée de la mémoire programme
DPE :
Donnée de la périphérie
DMD : Donnée de la mémoire des données
RD :
Read, lire
WR :
Write, écrire
De plus les notations suivantes illustrent l’état de la tension du bus :
La tension du bus est stable et valable, elle est soit high ou low
La tension du bus n’est pas valable ("don't care")
La tension du bus change
1.4.2 Le plan de mémoire
Le plan de mémoire (memory map) définit les zones de mémoires pour les composants externes : comme par
exemple les mémoires externes (programme et données) ainsi que les composants périphériques. La Figure
suivante montre un plan de mémoire pour une zone d’adressage de 64 kilos bytes :
Version 3.1, juin 2008
Page 7
Informatique 3
Architecture d’un microordinateur standard
Périphérie
Non utilisé
Non utilisé
RAM 2
(8kByte)
RAM 1
(8kByte)
Flash
(32kByte)
Adresse
0xFFFF
0xE000
A15
1
1
A14
1
1
A13
1
1
A12
1
0
0xBFFF
0xA000
0x9FFF
0x8000
0x7FFF
0
1
1
1
1
0
0
0
0
0
0
1
0
1
1
0
0
1
0
1
0
1
0
1
0
Figure 9 : Exemple d’un plan de mémoire avec un bus d’adresse de 16 bits
Les contrôleurs 8 bits (8 bit définit ici la largeur du bus des données) possèdent généralement un bus d’adresse
de largeur 16 bits. Ils sont ainsi en mesure d’adresser une zone de mémoire de 64 kilos bytes (0xFFFF). Quant
aux microcontrôleurs 32 bits, ils possèdent un bus d’adresse de largeur 32 bits et sont ainsi en mesure d’adresser
une zone de mémoire de 232 bytes (4 Giga bytes).
La taille de la mémoire dépend du type du contrôleur. Les contrôleur 8 bits possède en général quelques kilo
bytes de mémoire. Cela est suffisant, car ces derniers sont destinés aux applications relativement simples, qui ne
nécessitent pas de systèmes d’exploitation. Les contrôleurs 32 bits, qui sont destinés aux systèmes embarqués,
nécessitent en générale plusieurs Méga bytes de mémoire.
1.4.3 Le décodeur d’adresse
La tâche du décodeur d’adresse est de sélectionner un des composants externes. Admettons par exemple qu’un
système à microcontrôleur soit composé de plusieurs composants de stockage (RAM et ROM). Dans ce système,
du bus d’adresse ne suffit pas pour sélectionner un des composants. Par conséquent, il faut utiliser des signaux
de sélection (Chip Select, CS) supplémentaires. Ces signaux sont fournis par le décodeur d’adresse en fonction
des bits de poids plus fort du bus d’adresse.
Les décodages d’adresse simples sont réalisés avec de la logique discrète (AND, OR ou 1 of X decoder). Les
composants nécessaires pour réaliser ce genre de décodeur ne sont pas très chers. Toutefois, la logique discrète
nécessite plus de place sur la platine et elle n’est pas flexible. Par conséquent, les erreurs de conception ou les
éventuelles adaptations du plan de mémoire nécessitent souvent une nouvelle platine.
A cause des problèmes de la logique discrète décrits ci-dessus, les décodeurs d’adresse sont souvent réalisés à
l’aide de la logique programmable (GAL, PAL, CPLD etc.). Le décodeur d’adresse correspondant au plan de
mémoire de la Figure 9 peut être réalisé de la manière suivante :
Adresse
Logique
program.
CS0
Flash
CS1
RAM 1
CS2
RAM 2
CS3
Périphérie
Figure 10: Décodeur d’adresse programmable
Les équations logiques permettent de programmer ces décodeurs d’adresse. Par exemple les signaux CS pour le
plan de mémoire de la Figure 9 seraient programmés de la manière suivante :
Version 3.1, juin 2008
Page 8
Architecture d’un microordinateur standard
Informatique 3
CS1
CS2
CS3
CS4
=
=
=
=
/A15
A15 * /A14 * /A13
A15 * /A14 * A13
A15 * A14 * A13
La Figure suivante montre un schéma bloque d’un circuit contenant un décodeur d’adresse ainsi que des
composants de stockages externes et périphériques. Ce circuit contient une Flash de 32 kilos bits, deux RAM de
8 kilos bits et un convertisseur A/D à 1 Byte:
Bus de données
CS4
CS3
Décodeur
d’adresse
CS2
8k * 8
RAM 1
32k * 8
Flash
8k * 8
RAM 2
Périphérie
(convertisseur
A/D de 1 byte)
CS1
A0 .. A15
A0 .. A14
A0 .. A12
A0 .. A12
Bus d’adresse
Figure 11: Schéma bloque du circuit avec le décodeur d’adresse, les composants de stockage (Flash et ROM) et
périphérique
Remarque :
Ce schéma bloque ne contient pas les bits de contrôle /RD et /WR.
Le convertisseur A/D est sélectionné avec le chip select CS4. Du fait qu’il ne possède qu’une seule adresse
physique, il sera reproduit dans toute la zone de mémoire réservée à la périphérie. C'est-à-dire que la CPU peut
l’adresser entre 0xE000 et 0xFFFF.
1.5 La mémoire
1.5.1 Les technologies
Fondamentalement il existe les mémoires non volatiles, qui sont utilisée uniquement en lecture, et les mémoires
volatiles, qui peuvent être utilisées en lecture ou en écriture.
Mémoires non volatiles
Ces mémoires conservent leur contenu, même si leur alimentation est coupée. Les différents types de mémoire
non volatile sont les suivants :
• ROM (Read Only Memory) : Programmation par le fabriquant à l’aide de masques.
• EPROM (Erasable Programmable ROM) : Ces mémoires peuvent être programmées plusieurs fois par
l’utilisateur (outils de programmation spécifique) et effacés à l’aide de rayon UV.
• OTP (ou OTP ROM, One Time Programmable ROM) : Ces mémoires sont construites comme les EPROM,
toutefois sans fenêtre. Les OTP ne peuvent être programmées qu’une seule fois par l’utilisateur.
• EEPROM (Electrical Erasable Programmable ROM) : Ces mémoires peuvent être effacées et reprogrammées
case par case durant leur fonctionnement. Les EEPROM ont une capacité réduite (quelques kilos bytes) et
sont, par conséquent, utilisées pour stocker les données de production, comme par exemple les numéros de
série etc.
Version 3.1, juin 2008
Page 9
Architecture d’un microordinateur standard
Informatique 3
• FLASH (la définition exacte est FLASH EEPROM) : Ces mémoires peuvent être effacés électriquement par
bloque durant leur fonctionnement (pas de possibilité d’effacer uniquement des cases, comme avec les
EEPROM). Les FLASH possèdent une grande capacité de stockage (quelques Mégas bytes) et sont, par
conséquent, souvent utilisées pour stocker le code du programme.
Mémoire volatile
Ces mémoires perdent leur contenu dès que leur alimentation est coupée. Ces mémoires sont en générale
qualifiées de RAM (Random Access Memory). Random veut dire que les cases mémoires peuvent être accédées
de façon aléatoire. Il existe les catégories suivantes :
• DRAM (Dynamic RAM) : Ces mémoires stockent l’information à l’aide de condensateur et doivent, par
conséquent, être rafraîchies périodiquement.
• SRAM (Static RAM) : Ces mémoires possèdent une structure plus complexe que les mémoires DRAM mais,
par contre, elles ne doivent pas être rafraîchies périodiquement. Les SRAM sont plus rapide, nécessitent
moins de courant et sont plus cher que les DRAM.
• SDRAM (Synchronous Dynamic RAM) : Ces mémoire sont une version cadencée des DRAM. La fréquence
d’horloge est prédéfinie par le bus du système. Chez les DDR-SDRAM (Double Data Rate SDRAM), les
accès mémoires sont possibles aux flans montant et aux flans descendants de l’horloge.
Aujourd’hui il est également possible de travailler avec des technologies RAM non volatile (FeRAM, MRAM).
Toutefois, ces dernières possèdent une faible capacité de stockage et sont relativement chères.
1.5.2 L’organisation de la mémoire
Les mémoires sont organisées comme un Tableau, qui contient des cases mémoires. La largeur de ces cases
dépend du type de la mémoire et correspond à 1, 8 ou 16 bits.
La Figure suivante montre la structure d’une mémoire organisée en byte :
Mémoire
Adresse
La plus petite adresse 0
1
7
MSB
0
LSB
~
La plus grande adresse
Byte
0
1
~
n
n
Largeur de la mémoire
(ici byte)
Figure 12 : Structure d’une mémoire organisée en byte
Le nombre de bit d’adresses, qui sont utilisés pour adresser la mémoire, dépend de la taille de la mémoire. Avec
m bits d’adresse, il est possible d’adresser 2m cases mémoires. Par exemple avec 16 bits d’adresses, il est
possible d’adresser un do maire de 64 k (ce qui est souvent utilisé avec de microcontrôleur à 8 bits).
1.5.3 Les architectures
Les mémoires sont organisées de tell façon, que les informations sont stockées dans un Tableau des cases
mémoires (Memory-Matrix). L’adressage des cases mémoires s’effectue à l’aide de décodeur d’adresse. Les
signaux de contrôle comme CS, OE, R/W contrôle les driver du bus.
Architecture d’une ROM :
Version 3.1, juin 2008
Page 10
Architecture d’un microordinateur standard
A0 ..
An
Row-Decoder
Informatique 3
Memory-Matrix
Column-Output
D0 ..
Dn
Column-Decoder
An+1
.. Az
OE
CS
Control
Figure 13 : L’architecture d’un composant ROM
Les composants ROM possèdent typiquement un bus de données de largeur 8 ou 16 bits. La largeur du bus
d’adresse dépend de la capacité de stockage. Les signaux de contrôle sont composés d’un CS (Chip Select) pour
la sélection du composant, d’un OE (Output Enable) pour activer des amplificateurs de sortie du bus de données.
La Figure 13 ne contient que les signaux de contrôle, qui permettent la lecture de la ROM. La programmation
nécessite des signaux de contrôle supplémentaires.
A0 ..
An
Row-Decoder
L’architecture d’une SRAM :
Memory-Matrix
Column-In/Output
D0 ..
Dn
Column-Decoder
An+1
.. Az
OE
CS
Control
R/W
Figure 14 : L’architecture d’un composant SRAM
La structure des composants SRAM est identique à celle des composants ROM. Toutefois, le bus de données est
bidirectionnel, afin que la CPU puisse lire et écrire. Un signal de contrôle supplémentaire (Read/Write) est par
conséquent nécessaire, afin de pouvoir définir le sens de la communication. Certain fabriquant utilise même deux
signaux de contrôle distincts (Read et Write) pour réaliser cette tâche.
L’architecture d’un composant SDRAM
Chez les composants DRAM et SDRAM l’adresse n’est pas fournie entièrement sur le bus d’adresse. En effet,
afin de pouvoir réduire de nombre de pin, cette dernière est fournie en deux étapes : d’abord les adresses
colonnes et ensuite les adresses lignes. Deux signaux de contrôle supplémentaires sont donc nécessaires, afin de
Version 3.1, juin 2008
Page 11
Informatique 3
Architecture d’un microordinateur standard
pouvoir signaliser laquelle de ces adresses est fournie sur le bus d’adresse. Ces signaux sont le RAS (Row
Address Strobe) et le (Column Address Strobe) CAS.
Figure 15 : Diagramme de bloc du SDRAM K4S561633F de Samsung (4M * 16 Bit * 4 Banks)
Le comportement temporel de la lecture d’une SRAM est le suivant :
ADDR
/RAS
/CAS
row address
column address
read row address
disable output driver
read column address
enable output driver
Dout
valid
t access RAM
Figure 16: Le comportement temporel de la lecture d’une SDRAM
1.5.4 La documentation
Les caractéristiques les plus importantes des composants de stockage sont décrites dans la documentation, qui est
fournie par le fabriquant. Ces dernières sont typiquement:
• La taille de la mémoire (kilo bit ou kilo byte)
• Assignation des pins
• Organisation de la mémoire (bit, byte ou mot)
• Les caractéristiques DC (tension, consommation de courant ...)
• Les caractéristiques AC (temps d’accès ...)
• Table de vérité (logique de contrôle)
Version 3.1, juin 2008
Page 12
Architecture d’un microordinateur standard
Informatique 3
1.6 La hiérarchie de la mémoire
Chaque technologie de stockage possède ses avantages et ses désavantages. Par conséquent les composants de
stockage sont organisés de façon hiérarchique :
CPU
Prix par bit
Temps d’accès
Capacité
Register
Élevé
Faible
Faible
Faible
Élevé
Élevé
Cache
Mémoire de travail
Mémoire de masse
Figure 17 : Hiérarchie des composants de stockage
Les registres :
Les registres sont des cases mémoire très rapide, destinées au stockage des opérandes et du résultat de l’ALU. La
CPU peut accéder directement aux registres, c’est à dire sans passer par le système de bus (voir également
chapitre 1.3).
La mémoire cache :
La mémoire cache est une mémoire intermédiaire, qui se situe entre les registres et la mémoire de travail. Cette
mémoire rapide est destinée au stockage des instructions (Instruction-Cache) et des données (Data-Cache) du
programme, qui doivent être utilisées souvent.
Les CPU actuelles sont en mesure de travailler à des fréquences d’horloge supérieures à celles de leurs systèmes
de bus. En d’autres thermes, le temps d’accès à la mémoire de travail est supérieur aux cycles d’horloge interne
du processeur, et représente souvent le talent d’Achille des systèmes à microprocesseur. Par conséquent, lorsque
la CPU lit les instructions ou les données à partir de la mémoire de travail, elle les dépose également dans la
mémoire cache. Si ces données doivent être réutilisées, elles seront chargées automatiquement à partie de la
mémoire cache au lieu de la mémoire de travail. Ce procédé est transparent plus l’utilisateur, c'est-à-dire que le
contrôle la mémoire cache est effectué par le hardware.
On parle d’un « Cache Miss », lorsque des données ne sont pas disponibles dans la mémoire cache. Ces données
seront alors lues à partir de la mémoire de travail et stockées dans un « Cache Line », dont la taille est
typiquement de quelques bytes. Lorsque la mémoire cache est pleine, les « lignes de cache » existantes doivent
être sur écrites.
On parle d’un « Cache Hit », lorsque des données à charger sont disponibles dans la mémoire cache. L’accès à
ces données est plus rapide que si elles devaient être lues à partir de la mémoire de travail.
Les mémoires cache possèdent typiquement une taille de 100 kilos bytes. Toutefois, seul les microprocesseurs
puissants possèdent une telle mémoire.
Les mémoires caches peuvent être échelonnées. Le premier échelon est alors une mémoire cache interne, plus
petite mais très rapide (L1). Le second échelon est une mémoire RAM externe, plus grande mais moins rapide
(L2).
La mémoire de travail :
La mémoire de travail est destinée au stockage des instructions (Flash) et des données (SRAM et SDRAM) du
programme (voir également chapitre 1.5).
Dans le monde des ordinateurs personnels (PC), le code est copié depuis la mémoire de masse dans la RAM, et il
est exécuté à partir de cette dernière.
Dans le monde des systèmes embarqués, le code est exécuté soit à partir de la Flash ou il est copié depuis la
Version 3.1, juin 2008
Page 13
Architecture d’un microordinateur standard
Informatique 3
Flash dans la RAM, durant le processus de démarrage (boot), et est exécuté ensuite à partir de cette dernière.
La mémoire de masse :
Les mémoires de masse, comme par exemple les disques dures ou les CD, ne sont pas utilisées dans les systèmes
embarqués. Par contre, ces dernières sont souvent employées dans les PC industriels. Toutefois, il ne faut pas
oublier les désavantages de la mécanique dans les environnements industriels (la température, les vibrations,
l’humidité, la poussière etc.). Par conséquent, on préfère utiliser ici les cartes CF, les cartes SD ou les mémoires
sticks en tant que mémoire de masse.
1.7 La MMU
Die MMU (Memory-Management Unit) est une unité hardware destinée à la gestion de la mémoire. Les
avantages du MMU apparaissent essentiellement avec les systèmes d’exploitation. Avec les processeurs 32 bits,
la MMU est souvent intégrée sur le même chip que celui de la CPU.
La MMU met à disposition les fonctionnalités suivantes :
1. Protection des segments de mémoire des différents programmes : Un système d’exploitation peut ainsi
exécuter plusieurs programmes simultanément. La MMU empêche qu’un programme puisse accéder au
segment de mémoire d’un autre programme. Cette fonctionnalité est très importante pour les systèmes
embarqués, car elle permet d’augmenter leur sécurité.
2. La mémoire de masse peut contenir plus de code que la mémoire de travail. Le code à exécuter est toujours
copié depuis la mémoire masse dans la mémoire de travail. Le code, qui n’est pas utilisé, sera ainsi sur écrit.
Par conséquent, les données, qui ne sont pas utilisées temporairement, doivent être sauvées sur la mémoire de
masse (swapping). Ces fonctionnalités sont importantes dans le domaine de la bureautique, ou de nombreux
programmes sont à disposition sur la mémoire de mass. Par contre, elles ne sont pas importantes dans les
systèmes embarqués.
1.7.1 Les adresses physiques et virtuelles
Les adresses virtuelles ou logiques désignent les adresses, qui sont attribuées au programme par le compilateur /
relieur et qui sont utilisées durant l’exécution du programme dans la CPU. Ainsi il est possible d’exécuter
plusieurs programmes en parallèle, qui possèdent tous une adresse virtuelle de base 0.
Les adresses physiques désignent les adresses, qui sont fournies sur le bus d’adresses durant l’exécution du
programme (adresses physiques des composants).
Æ Le programme et la CPU travaillent avec des adresses virtuelles. Les accès aux composants de
mémoire s’effectuent avec des adresses physiques.
Processeur
CPU
CPU fournit une
adresse virtuelle
Mémoire
de travail
Mémoire de
masse
Peripherie
MMU
MMU fournit une
adresse physique pour
accéder à la mémoire
Bus
Figure 18: La MMU entre la CPU et la mémoire
La tâche du MMU est de transformer l’adresse virtuelle en une adresse physique ou de réallocation (relocation).
Version 3.1, juin 2008
Page 14
Informatique 3
Architecture d’un microordinateur standard
Pour obtenir l’adresse physique, la MMU additionne l’adresse virtuelle à la valeur qui est contenue dans les
registres de réallocation (relocation register). Simultanément il contrôle si l’accès au segment est autorisé ou non,
à l’aide des registres de limitation.
Le fonctionnement du MMU peut être schématisé de la manière suivant :
Limit
register
CPU
Programm
jes
<
Virtual
address
Relocation
register
Work
memory
+
Physical
address
no
Address error
Trap
MMU
Figure 19 : Schéma bloc simplifié du MMU
Lorsque l’on passe d’un programme à un autre, il faut recharger les registres de réallocation et de limite. Ce qui
est la tâche du système d’exploitation. Chez les processeurs, qui ne possèdent pas de MMU, Les adresses
virtuelles correspondent aux adresses physiques.
1.7.2 Pages et trames, Tableau de pages
La zone de mémoire virtuelle est partagée en blocs de tailles identiques, qui sont appelé « pages ». La zone de
mémoire physique est également partagé en blocs de tailles identiques, qui sont appelé « trames ». La taille des
pages et des trames dépend des systèmes et se situe entre 512 bytes à 16 Méga bytes.
Des Tableaux de pages sont utilisés pour convertir les adresses virtuelles en adresses physiques. Les adresses
virtuelles sont composées des champs suivants :
1. Le numéro de la page, qui indique l’index du Tableau de pages. Le Tableau de pages contient l’adresse de
base de chaque trame (adresse physique).
2. Un offset de page, qui est additionné au contenu du Tableau de pages (adresse de base) pour construire
l’adresse physique.
Version 3.1, juin 2008
Page 15
Architecture d’un microordinateur standard
Informatique 3
Adresse physique
0
1 0 0 0 0 0
Numéro de trame = 2
obtenu du tableau de
page
Tableau
de page
Numéro de page = 4
correspond à
l’indexe du tableau
de page
0
15
14
13
12
000
000
11
10
9
8
7
6
5
111
000
4
3
2
1
0
000
000
101
000
100
000
011
010
110
000
001
000
0 0
0 0 10
0 0
0
0
0
1
0
1
0
1
0
1
0
1
1
1
0
1
0
010
bit de
validité
Offset
1 0 0 0 0 0 0 0 0 0 0 10 0 0 0
Adresse virtuelle
Figure 20 : MMU avec 16 pages de 4 k bytes
La Figure de l’exemple de ci-dessus montre, que les zones de mémoire virtuelles peuvent être plus grandes que
les zones de mémoire physiques. Le bit de validité indique si le contenu du Tableau de pages est valide ou pas.
Si ce n’est pas le cas, les données doivent d’abord être copiées depuis la mémoire de masse dans la mémoire de
travail.
1.7.3 Les tampons auxiliaires de traduction
Les Tableaux de pages peuvent devenir très grand, en fonction de la taille des pages et du volume de mémoire
qu’ils représentent. D’un autre côté, les programmes utilisent relativement peu ces Tableaux (boucle, Tableaux
etc.).
Le calcul des adresses physique peut être optimisé à l’aide des tampons auxiliaires de traduction (Translation
Look aside Buffers abrégé en TLB). Ces derniers sont également intégrés dans la MMU. Le TLB est un Tableau
contenant 8 à 64 entrées, qui correspondent aux entrées des Tableaux de pages.
Version 3.1, juin 2008
Page 16
Architecture d’un microordinateur standard
Informatique 3
Numéro de la
Page (virtuel)
Trames
(physique)
22
54
60
52
36
18
632
320
Validité
modification
protection
1
1
1
1
0
1
0
0
rwx
r x
rw
rw
Tableau 2 : Exemple de demande pour le TLB
Le TLB contient des informations sur les pages : numéro de la page, trame, bit de validité, bit de modification
(montre si le contenu d’une trame a été modifié et, par conséquent, si ce contenu doit être sauvé avant son
élimination) et bits de protection (droit d’accès sur une trame donnée).
Le processus de la conversion de l’adresse virtuelle en une adresse physique est le suivant : D’abord la MMU
contrôle si la page recherché existe dans le TLB. Pour cela la demande est comparée avec les numéros de page
du TLB. Lorsqu’il y a correspondance (TLB hit), le numéro de la trame est lu directement à partir du TLB.
Lorsqu’il n’y a pas de correspondance (TLB miss), la MMU continue la recherche avec le Tableau de pages.
Finalement une demande est choisie dans le TLB et est remplacée avec le numéro de la page, contenu dans le
Tableau de pages. Le TLB contient par conséquent tous les numéros de pages, qui ont été utilisés récemment.
Adresse virtuelle
CPU
Numéro
Offset
Page
Frame
Number Number
TLB hit
TLB
Page
Frame
Number Number
Numéro
Offset
Mémoire
Adresse physique
TLB miss
Page Table
Figure 21 : MMU avec un Tableau de pages et un TLB
1.8 DMA
L’accès direct à la mémoire (Direct Memory Access abrégé par DMA) est un procédé, qui permet de transférer
rapidement les données entre la mémoire de masse, ou les composants périphériques, et la mémoire de travail.
Un contrôleur DMA est nécessaire pour cela.
Sans le contrôleur DMA, les transferts des données entre la périphérie et la RAM doivent passer par la CPU.
Dans ce cas, ce dernier doit gérer les adresses source, les adresses de destination et les registres tampons. Ce
transfert doit bien entendu être programmé et nécessite, par exemple, plusieurs cycles de bus pour ne transférer
Version 3.1, juin 2008
Page 17
Architecture d’un microordinateur standard
Informatique 3
qu’un mot. Ce qui a tendance de fortement ralentir les transferts.
I/O
I/O
Mémoire
CPU
Figure 22 : Transfert de données à travers la CPU
Le contrôleur DMA permet de transférer les données sans que ces derniers passent par la CPU. La CPU est alors
découplé du bus, afin que contrôleur DMA puisse reprendre le contrôle de ce dernier. La tâche de la CPU se
limite dans ce cas à l’initialisation du contrôleur DMA (adresse source, adresse destination et quantité de
données).
I/O
I/O
CPU
Mémoire
Contrôleur
DMA
Figure 23 : Transfert de donnée avec le DMA
1.9 La périphérie
Les composants suivant sont considérés comme périphériques :
a) Les composants qui permettent d’accéder aux données de l’environnement du système. Ces données sont lues
avec des senseurs ou d’autre type d’interfaces.
b) Les composants qui permettent de transmettre les données à l’environnement du système. Ces données sont
transmises avec des actuateurs ou d’autres types d’interface.
La périphérie représente l’interface entre le processeur et son environnement. Les composants périphériques sont
en général connectés au bus du processeur.
1.9.1 Les amplificateurs de sortie
Les signaux de sortie d’un chip, qui sont fournis à l’aide des pins, doivent être amplifiés. Il existe différents
types d’amplificateur de sortie, dont le choix dépend de l’application.
Version 3.1, juin 2008
Page 18
Architecture d’un microordinateur standard
Informatique 3
Port
Out
Port
Out
D
Port
Out
G
Totem-Pole
Open Drain
Tri state
Figure 24 : Amplificateur de sortie
Les étages totem pole
Les étages totem pole fournissent toujours un signal à leur sortie. Par conséquent, ils ne peuvent pas être
connectés en parallèle !
a) La logique low est représentée le plus souvent par « 0 »
b) La logique high est représentée le plus souvent par « 1 »
Open Drain
Les sorties Open Drain (avec la technologie FET) ou Open Collector (avec la technologie bipolaire) possèdent
un seul transistor, qui permet de tirer une résistance (Pull-up) contre la masse. Les résistances pull-up peuvent
être sois internes ou externes. Les sorties Open Drain et Open Collector peuvent être connectées en parallèle,
comme par exemple avec les sources d’interruption :
Pull
up
Source
d’interrup.
1
Source
d’interrup.
2
Source
d’nterrup.
3
IRQx
Figure 25 : Source d’interruption avec des sorties Open Drain
Tri state
Les sorties tri state peuvent avoir un état à haute impédance. L’état de sortie active ou « tri state » est activée à
l’aide d’un signal de contrôle supplémentaire (G).
En générale les sorties, qui fournissent des signaux sur un bus, sont réalisées avec des tri states, comme par
exemple les entrées et sorties des données (I/O) d’une RAM.
1.9.2 Digital Input / Output
Les entrées et sorties digitales sont utilisées respectivement pour la lecture et l’écriture des signaux digitales. Il
existe deux possibilités pour fournir des entrées sorties digitales :
1) Utilisation de pins du microcontrôleur, appelés GPIO. Le nombre de ces pins varie en fonction de la famille
des microcontrôleurs. L’accès à ces derniers s’effectue à l’aide de registres.
2) Utilisation de composants périphériques supplémentaires (FPGA, PIO, …), qui mettent à disposions des I/O.
La communication avec ces composants s’effectue avec le système de bus.
Les entrées et sorties digitales sont utilisées pour connecter les éléments d’affichage (lampes, LED etc.), les
relais, les moteurs, les soupapes etc.
Les sorties digitales possèdent souvent un étage d’amplification, afin qu’elles puissent fournir le courant
nécessaire à la transmission (ex. contrôle des moteurs, des soupapes etc.). Les entrées digitales possèdent
souvent des filtrés (circuit RC et trigger de Schmitt). Elles sont également protégées contre les sur tensions
Version 3.1, juin 2008
Page 19
Architecture d’un microordinateur standard
Informatique 3
(comme par exemple à l’aide de diodes Transzorb et des varistances).
Contrôleur de
moteur
Microcontrôleur
Motor
GPIO1
GPIO2
Interrupteur
…
Protection
d’entrée
Figure 26 : Exemple d’utilisation de GPIO
1.9.3 L’interface sérielle
Les interfaces sérielles sont utilisées pour transmettre des données de façon sérielle (ex. RS232, I2C, SPI,
FireWire, USB etc.). Un registre à décalage est nécessaire pour convertir les données, depuis le format parallèle
en séquence de bits, afin de pouvoir réaliser la transmission.
Les propriétés les plus important de la transmission sérielle sont les suivants :
• Le nombre de bit par seconde (baud rate)
• La tension
• Le protocole
TxD
RxD
Sende-Schieberegister
Steuersignale
Empfangs-Schieberegister
Control-Register
CPU
Figure 27: Principe de fonctionnement d’une interface sérielle
1.9.3.1 RS232
L’interface RS232 est très importante dans le domaine des systèmes embarqués. Cette interface permet par
exemple de gérer un affichage LCD ou une ligne de commande (Command Line Interface). La plupart des
microcontrôleurs possèdent déjà une interface RS232. Toutefois, les tensions de sortie de ces dernières
correspondent au niveau TTL. Par conséquent, un convertisseur de tension externe doit être ajouté au système.
Les interfaces RS232 sont accessibles à l’aide de registres.
• Les tampons de transmission et de réception, contiennent 1 byte. Les deux tampons possèdent souvent la
même adresse, car il n’est possible que d’écrire dans le tampon de transmission et de lire à partir du tampon
de réception.
• Les registres de contrôle, qui permettent de définir les modes de fonctionnement (la fréquence de
Version 3.1, juin 2008
Page 20
Informatique 3
Architecture d’un microordinateur standard
transmission (baud rate), le format des données, le bit de parité etc.) et les interruptions.
Les interfaces RS232 soutiennent différents modes de fonctionnement. Par exemple ils peuvent fonctionner soit
en mode synchrone ou en mode asynchrone. La fréquence de transmission est souvent définie avec un timer
standard. Certaine interface RS232 possèdent toutefois leur propre générateur de fréquence. Le timer peut ainsi
être utilisé pour d’autres applications.
Le schéma bloc de l’interface RS232 est typiquement le suivant :
Transmitter
Transmit FIFO
Transmit Holding Register
TxD
Internal Bus
Transmit Shifter
Control
Unit
Baudrate
Generator
Receiver
Receive Shifter
RxD
Receive Holding Register
Receive FIFO
Figure 28 : Schéma bloc de l’interface RS232 du microcontrôleur C515C
(Source: Manuel d’utilisation du C515C)
1.9.3.2 SPI
L’interface SPI (Serial Peripheral Interface) est un système de bus sériel à haut débit, destiné à la communication
entre le microcontrôleur et la périphérie. Ce dernier est souvent utilisé pour la communication avec des
extensions I/O, des affichages LCD ainsi que des convertisseurs A/D et D/A. Il peut également être utilisé pour
la communication entre microcontrôleurs.
La Figure 29 montre le principe de fonctionnement du SPI.
Version 3.1, juin 2008
Page 21
Architecture d’un microordinateur standard
Informatique 3
Générateur de la
fréquence d’horloge
Entré des données
en parallèle
7
Entré des données
en parallèle
0
7
Sortie des données
en parallèle
0
Sortie des données
en parallèle
Participant 1
Participant n
Figure 29 : Principe du SPI
L’interface SPI est toujours utilisée en mode maître esclave. Le maître est alors responsable de la génération de
la fréquence d’horloge. Le SPI peut travailler de façon duplexe à l’aide de deux lignes de transmission : MOSI
(Master Out Slave In) et MISO (Master In Slave Out). Les esclaves peuvent être connectés soit de façon
parallèle (c’est à dire que toutes les sorties des esclaves sont rassemblée et connectées à l’entré MISO du maître)
ou de façon sérielle (la sorite d’un esclave est connectée à l’entrée du prochain esclave et la sortie du dernier
esclave est connecté à l’entrée MISO du maître).
Le microcontrôleur écrit les données à transmettre dans un tampon de transmission. Ces dernières sont
sérialisées à l’aide d’un registre à décalage (comme une transmission RS232). Les données reçues sont
également converties à l’aide d’un registre à décalage. Le microcontrôleur peut alors lire ces données de façon
parallèle dans le tampon de réception. Du fait que les interfaces SPI ont une bande passante relativement élevé,
les tampons de transmission et de réception contiennent souvent plusieurs bytes.
Donnée
Donnée
Registre à
décalage
Registre à
décalage
Esclave SPI 2
Esclave SPI 1
MOSI
MISO
SCK
Sélection
esclave
SPI maître
Registre à
décalage
Horloge
FIFO de
réception
FIFO de
tansmission
Figure 30 : SPI avec un maître de deux esclaves
Version 3.1, juin 2008
Page 22
Informatique 3
Architecture d’un microordinateur standard
1.9.3.3 I2C
Le bus I2C (Inter Integrated Circuit) a été développé par l’entreprise Philips. Ce bus est utilisé pour connecter
les composants périphériques comme l’ EEPROM, les affichages LCD ou RTC (Real Time Clock) au
microcontrôleur.
Le bus I2C est composé de deux fils, ce qui réduit la partie hardware de façon drastique. Ce bus comprend une
ligne d’horloge SCL (Serial Clock) et une ligne de donnée SDA (Serial Data). La communication est par
conséquent synchrone. Les modes d’utilisation du bus sont maître et esclave.
La Figure suivante illustre une application typique avec le bus I2C :
Figure 31 : Application avec un bus I2C
Le protocole est défini de la manière suivante:
Figure 32 : Le maître (transmetteur ) adresse l’esclave (récepteur) avec une adresse composé de 7 bits et envoi 2
bytes de données
Le transfert de données entre le maître et l’esclave s’effectue de la manière suivante :
1. Le maître démarre le transfert des données en envoyant le bit de démarrage. Tous les esclaves entrent
ainsi dans un état passif d’écoute.
2. Le maître envoie ensuite l’adresse de l’esclave, avec lequel il aimerait communiquer. Cette adresse est
composée de 7 bits.
3. Le maître envoi le bit R/W, qui fixe le sens de la communication : Ecriture depuis le maître à l’esclave ou
lecture depuis l’esclave au maître
4. Le protocole I2C exige des confirmations (acknowledge) après chaque transmission d’un byte. L’esclave
accrédite avec le premier bit de confirmation, qu’il est prêt pour la communication.
5. Le transfert de données a lieu entre le maître et l’esclave. Un bit de confirmation est également échangé ici
après chaque transmission d’un byte. Ce bit est fourni par le maître dans le mode lecture et par l’esclave
dans le mode écriture.
6. Le transfert se termine avec un bit d’arrêt.
Le nombre de bytes à transmettre et le sens de la transmission peuvent varier selon les composants utilisés. Ces
informations sont fournies par documentation de ces derniers. Par exemple : le maître n’écrit qu’un byte dans
un convertisseur D/A. Alors qu’avec une EEPROM, qui possède une zone de mémoire interne, le maître doit
d’abord envoyer l’offset de la case mémoire à accéder. Le transfert de données n’est effectué qu’ensuite,
jusqu'au bit d’arrêt.
Version 3.1, juin 2008
Page 23
Architecture d’un microordinateur standard
Informatique 3
Le Tableau suivant illustre quelques exemples de transmission de données avec l’interface I2C (le bit
confirmation n’est pas affiché) :
Composant
Convertisseur
D/A
Démarrage
Ecriture RAM
Démarrage
Lecture RAM
Démarrage
Adresse
de
l’esclave
Adresse
de
l’esclave
Adresse
de
l’esclave
Wr
Données
Protocole
Arrêt
Wr
Données
Données
Arrêt
Wr
Données
Arrêt
Démarrage
Adresse
de
l’esclave
Rd
Données
Figure 33 : Exemple pour le protocole I2C
Le protocole I2C est défini au niveau électrique de la manière suivante :
Niveau de pause :
Le niveau de pause est high.
Condition de démarrage :
La condition de démarrage est définie par un flanc descendant sur SDA, suivi d’un flanc descendant sur SCL. Ce
signal est univoque et n’apparaître pas durant une transmission normale.
Condition d’arrêt:
La condition d’arrêt est définie par un flanc montant sur SCL, suivi d’un flanc montant sur SDA. Ce signal est
également univoque et n’apparaît par durant une transmission normale.
SDA
SCL
Start
Stop
Figure 34 : Condition de démarrage et d’arrêt
Les bits de données :
La valeur du signal SDA est fixée en fonction du bit à transmettre : 0 = low, 1 = high. La validité est signalée
avec un flanc montant du signal SCL. La lecture et l’écriture des bits de données ont toujours lieu pendant que le
signal SCL est haut.
ACK :
Le bit de confirmation (Acknowledge) veut dire que la réception est a été bonne ou que le récepteur est prêt pour
des transmissions supplémentaires. Du point de vu du maître, l’esclave doit confirmer chaque byte écrit. Du
point de vu de l’esclave, le maître doit confirmer chaque byte lu. Si ces confirmations n’ont pas lieu, le processus
de transmission sera rompu avec le bit d’arrêt.
NACK :
Not Acknowledged signal une erreur de transmission ou la fin de la disposition à recevoir.
Version 3.1, juin 2008
Page 24
Arrêt
Architecture d’un microordinateur standard
Informatique 3
SDA
1
0
0
1
0
1
1
1
SCL
Start
Slave-Adressse
R/W
ACK
Stop
Figure 35: Transmission au niveau bit
Dans la Figure 35, le maître envoi en premier la condition de démarrage, ensuite il envoi l’adresse de l’esclave
(1001011) et pour finir le bit R/W. L’esclave doit signaler sa présence avec le bit de confirmation. Il est
important que le maître maintienne le SDA à un état haute impédance durant cette phase. Les données peuvent
être transmis après le bit de confirmation (cela n’est pas montré dans la Figure). La communication est
interrompue avec le bit d’arrêt.
Admettons que l’on veut connecter un émetteur à plusieurs participants avec un bus I2C. Dans ce cas tous les
participants doivent se mettent dans un état à haute impédance. Certain microcontrôleur peuvent conFigurer leurs
sorties en tri state. Si cela n’est pas possible, il faut conFigurer les pins SCL et SDA en entrée.
1.9.4 Le timer
Le timer est utilisé comme base de temps dans les processeurs (système d’exploitation, horloge etc.) ou pour les
composants externes (ex. signal PWM, horloge pour les interfaces sérielles ...).
Oscillateur
Timer
Mode
Entrée
externe
Timer / Counter
Register
Overflow
Flag
Counter
Figure 36 : Principe de fonctionnement du timer
En générale des registres de 8 ou 16 bits sont utilisés dans les timers ou les compteurs. Dans le mode timer, ces
registres sont incrémentés périodiquement à l’aide de l’horloge interne du système. Dans le mode compteur,
cette incrémentation s’effectue en fonction de signaux externes.
Lorsqu’il y dépassement de capacité (c'est-à-dire au passage de 0xFFFF à 0 avec un registre de 16 bits), le
drapeau (flag) d’overflow est mis à un. Ce dernier peut être observé à l’aide d’une boucle software (polling) ou il
peut générer une interruption.
Le mode « de rechargement automatique» (auto reload) permet d’initialiser le registre du timer avec une valeur
prédéfinie, qui est contenue dans le « registre de rechargement » (reload register). Ce qui permet de générer des
signaux avec des périodes variables.
Version 3.1, juin 2008
Page 25
Informatique 3
Architecture d’un microordinateur standard
Oszillator
Timer
Register
Overflow
Flag
Reload
Reload
Register
Figure 37: Timer dans le mode de rechargement automatique
Dans le mode de rechargement automatique, il n’y a pas seulement une mis à un du flag overflow, mais le
compteur du timer est également initialisé avec la valeur du registre de rechargement.
1.9.5 Les convertisseurs A/D
Les convertisseurs A/D mesurent une tension analogique à leur entrée, comparent cette tension avec des tensions
de référence, et en fournissent l’équivalent digital à leur sortie. Le microcontrôleur peut lire cette valeur soit avec
un système de bus ou avec un interface sériel (comme par exemple le SPI).
Les convertisseurs A/D possèdent souvent plusieurs entrées analogiques, qui peuvent être sélectionnées à l’aide
d’un multiplexeur.
Les caractéristiques les plus important pour un convertisseur A/D sont les suivants :
• Largeur de bit (les valeurs typiques sont 8, 10, 12 ou 16 bits)
• Temps de conversion
Analog Inputs
MUX
VREF
S&H
Control-Register
A/D
Converter
Data-Register
CPU
Figure 38 : Principe d’un convertisseur A/D
1.9.6 Les convertisseurs D/A
Les convertisseurs D/A lisent une valeur digitale à leur entrée, convertissent cette valeur en une tension
analogique et fournissent cette dernière à leur sortie.
Les caractéristiques les plus important pour un convertisseur D/A sont les suivants:
• Largeur de bit (les valeurs typiques sont 8, 10, 12 ou 16 bits)
Version 3.1, juin 2008
Page 26
Informatique 3
Architecture d’un microordinateur standard
• Temps de conversion
La conversion D/A peut être également effectuée avec une sortie PWM, qui est connectée à un filtre passe bas.
1.10 Les types de processeur
Un processeur est un chip qui contient au minimum un CPU. Il existe plusieurs sorte de processeurs : les
microprocesseur, les microcontrôleur et les DSP. Dans les chapitres suivants l’expression processeur représente
tous les types de processeur.
1.10.1 Les microprocesseurs
Un microprocesseur contient uniquement une unité de contrôle et une unité de calcul. Tous les composants de
stockage et périphériques sont externes. Par conséquent, ils ne sont accessibles qu’avec le système de bus.
1.10.2 Les microcontrôleurs
Les microcontrôleurs sont conçus essentiellement pour les applications de contrôle et sont, par conséquent,
optimisés au niveau du coût. En plus de la CPU, ils contiennent également de la mémoire interne, pour le
stockage des instructions et des données du programme, ainsi que des modules périphériques (en fonction de la
famille des microcontrôleurs).
1.10.3 Les DSP
Les DSP sont conçus pour les applications de traitement du signal digital, qui nécessitent des puissances de
calcul élevées. Ils sont utilisés pour l’exécution d’algorithmes complexes (ex filtrage, transformation de Fourier
etc.). Un DSP contient toujours un module pour la multiplication. Une opération de multiplication et d’addition
peut ainsi être effectuée simultanément, en un seul cycle d’horloge. L’architecture des DSP est normalement
celle de Harvard.
1.10.4 CISC / RISC
RISC et CISC sont des notions différentes pour définir les jeux d’instructions. Elles sont utilisées autant avec les
microprocesseurs qu’avec les microcontrôleurs.
Complex Instruction Set Computer (CISC): Les instructions peuvent être relativement complexes. Une seule
instruction assembleur est subdivisée en une séquence de micro instructions. L’exécution d’une instruction
nécessite donc plusieurs cycles d’horloge. Le micro programme est intégré par le fabricant. Par conséquent,
l’utilisateur n’y a pas d’accès.
Reduced Instruction Set Computer (RISC): Les instructions sont relativement simples. Il n’y a pas se micro
instructions et les instructions sont exécutées directement.
1.11 Exemple de famille de microcontrôleur
Les sections suivantes décrivent les familles de microcontrôleur les plus répandues.
Les microcontrôleurs se distinguent par leur puissance de calcul et par leurs modules périphériques tel que :
• Mémoire (ROM / Flash, RAM, EEPROM)
• GPIO
• Timer
• Interface sérielle
• Convertisseur A/D
Version 3.1, juin 2008
Page 27
Informatique 3
Architecture d’un microordinateur standard
• PWM
• CAN
• USB
Le Tableau suivant fournit un aperçu des familles de microcontrôleur.
Famille
8051
Description brève
La famille 8051 est la famille la plus connue et la plus répandue des contrôleur 8 bits.
Plusieurs fabricants fournissent des dérivées de ce microcontrôleur, qui se distinguent par
leurs modules périphériques. Le 8031 de INTEL est considéré ici comme le précurseur.
PIC
Le PIC est une famille de contrôleur de 8, 16 et 32 bits de Microchip. Il est utilisé avant tout
dans les applications à bas prix et à basse consommation.
68HCxx
Les familles 8 bits de Motorola 68HC05, 68HC08 et 68HC11 sont très répandues dans
l’industrie et dans l’enseignement. Cependant, elles ne sont plus très utilisées dans les
nouvelles applications.
MC683xx
Le contrôleur 32 bits de Motorola se base sur la CPU32. Les registres de la CPU ont une
largeur de 32 bits. En fonction du contrôleur, le bus de données peut contenir 16 à 32 bits et
le bus d’adresse 24 à 32 bits. Ces contrôleurs sont utilisés pour des applications, qui
nécessitent des puissances de calcul moyennes, comme la télécommunication et l’industrie
automobile. La famille est construite de façon modulaire et contient plusieurs membres.
Cette famille est remplacée dans les nouvelles applications par celle du ColdFire.
ColdFire
La famille des ColdFires remplace celle des MC683xx de Motorola. ColdFire est un
processeur de 32 bits pur, c. à d. qu’il contient des bus d’adresse et de données de 32 bits.
Les processeurs ColdFire possèdent la même architecture que ceux 683xx. Toutefois, ils
sont plus puissants que leurs prédécesseurs.
ARM
La société ARM propose des cœurs divers, qui sont fabriqués sous licence par différentes
compagnies. ARM est une abréviation pour Advanced RISC Machine. Actuellement les
familles ARM7 et ARM9 (tous deux à 32 bits) sont très répandues dans le domaine des
contrôleurs embarqués. Ces contrôleurs fournissent une bonne puissance de calcul pour une
consommation relativement basse.
MSP430
Le MSP40 est une famille de contrôleur du type RISC à 16 bits, produite par TI. Il est
utilisé avant tout dans les applications à consommation ultra basse (ex. les appareils à
batteries).
AVR, SAM
Différentes familles de contrôleur de la compagnie Atmel comme AVR (processeur 8 bits
RISC), AVR32 (architecture 32 bits avec un DSP et la fonctionnalité SIMD) ou AT91SAM
(contrôleur très bon marché qui se base sur l’architecture ARM7). Ces contrôleurs ont une
grande croissance dans le domaine de l’électronique embarqué.
Tableau 3 : Différents familles de microcontrôleur
1.12 Les critères pour le choix d'un microcontrôleur
Plusieurs critères jouent un rôle plus ou moins important dans le choix d’un processeur. Le poids de ces critères
peut varier en fonction du projet :
• Puissance de calcul (MIPS, FLOPS)
• Largeur de bus (Bus de données et d’adresse, registres CPU)
• Consommation électrique
• Prix
Version 3.1, juin 2008
Page 28
Informatique 3
Architecture d’un microordinateur standard
• Disponibilité de deuxième source
• Composants périphériques (Timer, UART etc.)
• Carte d’évaluation et support du développement
L’expérience du développeur et la disponibilité d’environnement de développement et de test jouent souvent un
rôle non négligeable.
Version 3.1, juin 2008
Page 29
Informatique 3
Le microcontrôleur PXA270
2 Le microcontrôleur PXA270
La première partie de ce chapitre traite les différentes versions de l’architecture ARM. La seconde partie décrit le
digramme de block et le modèle des registres du microcontrôleur PXA270 de Intel. Ce chapitre se limite
toutefois aux tâches, qui sont prioritaires pour la programmation de ce dernier. Les tâches plus spécifiques sont
fournies dans les manuels d’utilisateur Intel [1] à [8] ou par la littérature spécialisée [10] ou [11].
2.1 L’architecture ARM
Les processeurs ARM ont été développés (entre 1983 et 1985) par la société Acorn Computers Limited à
Cambridge (Angleterre). C’était la première utilisation commerciale d’un processeur RISC. La société ARM
Limited (Advanced RISC Machines Limited) a été créée en 1990, afin de continuer de développer cette
technologie.
Les microprocesseurs, qui sont basés sur l’architecture ARM, sont actuellement très répondus. Les raisons en
sont multiples :
• Architecture commune
• Puissance de calcul élevée
• Faible consommation (typiquement moins d’un Watt)
• Coût réduit
Les domaines d’utilisation sont les suivants :
• Les systèmes embarqués (téléphone mobile, PDA, les tâches de contrôle)
• Les applications en relation avec la sécurité
• Plateforme pour différents systèmes d’exploitations
Les caractéristiques les plus importantes de l’architecture ARM sont les suivantes :
• Les caractéristiques typiques de l’architecture RISC :
− Un grand banc de registre à 32 bits
− Architecture « Load / Store », car les opérandes doivent être copiées dans les registres. La CPU ne peut
pas traiter les données, qui sont stockées dans de la mémoire.
− Les instructions sont orthogonales
− Adressage simple à l’aide des registres standard
− Trois modes d’adressage
− La longueur des instructions est fixe (32 bits). Ce qui simplifie le décodage des instructions.
• Les propriétés typiques de l’architecture ARM:
− Une instruction unique permet d’utiliser l’ALU avec le « barrel shifters » (shift left / right)
− Incrémentations et décrémentations automatiques des différents modes d’adressages
− Opérations « Load / Store » simultanées pour plusieurs registres
− Exécution conditionnelle des instructions (conditional execution)
− Les types de données byte (8 bits), halfword (16 bits) et word (32 bits)
− Les jeux d’instructions ARM à 32 bits, Thumb à 16 bits et Jazelle. Ce dernier est prévu pour l’exécution
du code byte Java
• L’ARM possède un système de traitement des interruptions simple et efficace, avec des bancs de registres
fantômes. Ces derniers sont mis à disposition pour les différents types d’exception, qui sont les suivants :
− Les interruptions rapides
− Les interruptions normales
− Memory abort (pour la MMU et la protection de la mémoire)
− Exécution d’une instruction non définie
− Les interruptions software
Version 3.1, juin 2008
Page 30
Informatique 3
Le microcontrôleur PXA270
• Les registres d’état : L’état actuel du processeur est stocké dans le registre « Current Program Status Register
(CPSR) » (voir chapitre 2.6):
− 4 bits d’état
− 2 bits pour la désactiver les interruptions
− 5 Bits pour le mode du processeur
− 1 bit pour le mode ARM ou Thumb
ARM propose plusieurs versions d’architecture. Les nouvelles versions sont compatibles avec les anciennes. Ces
dernières mettent à disposition de nouvelles instructions et de nouvelles fonctionnalités hardware. Chaque
version d’architecture est déclinée en différentes familles, qui à leur tour possèdent différents cœurs (Core). Le
Tableau suivant en fournit un aperçu :
Version 3.1, juin 2008
Page 31
Le microcontrôleur PXA270
Informatique 3
Architecture
ARM
v1 (1983)
v2
v3 (1991)
v4
v4T
v5TE (1999)
v5TEJ (2000)
v6 (2001)
v7
Brève description
Famille / Coeur
Première version de l’architecture ARM de Acorn Computers,
basée sur la CPU 6502.
Adressage à 26 bits
Pas de multiplication et de co-processeur
Premier chip commercial,
Adressage à 26 bits, bus de données à 32 bits, multiplication
fournissant un résultat à 32 bits,
architecture simple : 30'000 transistors, basse consommation, v2
ne possède pas de mémoire cache, v2a est la première version
avec une mémoire cache,
soutient le co-processeur
Première version de ARM Limited.
Processeur indépendant ou intégré dans un CPU en tant que
cellule macro.
On-Chip-Cache, MMU, adressage à 32 bits, les registres CPS et
SPS sont séparés.
35'000 transistors.
La version V3M soutient les instructions « MultiplyAccumulate », fournissant un résultat de 64 bits.
La plus vieille architecture ARM, qui est encore soutenue
aujourd’hui.
Nouvelle instructions pour charger et stocker des demi mots
signés et non signés (16 bits) ainsi que des bytes signés.
Introduction du mode système.
V4 possède pour la première fois d’une définition formelle.
Nouveau format comprimé à 16 bits (Thumb) des jeux
d’instruction.
ARM1
Amélioration des instructions Thumb.
Nouvelles instructions, comme par exemple BLX, CLZ et BRK.
Extension du jeux d’instruction pour le traitement du signal
(support DSP) de la version E, comme par exemple les instruction
à cycle unique 16*16 et 16*32 MAC.
Introduction de la technologie Jazelle, pour exécuter de façon
optimale le code byte Java.
Cela est plus rapide qu’une machine virtuelle Java (Java Virtual
Machine) implémenté en software.
Soutient des environnements multiprocesseurs. Instruction
multimédia qui soutiennent le SIMD, comme par exemple le
MPEG4.
TrustZone : partage de l’espace d’adressage physique dans une
partie sure et un partie non sure.
6 nouveaux bits d’état (GE [3:0], bit E, bit A).
Trois profiles de processeur sont soutenus :
A : Les applications pour utilisateur générales
R : Système temps réel
M : Serial Wire Debug (SWD) pour les microcontrôleur et les
application bas coûts, afin de réduire le nombre de Pins.
Version améliorée du jeu d’instruction Thumb.
ARM2
ARM6, ARM600,
ARM610,
ARM7, ARM700,
ARM710
StrongARM, ARMS,
ARM810
ARM7TDMI,
ARM710T, ARM740T,
ARM9TDMI,
ARM920T, ARM940T
XScale,
ARM9E-S,
ARM10TDMI,
ARM1020E
ARM926EJ,
ARM1026EJ
ARM1136J,
ARM1156T2
Coretex-M3, Coretex-R4,
Coretex-A8
Tableau 4 : Aperçu des architectures ARM
Divers familles de processeur ARM sont proposées pour une version d’architecture donnée (Par exemple :
ARM7, ARM9, ARM10 etc.). Au sein d’un famille il existe plusieurs cœurs (Par exemple : ARM7TDMI,
Version 3.1, juin 2008
Page 32
Le microcontrôleur PXA270
Informatique 3
ARM740T). La nomenclature pour ces derniers est la suivante :
ARM{x}{y}{z}{T}{D}{M}{I}{E}{J}{F}{S}
x:
y:
z:
T:
D:
M:
I:
E:
J:
F:
S:
Famille
Gestion de mémoire / unité de protection
Mémoire cache
Décodeur d’instruction Thumb à 16-bit
Débuggeur JTAG
Multiplication rapide
Embedded ICE Macrocell
Instruction améliorée
Jazelle (code byte Java)
Unité à virgule flottante vectorielle
Version synthétisable
Tous les cœurs, qui ont été développés après le ARM7TDMI, contiennent les fonctionnalités TDMI.
Aujourd’hui il existe beaucoup de fournisseur de technologie silicium, qui possèdent des licences du cœur ARM
et qui les implémentent dans leur microcontrôleur. Voici un aperçu de ces fabricants : Analog Device, Atmel,
Freescale, Infineon, Intel, NEC, Philips, Samsung, TI et Toshiba.
2.2 Intel XScale
2.2.1 L’architecture XScale
L’architecture XScale est basée sur l’architecture ARMv5TE, dont le schéma bloque est illustré à la Figure 39 :
Figure 39 : Architecture Intel XScale, référence source : [6]
L’architecture XScale possède en supplément du XScale Execution Core, qui sera décrit dans le chapitre 2.2.2 de
façon plus détaillée, les unités suivantes:
Version 3.1, juin 2008
Page 33
Informatique 3
Le microcontrôleur PXA270
• Une mémoire cache pour les instructions de 32 kilos bytes (Instruction Cache abrégé par I-Cache). Les
segments de codes, qui sont souvent exécutés, sont stockés momentanément dans l’I-Cache. Le cœur du
processeur peut accéder à ces instructions à la fréquence d’horloge interne. Le I-Cache travaille avec des
adresses virtuelles ! Il améliore la performance du processeur, mais il n’influence pas son comportement de
façon déterminante.
• Une mémoire cache pour les données de 32 kilos bytes (Data Cache abrégé par D-Cache), qui permet de
stocker momentanément les données. Le D-Cache contient les données, qui sont souvent utilisées comme Par
exemple : les Tableaux, les coefficients etc.
• Mini D-Cache : Mémoire intermédiaire supplémentaire de 2 kilos bytes pour des données, qui doivent être
modifiées rapidement comme les entrées vidéos MPEG. Ce qui empêche que les données, qui doivent être
souvent modifiées, ne remplissent la mémoire cache.
• Write Buffer: Mémoire intermédiaire de 8 fois 16 bytes pour les données, qui doivent être stockées dans la
mémoire externe.
• La MMU pour les instructions (abrégé en anglais par IMMU) : Le IMMU est responsable de la conversion
des adresses virtuelles des instructions en adresses physiques, des droits d’accès, de la gestion des domaines
de la mémoire et du contrôle des attributs de l’I-Cache. Le IMMU contient un TLB avec 32 entrées selon le
principe de Round-Robin.
• La MMU pour les données (abrégé en anglais par DMMU): le DMMU est responsable de la conversion des
adresses virtuelles des données en adresses physiques, des droits d’accès, de la gestion du domaine de la
mémoire et du contrôle des attributs du D-Cache ou du mini D-Cache. Le DMMU contient également un
TLB avec 32 entrées.
• Branch Target Buffer (BTB): Le BTB réalise des prévisions statistiques sur le déroulement des sauts de
programme conditionnels. Cela est important pour le pipeline des adresses des instructions (voire chapitre
2.2.3). Lorsque cette prévision est erronée, il faut vider le pipeline (pipeline flush) afin de le remplir avec des
nouvelles instructions. Les prévisions suivantes sont possibles :
− Strongly taken: Le saut de programme a toujours été réalisés jusqu’à présent. L’adresse de destination
sera stockée.
− Weakly taken: Le saut de programme a souvent été réalisé jusqu’à présent. L’adresse de destination sera
stockée.
− Weakly not taken: Le saut de programme n’a été réalisés que rarement. L’adresse de la prochaine
instruction sera stockée.
− Strongly not taken: Le saut de programme n’a jamais été réalisé. L’adresse de la prochaine instruction
sera stockée.
• Core Memory Bus: Ce bus interne de 64 bits possède une bande passante de 4.8 Gigas Bytes / sec. Ce bus est
capable de lire 32 bits et d’écrire 32 bits simultanément en une seule période d’horloge. La bande passante de
correspond donc à 2.4 Gigas Bytes / sec pour chaque sens.
• Coprocessor Interface: Transfert de données de 32 bits entre le coprocesseur et la mémoire cache des
données.
• Coprocessor 15 (CP15): Les registres de contrôle des mémoires cache, de la MMU et du TLB.
• Coprocessor 14 (CP14): Les registres de contrôle du moniteur de performance (Performance Monitoring), du
débuggeur software et du mode d’horloge / puissance. Le moniteur de performance permet d’analyser le
comportement de la mémoire cache, celui du TLB ou la précision des prévisions du Branch Target Buffer.
• Multiply-Accumulate Coprocessor (CP0): Ce coprocesseur permet de réaliser des multiplications 16*16 bits,
en mode standard ou en mode dual (SIMD), et des multiplications 16*32 bits avec un accumulation de 40
bits.
• JTAG : « Boundary Scan Interface » est un interface standard destine aux testes.
• Debug : Le Debug permet de déboguer le programme durant son exécution (break points pour les instructions
et les données, Trace Buffer), en utilisant l’interface JTAG.
• Trace Buffer: Pour le déroulement de l’exécution du programme.
2.2.2 Le coeur d’exécution du XScale
La Figure suivante montre le transfert des données au sein du coeur d’exécution :
Version 3.1, juin 2008
Page 34
Le microcontrôleur PXA270
Informatique 3
Data
Sign extend
Write
Read
r15 (PC)
Rd
Registerbank
r0 – r15
Rn
Rm
B-Bus
A-Bus
Barrel shifter
A B Acc
ALU
MAC
Result-Bus
Address register
Incrementer
Address
Figure 40: Le transfert des données au sein du XScale, référence: [10]
Le traitement des données au sein des ARM / XScale s’effectue toujours à l’aide de registres. Il n’existe pas
d’instruction, qui soit capable de traiter directement de contenu de la mémoire. Les données sont donc
transférées dans le banc de registres, qui est composé de 16 registres de 32 bits.
La plupart des instructions ARM interprètent le contenu des registres comme des valeurs entières 32 bits
(signées ou non signées). L’unité « Sign extend » permet de convertir les valeurs signées 8 et 16 bits, qui ont été
lues à partir de la mémoire externe, en des valeurs signées 32 bits.
La plupart des instructions ARM traite deux opérandes (Rn et Rm). Le contenu de ces registres est transférer
avec les bus internes A et B. Le second opérande Rm peut être également décalé, soit vers la gauche ou vers la
droite, avec le « Barrel Shifter ».
L’ALU (Arithmetic Logic Unit) ou le MAC (Multiply Accumulate Unit) traitent les opérandes Rn et Rm, et
écrivent le résultat dans le registre (Rd).
Les instructions Load / Store permettent de transférer les données, soit à partir de la mémoire externe dans un
registre, ou inversement à partir d’un registre dans la mémoire externe. L’adresse de la case mémoire à
sélectionner est calculée par l’ALU. Cette dernière est copiée dans le registre d’adresse, afin d’être fournie sur le
bus d’adresse. L’incrémenter (Incremented) permet d’incrémenter ou de décrémenter cette adresse, après chaque
opération d’écriture et de lecture.
2.2.3 Le super pipeline du XScale
Les instructions à exécuter sont stockées dans un pipeline dans la plupart des processeurs. Le pipeline permet
simultanément d’exécuter l’instruction courante et de charger l’instruction suivante. Toutefois le pipeline
présente un désavantage, qui apparaît avec les sauts de programme conditionnels. Dans ce cas, il faut
systématiquement vider le pipeline, lorsque le comportement du programme a été mal prédit.
Le comportement du pipeline peut être expliqué à l’aide du pipeline à trois nivaux de l’ARM7. Le pipeline du
XScale est plus complexe et sera décrit plus loin.
Les niveaux du pipeline à 3 niveaux sont les suivants :
1) Fetch: Lecture de l’instruction à partir de la mémoire programme.
Version 3.1, juin 2008
Page 35
Le microcontrôleur PXA270
Informatique 3
2) Decode: Identification de l’instruction à exécuter.
3) Execute : Exécution de l’instruction à exécuter
Les trois étages (stage) du pipeline doivent être exécutés pour chaque instruction. L’exécution de chaque étage
nécessite un cycle d’horloge. Par conséquent, l’exécution d’une instruction complète nécessite trois cycles
d’horloge. Ce système permet toutefois d’exécuter une instruction par cycle d’horloge, car le pipeline traite
simultanément plusieurs instructions. L’exemple suivant illustre ce procédé :
time
Fetch
Decode
Cycle 1
Instr. 1
Cycle 2
Instr. 2
Instr. 1
Cycle 3
Instr. 3
Instr. 2
Execute
Instr. 1
Figure 41 : Exemple de pipeline à 3 niveaux
Au premier cycle d’horloge, l’instruction 1 est lue à partir de la mémoire programme. Au second cycle
d’horloge, le code d’opération (Opcode) de cette instruction est décode, alors que la prochaine instruction est lue
simultanément. Au dernier cycle d’horloge, l’instruction 1 est exécutée, l’instruction 2 est décodée et
l’instruction est 3 lue.
Le super pipeline du XScale est composé de 3 sous pipelines distincts :
1) Un pipeline des entiers à 7 étages ou le pipeline d’exécution principale. Ce pipeline est destiné à l’exécution
des instructions qui traitent les données, mis à part la multiplication.
2) Un pipeline à 8 étages, qui reprend les 5 premiers étages du pipeline des entiers. Ce pipeline est destiné aux
instructions load / store.
3) Un pipeline MAC de 6 à 9 étages, qui reprend les 4 premiers étages du pipeline des entiers. Ce dernier est
destiné aux instructions MAC.
Le super pipeline du cœur XScale peut être représenté de la manière suivante :
PC
PC+4
PC+8
PC+12
PC+16
Figure 42 : Le super pipeline du coeur RISC XScale, source : [3]
Tous les 3 pipelines sont en mesure d’exécuter leurs instructions en parallèle. Les tâches des différents étages
sont les suivantes :
• F1 / F2, Instruction Fetch: Livre au niveau ID la prochaine instruction à exécuter. Cette dernière est lue à
partir du cache d’instruction (I-Cache) en fonction du Programme Counter (PC). La différence de la valeur
du PC entre les niveaux F1 et X1, correspondant à 16 bytes, est définie intrinsèquement par le pipeline du
XScale. En présence de sauts de programme conditionnel, l’adresse de la prochaine instruction est définie par
Version 3.1, juin 2008
Page 36
Informatique 3
Le microcontrôleur PXA270
le tampon Branch Target.
• ID, Instruction Decode : Extraction du code d’opération (Opcode), des adresses des registres des opérandes et
du résultat à partir de l’instruction.
• RF, Register File / Shifter: Lit la valeur des registres définit par le niveau ID du banc de registre (opérandes),
exécute les éventuelles opérations de décalage (Barrel Shifter) et fournit les valeurs des opérandes à l’ALU
ou au MAC.
• X1, Execute : Exécute le traitement de donnée dans l’ALU. Tous le contenu du pipeline est vidée lorsque la
prévision du BTB, pour les sauts de programme conditionnels, s’est avérée comme étant fausse.
• X2, Execute 2 / State : Ce niveau actualise les registres d’état du programme (PSRs) et prépare les données
pour le niveau XWB (résultat de l’opération). L’état (instruction ARM ou Thumb) est définie en supplément.
• XWB, Write Back: Ecriture du résultat de l’opération dans le banc de registre. L’instruction se termine ainsi.
• D1 / D2, Data Cache : Les adresses pour les instructions load/store sont déterminées par le niveau X1.
L’accès au Data-Cache ou au mini D-Cache est réalisé au niveau D2.
• DWB, Data Write Back: Le données sont transférer dans la mémoire cache.
• M1 – Mx : ces niveaux traitent les instructions pour la multiplication et la multiplication avec accumulation
(coprocesseur)
2.3 Le PXA270 de XScale
2.3.1 Les propriétés
Les propriétés les plus importantes, héritées de la famille XScale, sont les suivantes :
• Processeur RISC 32 bits, qui est basé sur l’architecture ARMv5TE. Soutient toutes les instructions
ARMv5TE, en incluant les instructions Thumb et DSP (main pas de floating point).
• Un grand banc de registre, contenant 16 registres universels et 2 registres d’état. Les registres peuvent être
changés individuellement en fonction du contexte du processeur.
• Data et Memory Management Unit
• Super pipeline de 7 à 9 étages
• Mémoire cache de 32 kilos bytes pour les instructions, mémoire cache de 32 kilos bytes et un mini mémoire
cache de 2 kilos bytes pour les données
• Coprocesseur DSP (CP0) avec un accumulateur de 40 bits
• Coprocesseur 15 (CP15) pour la configuration du MMU, des mémoires Caches et des tampons
Les propriétés propres à la famille XScale sont les suivantes :
• Une fréquence d’horloge du coeur de 520 MHz et du bus de système de 208 MHz
• Gestion de la consommation avec différents modes d’économie de courant (idle, deep-idle, sleep, deepsleep). Les caractéristiques de consommation typiques sont de 747mW @ 520MHz (en mode actif) et
220mW @ 520MHz (en mode idle).
Version 3.1, juin 2008
Page 37
Informatique 3
Le microcontrôleur PXA270
2.3.2 Le diagramme de bloc
Figure 43 : Diagramme de bloc des PXA27x. Source : XScale PXA27x Family Developers Manual [2]
Le XScale PXA270 possède, en plus du cœur de XScale décrit au chapitre 2.2, les composants périphériques
suivants :
• Coeur XScale, dont les propriétés sont décrites au chapitre 2.2.
• Gestionnaire de consommation (Power-Management) flexible pour les applications à basse consommation
• SRAM interne de 4 * 64 kilos bytes
• Un contrôleur d’interruption (Interrupt-Controller) pour le masquage ou l’activation des interruptions. Ce
contrôleur est accessible à l’aide du plan de mémoire ou des registres du coprocesseur.
• Timer pour les systèmes d’opérations, un watchdog et 8 canaux timer supplémentaires.
• Unité PWM avec 4 canaux indépendants
• Real Time Clock (RTC) avec un conteur 32 bits pour le Timer, les interruptions périodiques etc.
• General Purpose I/O (GPIO): Beaucoup de pins du PXA27x sont multifonctionnels et peuvent être utilisés
comme entrées et sorties digitales.
• Memory Controller avec de nombreuses interfaces pour les composants de stockage internes et externes
(SDRAM, Flash, Card). Cette unité pilote le bus d’adressage, de données et de contrôle.
• Direct Memory Access Unit (DMA) pour les transferts de données de mémoire à mémoire, de périphérie à
mémoire et de mémoire à périphérie.
• De nombreuses interfaces sérielles
− 3 UART (Standard, Bluetooth, Full-Function)
− Port de communication infrarouge rapide
− Bus I2C
− AC '97 Codec Interface
− I2S Audio Codec Interface
− Contrôleur USB client et hôte
Version 3.1, juin 2008
Page 38
Le microcontrôleur PXA270
Informatique 3
•
•
•
•
•
•
− Port sériel synchrone (SSP)
Un contrôleur de panneau LCD (LCD Panel) avec de nombreux mode de fonctionnement
Contrôleur pour les cartes multimédia, cartes de mémoire SD (SD Memory Card) et cartes SDIO
Memory Stick Host Controller (Sony Standard)
Interface pour clavier
Interface pour les camera à capture rapide
Interface de Test / Debug
2.4 Les modes de fonctionnement
Le XScale (comme tous les autre processeur ARM) comprend 7 modes de fonctionnement. Ces derniers sont
décrits dans le Tableau suivant :
Mode
Utilisateur
Requête d’interruption rapide
Requête d’interruption
Superviseur
Abandon (abort)
Non défini
Système
Abréviation
USR
FIQ
IRQ
SVC
ABT
UND
SYS
privilège
Non
Oui
Oui
Oui
Oui
Oui
Oui
Bit de mode [4:0] du registre CPSR
10000
10001
10010
10011
10111
11011
11111
Figure 44 : Modes d’utilisation
Tous les modes, excepté celui d’utilisateur, sont des modes privilégiées. Par conséquent, ils peuvent accéder à
toutes les ressources du processeur. Ils peuvent également modifier les drapeaux d’interruption (flag) et possède
des bancs de registres fantômes.
Les modes FIQ, IRQ, SVC, ABT et UND sont des modes destinés aux traitements des interruptions (voir
chapitre 7 : Les interruptions). Le processeur exécute toutes les applications standard dans le mode utilisateur.
Lorsque des deux requêtes d’interruption hardware (FIQ ou IRQ) apparaissent, le processeur entre dans le mode
d’interruption correspondant à la requête afin de la traiter. Le processeur se trouve dans le mode superviseur
après le reset. Les routines du système d’exploitation sont exécutées dans ce mode. Le processeur entre dans le
mode abandon (ABT), lorsque apparaissent des erreurs d’accès mémoire. Le mode non défini est choisi lorsque
le processeur doit exécuter des instructions, qui ne sont pas définies ou qui ne sont pas soutenues. Le mode
système est identique à celui utilisateur. Ce dernier permet toutefois d’accéder aux registres CPSR (voir chapitre
2.6).
2.5 Le modèle des registres
Les registres constituent l’interface entre le programmeur et le processeur. Le set des registres ARM comprend
les registres suivants :
R0 – r15
CPSR
SPSR
16 registres d’utilités générales de 32 bits (general purpose), destinées au stockage des données
et des adresses.
Les trois derniers registres de ce banc sont utilisés normalement pour des tâches spéciales :
r13 en tant que « stack pointer » (sp), contient l’adresse actuelle de la pile du mode momentané
r14 en tant que « link register » (lr), contient l’adresse de retour dans le cadre des appelles de
sous routine.
r15 en tant que « program counter » (pc), contient l’adresse de la prochaine instruction, qui
doit être lue (fetch)
Current Program Status Register, voir chapitre 2.6
Saved Program Status Register
Version 3.1, juin 2008
Page 39
Le microcontrôleur PXA270
Informatique 3
L’accès aux 16 registres d’utilité général est possible dans tous les modes de fonctionnement. Mis à part
quelques exceptions, ces registres peuvent être utilisés librement.
r0
r1
Fast
interrupt
Request
r0
r1
r2
r3
r4
r5
r6
r7
r8
r9
r10
r2
r3
r4
r5
r6
r7
r8_fiq
r9_fiq
r10_fiq
r2
r3
r4
r5
r6
r7
r8
r9
r10
r2
r3
r4
r5
r6
r7
r8
r9
r10
r2
r3
r4
r5
r6
r7
r8
r9
r10
r2
r3
r4
r5
r6
r7
r8
r9
r10
r11
r12
r13 sp
r14 lr
r15 pc
r11_fiq
r12_fiq
r13_fiq
r14_fiq
r15 pc
r11
r12
r13_irq
r14_irq
r15 pc
r11
r12
r13_svc
r14_svc
r15 pc
r11
r12
r13_abt
r14_abt
r15 pc
r11
r12
r13_und
r14_und
r15 pc
cpsr
cpsr
spsr_fiq
cpsr
spsr_irq
cpsr
spsr_svc
cpsr
spsr_abt
cpsr
spsr_und
User und
System
Interrupt
Request
Supervisor
Abort
Undefined
r0
r1
r0
r1
r0
r1
r0
r1
Figure 45: Set des registres ARM
Les registres r0 à r8 sont communs pour tous les modes de fonctionnement. Ce ne sont donc pas des registres
fantômes.
Les registres r8 à r14 sont par contre des registres fantômes (banked register). Chaque mode de
fonctionnement possède son propre banc de ces registres (voir Figure 45). Les registres r8 à r12 ne sont pas
réservés pour des tâches spécifiques.
Le registre r13 est utilisé comme pointeur de pile (stack pointer abrégé par sp).
Le registre r14 est également appelé registre de reliage (link register abrégé par lr). L’adresse de retour est
copiée dans ce registre, lorsque le programme fait un saut dans une sous routine. Cette opération est également
exécutée avec les routines de service d’interruption. Toutefois, le registre du nouveau mode est utilisé dans ce
dernier cas.
Le registre r15 sert de compteur de programme (program counter abrégé par pc).
L’APCS (ARM Procedure Call Standard) spécifiée plus précisément l’utilisation des registres (voire chapitre
6 « Les sous routines »).
La Figure 45 montre que le mode d’interruption standard partage les registres r0 à r12 avec mode utilisateur.
Dans ce cas, seules les registres r13 et r14 sont des registres fantômes (banked register). C'est-à-dire que
uniquement ces deux registres diffèrent en fonction du mode de fonctionnement. L’avantage de cette technique
est que ces registres peuvent être modifiés dans un mode donné, sans que cela n’influence les autres modes. Ce
sujet est traités plus en détail dans les chapitre 6 « Les sous routines » et le chapitre 7 « Les interruptions ». Le
Saved Program Status Register (SPSR) contient la valeur du Saved Program Status Register (CPSR) du mode
précédent.
Version 3.1, juin 2008
Page 40
Le microcontrôleur PXA270
Informatique 3
2.6 CPSR Current Program Status Register
Ce registre permet de lire ou de modifier l’état actuel du processeur. Les bits et les drapeaux (flags) sont définis
de la manière suivante:
• Les bits d’état (Condition flags): N, Z, C, V, Q
• Les bits de masquage des interruptions (Interrupt Mask) : I (Interrupt Request) et F (Fast Interrupt Request)
• Etat du processeur (T) : distinction entre les états 32-Bit ARM ou 16-Bit Thumb
• Mode: Mode d’utilisation en fonction de la Figure 44
Fields
Flags
Status
Extension
Control
Bit 31 30 29 28
7 6
N Z C V Q
Function
not used
Condition
Flags
I
5 4
Mode
F T
Interrupt
Mask
0
Processor
Mode
Thumb
State
Figure 46: Current Program Status Register
2.7 Les bits d’état
Les bits d’état (Condition Flags) sont modifiés par l’ALU en fonction des opérations de comparaisons ou
d’arithmétiques. Une soustraction (instruction SUBS) met par exemple le bit Z (Zero) a un, lorsque le résultat de
l’opération et nul.
Les sauts de programme conditionnels sont toujours réalisés en fonction des bits d’état. Si le programme contient
par exemple l’instruction « if (A == 0) », il exécutera un saut sera en fonction du bit Z. Les processeurs
ARM possèdent en supplément des instructions conditionnelles, qui sont également exécutées en fonction des
bits d’état (Conditional Execution).
Le Tableau suivant contient les bits d’états du registre CPSR ainsi que leur description :
Version 3.1, juin 2008
Page 41
Le microcontrôleur PXA270
Informatique 3
Drapeau
(flag)
N
Nom du drapeau
Description
Negative
Z
Zero
C
Carry
V
oVerflow
Le bit N est considéré comme le signe des nombres signés. Ce dernier est mis à
un (1) avec les nombres négatifs, et il est mise à zéro (0) avec les nombres
positifs.
Le bit Z est mis à un lorsque le résultat de l’opération ALU est nul. Cela est
également valable pour les comparaisons de nombres : Le bit Z est mis à un
lorsque deux nombre sont égaux.
Avec les additions, le bit C est mis à 1 lorsqu’il y a un dépassement de capacité
non signé, sinon il reste à 0 (voir Figure 47).
Avec les soustractions, le bit C est mis à 0 lorsqu’il y a un dépassement de
capacité non signé, sinon il reste à 1 (voir Figure 47).
Avec les opérations de décalage, le bit C contient la valeur du dernier bit de
l’opérande.
Avec les additions et les soustractions, le bit V est mis à un lorsqu’il y a un
dépassement de capacité signé (voir Figure 48).
Q
saturation
Ce bit est mis à 1 par les instructions pour empêcher les dépassements de
capacité (saturation). Ce dernier n’est disponible que dans certains cœurs (ex.
v5TE).
Tableau 5 : Les bits d’état
Do maine des nombres
232 - 1
0
C=0
Dépassement avec
Soustraction
32
(2
) -1
Nulle
0
32
(2
SUB
Dépassement avec
addition
1
)
C=1
2
ADD
231
Figure 47 : Cercle de nombres binaires non signée
Version 3.1, juin 2008
Page 42
Le microcontrôleur PXA270
Informatique 3
- 231
Domaine des nombres
231 -1
Nulle
0
1
-1
2
SUB
N=1
Négatif
- 231 - 1
V=1
N=0
Positif
231
Dépassement avec
soustraction
Dépassement avec
addition
ADD
V=1
Figure 48 : Cercle de nombres binaires signés
2.8 Les modèles de mémoire et les format de
données
Dans les processeurs de la famille ARM, le stockage des données s’effectue par défaut avec le format petit
boutiste (little-endian). Les bytes de poids plus faible des variables sont ainsi stockés en premier, suivis par les
bytes de poids plus fort. Mais les processeurs ARM peuvent être configurés, afin que les données soient stockées
avec le format gros boutiste (big-endian). Nous nous limiterons dans ce chapitre au format petit boutiste.
Les processeurs ARM - à partir de la version v4 - soutiennent les formats de données suivants :
• Byte signés et non signés (8 bits, char)
• Demi mot (halfword) signés et non signés (16 bits, short int)
• Mot (word) signés et non signés (32 bits, long int)
Les processeurs ARM sont basés sur l’architecture Load/Store. C'est-à-dire que les opérandes de l’ALU doivent
toujours être stockées dans des registres. Les opérateurs de l’ALU traitent ainsi les données sous formant mot
(32 bits). Les seules instructions, qui sont capables de transférer des données entre la mémoire et les registres,
sont les instructions de transfert de donnée (Load et Store). Ces instructions sont capables de transférer des
données du type byte, demi-mot et mot. Lorsqu’une donnée du type byte ou demi-mot est lue à partir de la
mémoire, elle est étendue à 32 bits avec l’unité d’extension de signe « Sign Extend » (voir Figure 40).
Certaine conditions doivent être respectées pour le stockage des données dans la mémoire. Les Figures suivantes
illustres le stockage des bytes, des demi mots et des mots dans la mémoire :
Model de mémoire avec un adressage du type byte :
Adresse
N
n+1
n+2
n+3
Byte 0
Byte 1
Byte 2
Byte 3
Figure 49: Model de mémoire du type byte
Version 3.1, juin 2008
Page 43
Le microcontrôleur PXA270
Informatique 3
Model de mémoire avec un adressage du type demi mot :
Adresse
n
Demi mot 0
n+2
Demi mot 1
Byte de poids plus faible du demi mot 0
Byte de poids plus fort du demi mot 0
Byte de poids plus faible du demi mot 1
Byte de poids plus fort du demi mot 1
Figure 50: Model de mémoire du type demi mot
Un demi mot est toujours stocké a une adresse paire (frontière 2 bytes). Le byte de poids plus faibles sera stocké
à l’adresse inférieure (paire), et le byte de poids plus for à l’adresse supérieur (impaire). Le bit de poids le plus
faible de l’adresse de base A0 est donc nul.
Model de mémoire avec un adressage du type mot :
Adresse
n
Mot 0
Byte de poids le plus faible du mot 0
n+4
Mot 1
Byte de poids le plus fort du mot 0
Byte de poids le plus faible du mot 1
Byte de poids le plus fort du mot 1
Figure 51: Model de mémoire du type mot
Un mot est toujours stocké à une adresse, qui est divisible par 4. Le byte de poids le plus faible du mot est stocké
à l’adresse n, alors que le byte de poids le plus fort à l’adresse n+3. Les deux bits de poids les plus faibles de
l’adresse de base (A0 et A1) sont donc nuls.
2.9 Le plan de mémoire du PXA270
Les registres r0 à r15 et le registre CPSR sont accessibles directement. C'est-à-dire que les instructions
assembleur peuvent utiliser ces registres comme opérande. Tous les autre registres (comme par exemple ceux du
GPIO, de l’USB etc.) ne sont accessibles qu’à l’aide du système de bus interne (adresse et données). Chacun de
ces registres possèdent donc sa propre adresse. Le plan de mémoire (Memory map) du processeur illustre les
espaces d’adressage pour les différents groupes de registres.
Le plan de mémoire du PXA27x est le suivant :
Version 3.1, juin 2008
Page 44
Informatique 3
Le microcontrôleur PXA270
Figure 52 : Le plan de mémoire du PXA27x, source : XSCALE_PXA27x_Family_Developers_Manual [2]
2.10 Le plan de mémoire du CARME
Les espaces d’adressage des composants périphériques et de stockage externe (Flash et SDRAM) du kit de
développement CARME ont été inclus dans le plan de mémoire de la Figure 52. Certains espaces d’adressage du
kit sont donc identiques à ceux du PX270 ; comme par exemple celui du slot Compact Flash. Le contrôleur
CAN, qui est sélectionnable avec CS1 dans CARME, possèdent l’adresse de base 0x0400’0000.
Version 3.1, juin 2008
Page 45
Informatique 3
Le microcontrôleur PXA270
0xFFFF_0800
0xFFFF_0000
0xA400_0000
0xA000_0000
0x5800_0000
0x4000_0000
0x3000_0000
0x2000_0000
0x1800_0000
0x1400_0000
0x1000_0000
0x0C00_0000
0x0800_0000
0x0400_0000
0x0200_0000
0x0000_0000
Réservé
High Vector Debug Handler
Réservé
64 M bytes SDRAM
Réservé
Périphérie
Compact Flash 1
Compact Flash 0
Réservé
nCS5
nCS4
CPLD, MIN3IO (nCS3), Extension 1 bis 4
Ethernet-Controller (nCS2)
CAN-Controller (nCS1)
Réservé
32 M byte Flash (Vector Table)
Figure 53 : Le plan de mémoire du kit de développement CARME
2.11 Le schéma des pins
Le PXA270 est produit avec différents boîtiers BGA. Par conséquent, les connexions peuvent varier en fonction
du boîtier. Les pins sont répartis selon leur fonctionnalité dans différents blocks. La Figure suivante illustre un
exemple de répartition des pins :
Figure 54: Le schéma des pins du PXA270 (23mm/360 Ball Grid),
Source : Intel PXA27x Processor Family Design Guide [7]
2.12 Connexion des composants Flash et SDRAM
Le PXA270 possède un bus d’adresse et de données de 32 bits. De nombreux composants de stockage possèdent
toutefois une organisation de 8 ou 16 bits. Deux ou quatre composants doivent donc être utilisés en parallèle,
afin de pouvoir réaliser une connexion à 32 bits. Des signaux de contrôle sont également nécessaires, afin de
Version 3.1, juin 2008
Page 46
Le microcontrôleur PXA270
Informatique 3
pouvoir gérer la communication. Les Figures suivantes illustrent des connexions typiques des composants Flash
et SDRAM, qui possèdent une organisation de 16 bits.
Flash de 4 Méga * 16 bits
Le schéma bloque de la connexion est le suivant :
nCS
nWE
nOE
nSDCAS
nSDCLK<0>
MA<23:0>
MD<31:0>
4M*16 Flash
4M*16 Flash
nCS
nWE
nCS
nWE
nOE
nOE
nADV
nADV
CLK
MA<23:2>
MD<15:0>
A<21:0>
DQ<15:0>
CLK
MA<23:2>
MD<31:16>
A<21:0>
DQ<15:0>
Figure 55: Schéma bloque de la connexion des composants flash avec une organisation de 16 bits
Source: Intel PXA27x Processor Family Developer's Manual [2]
Les signaux suivants interviennent dans la connexion :
Signal
CS
WE
OE
ADV
CLK
A
DQ
Description
Chip-Select : Sélectionne un banc de composants de stockage. Un banc représente un certain
nombre de composants, qui mis ensemble sont en mesure de traiter des données de 32 bits.
Le banc dans l’exemple de ci-dessus est composé de 2 composants avec une organisation de
16 bits.
Write Enable : Signal d’écriture, avec lequel les données peuvent être écrites dans la flash.
Output Enable : Signal de lecture avec lequel les données peuvent être lues à partir du flash.
Ce signal active les amplificateurs de sortie pour le bus de données.
Address Valid : Ce signal indique que les adresses, qui sont fournies par le processeur sur le
bus d’adresse, sont valables. Correspond au signal de sortie du processeur nSDCAS.
Horloge pour tous les composants statiques comme les flashs ou les SDRAM
Bus d’adresse : Seul les données du type mots sont lues dans cet exemple (32 bits). Par
conséquent les bits d’adresse A0 et A1 n’y sont pas utilisés.
Bus de données : Les composants de stockage possèdent une organisation de 16 bits. Par
conséquent, le composant de gauche est connecté aux 16 bits de données de poids plus
faibles (low halfword) et celui de droite aux 16 bits de données de poids plus fort (high
halfword).
Tableau 6 : Signaux de contrôle destinés au composant flash
SDRAM de 4 Méga * 16 bits
Le schéma bloque de la connexion est le suivant :
Version 3.1, juin 2008
Page 47
Le microcontrôleur PXA270
Informatique 3
nCS
nWE
nSDRAS, nSDCAS
nSDCKE, nSDCLK<2:1>
MA<24:10>
DQM<3:0>
MD<31:0>
MA<21:10>
MA<23:22>
DQM0
DQM1
MD<15:0>
4M*16 SDRAM
4M*16 SDRAM
nCS
nWE
nCS
nWE
nRAS
nRAS
nCAS
nCAS
CKE
CKE
CLK
CLK
A<11:0>
BA<1:0>
DQML
DQMH
DQ<15:0>
MA<21:10>
MA<23:22>
DQM2
DQM3
MD<31:16>
A<11:0>
BA<1:0>
DQML
DQMH
DQ<15:0>
Figure 56 : Schéma bloque de la connexion des composants SDRAM avec une organisation de 16 bits
Source : Intel PXA27x Processor Family Developer's Manual [2]
Les signaux suivants interviennent dans la connexion :
Signal
CS
WE
RAS
CAS
CKE
CLK
A
BA
DQML/DQMH
DQ
Description
Chip-Select : Sélectionne un banc de composants SDRAM
Write Enable : Signal d’écriture, avec lequel les données peuvent être écrites dans la
SDRAM.
Row Address Strobe
Column Address Strobe
Clock Enable
Clock
Adresses pour row et column
De nombreux SDRAM proposent des bancs de mémoire internes. Ces derniers peuvent être
sélectionnés à l’aide des signaux « Bank Address ». Ces signaux sont connectés côté
processeur aux bits d’adresses.
Data byte mask control. Ces quatre lignes de contrôle du processeur permettent de transférer
les données de façon byte ou demi mot : DQM<0> correspond au byte de poids le plus faible
(bit 0 – 7), DQM<3> au byte de poids le plus fort (bit 24 - 31).
Bus de données : Les deux composants SDRAM possèdent une organisation de 16 bits. Par
conséquent, le composant de gauche est connecté aux 16 bits de données de poids plus
faibles (low halfword) et celui de droite aux 16 bits de données de poids plus fort (high
halfword).
Tableau 7 : Signaux de contrôle destinés au composant flash
2.13 Schéma hardware avec le PXA270 & la mémoire
Le document « PXA27x Processor Developer's Kit » d’Intel [8] contient un schéma bloque d’un système à
microcontrôleur contenant le PXA270, des SDRAM et des flashs. Les schéma de la carte Colibri de Toradex, qui
est utilisé dans le kit de développement CARME, n’est malheureusement pas disponible.
Version 3.1, juin 2008
Page 48
La programmation en assembleur
Informatique 3
3 La programmation en assembleur
3.1 Introduction
Ce chapitre traite la programmation en assembleur de façon générale. Toutefois, les exemples d’assembleur y
sont définis avec le jeu d’instruction ARMV5TE des processeurs XScale. La syntaxe de l’assembleur s’oriente à
celle de GNU. Cette dernière diffère dans un certain nombre de point par rapport à celles des autres fournisseurs.
L’assembleur est un langage de programmation proche du hardware. Il dépend par conséquent du hardware, c’est
à dire qu’il a été développé pour une famille de processeur bien définie.
Avantage : l’assembleur est optimisé pour le hardware (registre, architecture etc.)
Désavantage : l’assembleur n’est pas portable, c. à d. qu’il ne peur pas être utilisé avec un autre CPU.
Ce chapitre traite les équivalences entre les différents assembleurs.
3.2 Les niveaux des langages de programmation
Un processeur ne comprend que le code machine, qui est toutefois incompréhensible pour l’homme. L’homme
utilise donc des langages de programmation, qui sont plus compréhensible pour lui. Ces derniers sont traduits par
des assembleurs ou des compilateurs en code machine.
Prend une bouteille de bière dans le
réfrigérateur
Bière – 1
Bière = Bière – 1;
LDR
SUB
STR
r4,beer
r4,#1
r4,beer
0xe59f4020
1110’0101’1001’1111’0100’0000’0010’0000
0xe2444001
1110’0010’0100’0100’0100’0000’0000’0001
0xe0802001
1110’0000’1000’0000’0010’0000’0000’0001
Langue naturelle
Pseudo code
Langage de programmation haut
niveau
Assembler
Abstraction
Proche du hardware
La Figure suivante montre les niveaux de langage de programmation possible :
Code machine
Figure 57 : Niveau des langages de programmation
a) La langue naturelle est la plus compréhensive pour l’homme. Elle est malheureusement trop floue et trop
redondante. Elle ne convient donc pas pour la programmation.
b) Le pseudo code est souvent utilisé dans la phase de design. Son niveau d’abstraction est très élevé et il n’est
pas standardisé.
c) Les langages de programmation haut niveau possèdent également un niveau d’abstraction élevé. Les
compilateurs traduisent ces langages dans des codes machine, dont l’efficacité dépend du langage de
programmation et du compilateur. Les langages de programmation les plus répondus pour les
microprocesseurs sont le C et C++. Les langages de programmation haut niveau sont standardisés (ex. ANSIC). Ce qui permet de porter les programmes d’un processeur à un autre, avec plus ou mois d’efforts.
d) Les programmes en assembleur sont très difficilement compréhensible pour l’homme. Toutefois, les
programmes en assembleur sont plus performants et utilisent mieux les ressources que les programmes haut
niveau.
Version 3.1, juin 2008
Page 49
Informatique 3
La programmation en assembleur
3.3 La structure d’un fichier en assembleur
Les points suivants influence la structure d’un fichier assembleur :
• La syntaxe de l’assembleur, qui dépend du processeur
• Les directives de l’assembleur, qui dépendent de l’assembleur
• Les lignes directives de programmation, qui dépendent du fabricant
La Figure suivante montre une éventuelle construction d’un fichier assembleur.
/*************************************************************************
*
*
* Projet
: NomProjet
*
*
*
*
*
**************************************************************************
* Programme/Module : NomModule
*
* Nom du fichier
: NomFichier.68k
*
* Version
: 1.00
*
* Définition
: dd.mm.yyyy
*
* Auteur(s)
: NomAuteur
*
* -----------------------------------------------------------------------*
* Description
: Description brève du module
*
*
*
**************************************************************************
* Modification:
*
* Auteur
Date de la modification
*
* m.n
dd.mm.yyyy
*
*************************************************************************/
Entête (header)
(en option)
/*************************************************************************
* PUBLIC DECLARATIONS
*
*************************************************************************/
.global
mysub
@ exported subroutines
Interface du
module
(en option)
/*************************************************************************
* EXTERNAL DECLARATIONS (optional)
*
*************************************************************************/
.extern
extsuB
@ imported subroutines
Symbole importé
(en option)
/*************************************************************************
* include DEFINITIONS
*
*************************************************************************/
.include
″pxa270.h″
@ include controller registers
Fichier à inclure
(en option)
/*************************************************************************
* EQUATE DEFINITIONS
*
*************************************************************************/
.equ
MAX,0x1000
@ maximum allowable size
Définition EQU
(en option)
/*************************************************************************
* VARIABLE AND CONSTANT DEFINITIONS
*
*************************************************************************/
.data
myvar: .space
4
@ space for 1 Word (32-Bit)
Définition des
variables et des
constantes
(en option)
/*************************************************************************
* CODE
*
*************************************************************************/
.text
Code
Version 3.1, juin 2008
Page 50
La programmation en assembleur
Informatique 3
mysub:
ADR
MOV
STR
BL
MOV
r0, myvar
r1, #MAX
r1, [r0]
Extsub
pc, lr
@
@
@
@
@
Load the address of myvar
Load the constant value MAX
Copy the MAX value in to myvar
Call the subroutine Extsub
Return to the calling function of mysub
.end
Figure 58 : Construction possible d’un fichier assembleur
Les entêtes (Header) dépendent de la société. Il existe normalement dans les sociétés des lignes directives pour la
programmation, qui définissent l’aspect de l’entête. L’entête devrait toutefois contenir au minimum les
informations suivantes
• Nom du projet
• Brève description du module
• Historique
La partie « PUBLIC DECLARATIONS » contient tous les noms de sous-routines et de variables, qui sont
définies dans le module courant et doivent être exportées dans les autres modules.
La partie « EXTERNAL DECLARATIONS » contient tous les noms de sous-routines et de variables, qui doivent
être importées depuis les autres modules.
Les fichiers, qui contiennent la description des registres du contrôleur, peuvent être importés dans la partie
« include DEFINITIONS ». include copie tout le contenu du fichier en question dans le module.
La partie « EQUATE DEFINITIONS » contient les définitions EQUATE (correspond à la directive #define
de C).
La partie « VARIABLE AND CONSTANT DEFINITIONS » contient les définitions des variables et des
constantes.
La partie « CODE » contient les instructions du programme. Cette partie est divisée en 4 colonnes (voir chapitre
4.3.1).
3.4 La syntaxe assembleur
3.4.1 La structure d’une ligne assembleur
La syntaxe de l’assembleur, qui également nommé mnémonique, est orientée ligne. Chaque ligne du code source
correspond donc à une instruction assembleur. La Figure suivante illustre un exemple d’instruction assembleur :
Etiquette
Opérations / instructions
Opérandes
Commentaire
main:
LDR
R0, #MAX
@ Max value
Figure 59 : Une ligne d’instruction assembleur
Etiquette :
Le champ des étiquettes commence à la première colonne et se termine avec « : ». L’étiquette peut contenir le
nom d’une variable, d’une sous-routine ou d’un label. Un label est une sorte de marque, qui est utilisé pour les
sauts de programme.
Opération / instructions :
Le champ des opérations / instructions contient les instructions pour la CPU ou les directives pour l’assembleur.
Dans l’exemple ci-dessus « LDR
» est une instruction, qui commande à la CPU de copier la valeur constante
« MAX » dans le registre « R0 ».
Toutes les instructions d’un processeur sont définies dans son jeu d’instruction (voir chapitre 4, qui traite le jeu
Version 3.1, juin 2008
Page 51
La programmation en assembleur
Informatique 3
d’instruction de l’ARM V5)
Toutes les opérations peuvent être exécutées de façon conditionnelle.
Exemple :
CMP
r0, #0
CMPNE r1, #1
ADDEQ r2,r3,r4
@ if (a==0 || b==1)
@ c = d + e;
Figure 60 : Instruction assembleur conditionnelle
Ce concept permet d’économiser de nombreux sauts de programme en comparaison avec d’autre famille
d’assembleur. La condition est définie avec un suffixe ou un code de condition à la fin de l’instruction. Par
exemple, le suffixe « NE » de la deuxième comparaison a pour conséquence que cette instruction n’est exécutée
que si le résultat de l’opération précédente est différent de zéro. De la même façon, l’addition n’est exécutée que
si le résultat de l’opération précédente est égal à zéro (EQ).
L’instruction, qui vient d’être exécutée, fixe la condition. Cette dernière est évaluée l’aide des bits d’état courant
du programme (flags), qui se situent dans le registre du même nom (Current Program Status Register abrégé par
CPSR). Dans l’exemple de ci-dessus les conditions sont fixées par les deux opérations de comparaisons.
Toutes les opérations arithmétiques, qui sont exécutées par l’ALU, influencent les bits d’état N, Z, C et V. Les
opérations logiques ne modifient que N, Z et C.
Les opérandes :
Les opérandes des instructions ou des directives assembleur sont définis dans le champ des opérandes. Dans
l’exemple de ci-dessus les opérandes de l’instruction « LDR » sont la constante « MAX » et le registre « r0 ».
Le processeur ARM travail fondamentalement avec trois opérandes. Certaines instruction, comme par exemple
les sauts de programme, se limitent à un ou deux opérandes. Le jeu d’instruction ARM ne contient pas
d’instruction sans opérande.
Instruction avec un opérande :
Ce type d’instruction ne possède qu’une adresse de destination. Cette dernière est définie de façon symbolique
avec les ramifications ou les sauts de programme.
Exemple :
B
SWI
start
0x10
Instruction avec deux opérandes :
Cette catégorie contient la plupart des instructions de transfert de donnée. Ces dernières stockent / chargent les
données depuis la mémoire de travail dans les registres du processeur
Exemple :
MOV
LDR
pc,lr
r0,waleur
Les instructions avec trois opérandes :
La plupart des instructions, qui traitent les données, nécessitent trois opérandes. Elles possèdent le formant
suivant :
mnemonic
dest, src, shift
Dans cette expression « dest » représente le registre de destination et « src » celui de source. Les registres r0
à r15 peuvent être utilisés pour cela. L’opérande « shift » permet de traiter un opérande à l’aide du « barrel
shifter » avant l’exécution de l’opération. Il permet également de définit un valeur constante de 8 bits.
Version 3.1, juin 2008
Page 52
La programmation en assembleur
Informatique 3
Chez les processeurs RISC, les instructions de traitement de données ne se limitent en générale à des opérations
entre registres. Les opérations entre des registres et la mémoire de travail sont exclusivement des opérations de
transfert de données.
Les commentaires :
Les commentaires du champ de commentaire sont définis pour améliorer la compréhension du code.
L’assembleur GNU prévoit trois types de commentaires : les commentaire en bloc, les commentaire en ligne et
les commentaire de fin de ligne.
Les commentaires en bloc sont formulés entre « /* » et « */ », comme en ANSI-C. Les commentaires en ligne
sont définis uniquement sur une ligne et ils sont introduits avec un dièse « # ». Les commentaires de fin de ligne
sont défini à la fin de la ligne et ils sont introduits avec un « @ ». Il est très important de bien commenter les
programmes assembleur. Toutefois, le commentaire ne devrait pas décrire l’instruction, mais améliorer la
compréhension du déroulement du programme.
Exemple :
/* Commentaire de bloc
*/
# Commentaire en ligne
LDR
r0,=operand1
@ Commentaire fin de ligne
Figure 61: Les trois formes des commentaires assembleur
3.4.2 Les symboles
Les symboles sont des noms de variables, de sous-routines, de labels etc. Les caractères autorisés pour les
définir sont les suivants :
• Les lettres a à z et A à Z (pas d’accent)
• Les chiffres 0 à 9
• Le caractère de soulignement « _ »
• Le point « . »
• Le caractère dollars « $ »
Les règles suivantes régissent la définition des symboles :
• Le premier caractère ne doit pas être un chiffre.
• Un symbole peut être aussi long que possible, tous les caractères sont significatifs.
• Distinction entre les majuscules et les minuscules.
L’assembleur GNU soutient également les symboles locaux.
Le point unique, en tant que symbole prédéfini, possède une signification précise : Il représente la valeur du
compteur de programme courant. Par exemple « .=.+4 » est équivalent à « .space 4 ».
3.4.3 Les constantes
Les règles suivantes régissent la définition des constantes :
Version 3.1, juin 2008
Page 53
La programmation en assembleur
Informatique 3
Type
Chaîne de caractère
Caractère
Numérique
Numérique
Numérique
Numérique
Description
String
Char
Hexadécimal
Binaire
Octal
Décimal
Préfix
"
'
0x
0b
0
Pas de préfix
Exemple
"Bonjour"
'A'
0x7FF
0b0111011
0124
123
Tableau 8 : Règle qui régissent la définition des constantes
Les constantes peuvent être spécifié avec le caractère « = ». Cela est valable pour les valeurs numériques et les
adresses, qui sont représentées à l’aide de symbole.
Les valeurs, qui ne peuvent pas être chargées par les instructions « MOV », sont automatiquement adressées de
façon relative avec compteur de programme (ici [pc, #4]). Dans l’exemple suivant, la constante
0x12345678 est chargé de la mémoire programme de cette façon. Par contre, la valeur un est directement
chargée avec l’instruction MOV.
Exemple :
start:
loop:
0xa00004e8
0xa00004ec
<loop+12>
0xa00004f0
0xa00004f4
LDR
LDR
ADD
B
r0,=1
r1,=0x12345678
r0,r0,r1
loop
@ Charger la valeur constante 1
@ Charger la valeur 0x12345678
@ Additionner les deux valeurs
<start>:
<loop>:
MOV
LDR
r0, #1 ; 0x1
r1, [pc, #4]
<loop+4>:
<loop+8>:
ADD
B
r0, r0, r1
0xa00004ec <loop>
@ la valeur est chargé de la mémoire 0xa00004f8
Figure 62 : Le code objet généré pour le chargement de la constante 0x12345678
Remarque :
La valeur constant est stockée à l’adresse 0xA00004F8. Le compteur de programme adresse la prochaine
instruction à exécuter, qui est stockée sous 0xA00004EC. Le chargement des instructions relatif au compteur de
programme, s’effectue toujours avec un décalage préalable de - 8. Ce qui fournit le décalage à noter dans le code
suivant : 0xA00004F8 - 0xA00004EC – 8 = 4.
3.4.4 Les opérateurs et les opérandes
Des calculs peuvent être effectués en dehors de jeu des instructions durant le processus d’assemblage. Ces
calculs sont surtout utilisés pour la détermination des tailles de la mémoire ou des distances des sauts de
programme.
Le Tableau suivant contient les opérateurs, qui sont autorisées dans les expressions assembleur. Des espaces
vides ne sont pas autorisés avant ou après ces opérateurs :
Version 3.1, juin 2008
Page 54
La programmation en assembleur
Informatique 3
+
*
/
%
&
|
^
&&
||
==, <>
>, >=
<, <=
<<
>>
~
Addition
Soustraction
Multiplication signée
Division signée
Reste de la division signée (Modulo)
Opération binaire et
Opération binaire ou
Opération binaire ou exclusive
Opération logique et
Opération logique ou
Egalité et inégalité
Plus grand que, plus grand que ou égale à
Plus petit que, plus petit que ou égale à
Opération de décalage vers la gauche
Opération de décalage vers la gauche
Négation par complément à deux
Inversion binaire, complément à un
Tableau 9 : les opérateurs pour les expressions assembleur
La priorité des opérateurs dans les expressions est la suivante :
Négation, complément
Multiplication, division, modulo
Décalage vers la gauche, décalage vers la droite
Opérations logiques et, ou et ou exclusive
Addition, soustraction
Egalité et inégalité
Opération de comparaison
Opérations booléennes et ou
Priorité maximale
Priorité minimale
Tableau 10 : la priorité entre les différents opérateurs
Le résultat d’une opération de comparaison est toujours un nombre entier dans l’assembleur GNU. La valeur 0
représente faut et la valeur -1 vrai. Les opérations booléenne && et || fournissent par contre une valeur +1,
lorsque le résultat est vrai. Cette différence ne joue aucun rôle pour l’évaluation des conditions, En effet tous ce
qui est différent de 0 est considéré comme vrai.
Exemple:
Les bits 3 et 11 du registre r0 doivent être effacés.
BIC r0, r0, #(1 << 3) | (1 << 11)
L’instruction BIC efface les bits dans le registre r0. Les bits à traiter sont spécifiés avec le paramètre
« #(1 << 3) | (1 << 11) ». La position du bit y est définie avec l’opérande « << », alors que l’opérande « | »
permet d’associer ces derniers.
3.5 L’environnement de développement
Les programmes proche du hardware (Firmware) sont généralement développés sur des PC avec des
environnements de développement intégrés (Integrated Development Environment, IDE). Ces derniers peuvent
être soit simulés ou testés directement sur le hardware (débuggeur). La plupart des environnements de
développement moderne proposent les fonctionnalités suivantes :
• Editeur
• Assembleur, Compilateur et relieur (Linker / Locator)
• Débuggeur
Version 3.1, juin 2008
Page 55
La programmation en assembleur
Informatique 3
• Gestion de projet
La Figure suivante illustre une vue d’ensemble des fichiers, qui sont générés durant la phase de développement :
Editor
Source
assembler
Source
*.s
assembler
*.asm
*.s
*.asm
Source
C / Source
C++
*.c
C / C++
*.cpp*.c
*.cpp
Assembler
Compiler
Listing
assembleur
Listing
*.lst
assembleur
*.lst
Fichier
objet
Fichier
*.oobjet
*.ltx*.o
Listing
compilateur
Listing
*.lst
compilateur
*.prn
*.lst
Fichier
objet
Fichier
*.oobjet
*.ltx*.o
Linker/Locator
Listing du
relieur
*.map
Fichier
binaire
*.bin
Fichier
débuggeur
*.elf
Figure 63 : Procédure de développement
3.5.1 L’éditeur
L’éditeur permet de définir le code source en assembleur ou avec un langage de programmation évolué. La
plupart des éditeurs sont sensible à la syntaxe et mettent en évidence les mots clés.
Exemple :
Le code en assembleur suivant a été défini à l’aide d’un éditeur.
start:
loop:
.arm
.global
start
.text
LDR
LDR
ADD
B
r0,=1
r1,=0x12345678
r0,r0,r1
loop
@ Load constant value 1
@ Load constant value 0x12345678
@ ADD both values
.end
Figure 64 : Exemple d’un code en assembleur
Version 3.1, juin 2008
Page 56
La programmation en assembleur
Informatique 3
3.5.2 L’assembler
L’assembleur est toujours spécifique à la famille des processeurs. Si vous voulez développer du code pour des
processeurs différents, vous devez également utiliser des assembleurs différents. On parle de « Cross
Assembler », lorsque le code en assembleur est développé sur un ordinateur différent de celui, qui doit exécuter
le programme (ex. l’assembleur fonctionne sur un PC et le code généré sur le microcontrôleur d’une machine à
café).
L’assembleur traduit le code source assembleur, qui est contenu dans un fichier ASCII avec une terminaison
« .s » ou « .asm », en un fichier objet (.o). Des fichiers supplémentaires peuvent être générés, en fonction des
options de l’EDI (ex. fichier de listing : List-File avec une terminaison « .lis »). Le listing de l’assembleur pour
l’exemple ci-dessus a été illustré dans la Figure suivante :
1
2
3
ARM GAS EditionExample.s
1
2.
3
4
5 0000 0000A0E3
start:
6 0004 04109FE5
loop:
7 0008 010080E0
8 000c FCFFFFEA
9
10 0010 78563412
ARM GAS
page 1
.arm
.global
start
.text
LDR
LDR
ADD
B
r0,=1
r1,=0x12345678
r0,r0,r1
loop
.end
EditionExample.s
DEFINED SYMBOLS
EditionExample.s:1
EditionExample.s:5
EditionExample.s:6
EditionExample.s:10
@ ADD 0x12345678
page 2
.text:00000000
.text:00000000
.text:00000004
.text:00000010
$a
start
loop
$d
NO UNDEFINED SYMBOLS
Figure 65 : Le listing assembleur
Les colonnes du fichier listing contiennent les informations suivantes :
Nr. de
colonne
1
2
3
reste
Contenu
Numéro de ligne du code source
Adresse relative de départ du code
Code machine, par exemple "0000A0E3" veut dire que le registre r0 doit être chargé avec la
valeur 0. "0100080E0" veut dire que le contenu du registre r1 doit être additionné au registre
r0. Toutes les instructions nécessitent 4 bytes (1 mot) de stockage. Elles sont donc stockées à des
adresses mot (divisibles par 4).
Code original en assembleur
Tableau 11 : Colonnes du fichier listing
3.5.3 Le compilateur
Comme l’assembleur, le compilateur traduit le programme haut niveau, qui est défini dans un fichier source, en
un fichier objet. Les compilateurs C ou C++ sont utilisés généralement pour les applications embarqués.
Version 3.1, juin 2008
Page 57
Informatique 3
La programmation en assembleur
3.5.4 Le relieur / locateur
Le relieur (Linker) assemble tous les fichiers objet d’un programme, alors que le localisateur (Locator) attribue
des adresses définitives aux instructions et aux données du programme.
Le relieur / localisateur génère les fichiers suivants :
a) Pour le chargement du code dans la mémoire (.bin) ou
b) Pour le débuggeur (.elf)
c) Fichier de listing et de mappage (.map)
« elf » est une abréviation pour « Executable and Linking Format ». Ce format est un standard pour la gestion
des exécutables, des codes objets des bibliothèques, du mappage de la mémoire et des informations nécessaires
au débuggeur. Le format elf est entre temps très répandu et il a remplacé conceptuellement le COFF et de
nombreux autres formats de débuggeur.
Le contenu de ce fichier ne devrait pas intéresser le programmeur. Il ne peut pas être lu avec l’éditeur, mais par
contre, il peut être exploité avec les applications « objdump.exe » ou « elfdump.exe ».
Figure 66 : Les informations contenues dans le fichier elf exploitées avec OBJDUMP.EXE
3.5.5 Le débuggeur
Le débuggeur permet de tester le code, en représentant le contenu des registres, des variables et du code sur
l’écran du PC. L’insertion de points d’arrêt (break points) dans le code source et son exécution contrôlée, pas par
pas, font partie des exigences minimales pour un débuggeur.
On parle de « target debugging » lorsque le débogage est exécuté directement sur le système en développement.
Dans ce cas le débuggeur, qui est exécuté sur le PC, est responsable du téléchargement du code de débogage sur
le système en développement et de la communication avec ce dernier. Alors que le processeur du système en
développement n’est responsable que de l’exécution de ce code.
3.5.6 La gestion du projet
La gestion de projet permet de gérer les données de manière centralisée :
• Gestion de tous les fichiers du projet (les fichiers sources mais également ceux des bibliothèques et ceux
générés par le projet).
• Définition des chemins du projet (library path)
• Le mappage des segments du programme et des données à des adresses absolues
• Définition des options pour l’assembleur, le compilateur et le relieur
Version 3.1, juin 2008
Page 58
Informatique 3
La programmation en assembleur
Les environnements de développement modernes (IDE), comme Eclipse ou MS Visual Studio, proposent ces
fonctionnalités.
Version 3.1, juin 2008
Page 59
Informtique 3
Jeu d’instruction du processeur ARM V5
4 Jeu d’instruction du processeur ARM V5
Ce chapitre traite le jeu d’instruction du processeur ARM (c. à d. les instructions, qui peuvent être exécutées par
la CPU). Les instructions ont été partagées dans différents groupes selon leur fonctionnalité. Une description
plus détaillée de ces instructions est fournie dans [1] ou [2]. Tous les exemples concernent le processeur
PXA270 de XScale. Ce dernier implémente je jeu d’instruction ARMV5TE, sans les instructions à virgule
flottante.
Les chapitres suivants traitent uniquement le jeu d’instruction. La description de l’architecture ARM et des ses
registres est fournie par les chapitres 2.4 et 2.5.
4.1 Les instructions
Toutes les 25 instructions de base du processeur sont définies avec des mnemonics (abréviation d’instruction).
Elles sont obtenues systématiquement des lettres initiales des mots, qui décrivent ces instructions en anglais.
Ex. : ADD, ADd with Carry, Reverse SuBtract, Exclusive OR, BIt Clear,
Toutes les instructions possèdent un format unique de 32 bits. Cela génère un certain nombre de limitations, qui
ne sont pas très graves :
• Il n’est pas possible de charger des valeurs directes de 32 bits. Mis à part si ces dernières peuvent être
construite avec une valeur (mantisse) de 8 bits et 4 bits de décalage. Toutes les autres valeurs doivent être
chargées à partir de la mémoire programme.
• Les instructions saut de programme ne possèdent qu’un déplacement de 24 bits (offset). Les sauts de
programme relatifs sont ainsi limités à un espace de ± 32 Mégas bytes, par rapport à l’adresse courante. Des
vrais sauts de programme de 32 bits sont réalisés avec le chargement d’une valeur de 32 bits, dans le registre
du compteur de programme.
• Les instructions Load/Store ne peuvent fonctionner qu’avec un offset de 12 bits. Les accès aux variables
relatifs sont ainsi limités à un espace de 4 kilos bytes, par rapport à l’adresse courante.
Tableau 12 illustre le jeu d’instruction du processeur ARM :
Version 3.1, juin 2008
Page 60
Jeu d’instruction du processeur ARM V5
Informatique 3
Instruction
ADC
ADD
AND
B
BIC
BKPT
BL
BLX
BX
CDP CDP2
CLZ
CMN
CMP
EOR
LDC LDC2
LDM
LDR
MCR MCR2 MCRR
MLA
MOV
MRC MRC2 MRRC
MRS
MSR
MUL
MVN
ORR
PLD
QADD
QDADD
QDSUB
QSUB
RSB
RSC
SBC
SMLAxy
SMLAL
SMLALxy
SMLAWxy
SMULxy
SMULWy
STC STC2
STM
STR
SUB
SWI
SWP
TEQ
TST
UMLAL
UMUL
Fonction
Addition de deux valeurs de 32 bits avec la retenue
Addition de deux valeurs de 32 bits
Opération logique ET entre deux valeurs à 32 bits
Saut relatif ± 32 Mégas bytes
Effacer les bits d’une valeur 32 bits
Point d’arrêt software (break point)
Saut avec stockage de l’adresse de retour (appel de sous-routine)
Saut avec stockage de l’adresse de retour et changement de registre
Saut avec changement de registre
Opération coprocesseur
Compter les zéros, qui précèdent
Comparaison inversée de deux valeurs 32 bits
Comparaison de deux valeurs 32 bits
Opération logique OU exclusive entre deux valeurs 32 bits
Charger le coprocesseur avec une ou plusieurs valeurs 32 bits
Charger plusieurs valeurs de 32 bits depuis la mémoire dans les registres ARM
Charger la valeur avec une adresse virtuelle dans un registre ARM
Charger une ou plusieurs registres ARM dans le coprocesseur
Multiplication et accumulation d’une valeur 32 bits
Charger la valeur 32 bits dans un registre
Charger depuis le processeur dans un ou plusieurs registres
Copier le registre de statut (CPSR ou SPSR) dans un registre ARM
Copier depuis le registre ARM dans un registre d’état (CPSR ou SPSR)
Multiplier deux valeurs de 32 bits
Charger une valeur 32 bits, préalablement inversée, dans un registre
Opération logique OU entre deux valeurs 32 bits
Indique l’adresse de la case mémoire, qui est en train d’être chargée
Addition signée de deux valeurs 32 bits avec limitation du dépassement de capacité
Addition signée double de deux valeurs 32 bits et limitation du dépassement de capacité
Soustraction signée double de deux valeurs 32 bits et limitation du dépassement de
capacité
Soustraction signée de deux valeurs 32 bits avec limitation du dépassement de capacité
Soustraction inverse de deux valeurs 32 bits
Soustraction inverse de deux valeurs 32 bits avec la retenu
Soustraction de deux valeurs 32 bits avec retenu
Multiplication/addition signées (16x16)+32 = 32 Bit
Multiplication/addition larges signées (32x32)+64 = 64 Bit
Multiplication/addition larges signées (16x16)+64 = 64 Bit
Multiplication/addition signées ((32x16)>>16)+32 = 32 Bit
Multiplication signée (16x16) = 32 Bit
Multiplication/addition signées ((32x16)>>16)+32 = 32 Bit
Stocker une ou plusieurs valeurs depuis le processeur dans la mémoire
Stocker plusieurs registres ARM dans le processeur
Stocker des registres à des adresses virtuelles
Soustraire deux valeurs à 32 bits
Interruption software
Echanger les registres ARM avec la mémoire de façon byte ou mot
Comparer deux valeurs 32 bits
Tester un bit dans un registre 32 bits
Multiplication/addition larges non singées (32x32)+64 = 64 Bit
Multiplication large non signée (32x32) = 64 Bit
Tableau 12 : Jeu d’instruction du processeur ARM à partir de la version V5E.
Version 3.1, juin 2008
Page 61
Jeu d’instruction du processeur ARM V5
Informatique 3
4.1.1 La syntaxe des instructions ARM
Le processeur ARM est une machine avec trois opérandes. Toutes les instructions, qui traitent les données, ne
travaillent qu’avec des registres.
Syntaxe :
Opcode
Rd, Rn {,N}
Le code d’opération est une des instructions du Tableau 12.
Tous les registres de r0 à r15 peuvent être utilisés pour Rd et Rn. L’opérande N permet de pré traiter
facultativement un des opérandes avec le décalage à barilier (Barrel Shifter). N peut être une valeur constante, un
registre ou un registre décalé. L’opération de décalage ne modifie pas le contenu du registre source. Toutes les
valeurs constantes ne sont toutefois pas admises, car ces dernières ne peuvent être composées que de valeurs 8
bits décalées dans un registre 32 bits. Des informations plus détaillées concernant les opérations de décalage sont
fournit au chapitre 4.3.2.
Exemple :
Avant :
r5 = 5
r7 = 8
MOV
r7, r5, LSL #2
@ r7 = r5*4 = (r5 << 2)
Après :
r5 = 5
r7 = 20
4.1.2 La syntaxe de la notation
Les descriptions des instructions suivantes utilisent la notation du Tableau 13. Les éléments de la syntaxe, qui
sont souvent utilisé, sont traités plus en détails dans les chapitres suivants.
[ ]
{ }
< >
|
Accès indirect, indexation
Elément facultatif
Un élément parmi d’autres éléments
Choix parmi une liste (ou)
Tableau 13 : Les éléments de la syntaxe pour la description formelle des instructions.
Accès indirect, indexation []
L’accès s’effectue à l’élément, qui est indexé entre parenthèses. L’indexation peut être soit l’adresse d’une case
mémoire ou une position de bit. Ainsi [Rn] représente la valeur de la variable, qui est adressée par l’adresse
stockée dans Rn.
Choix parmi une liste|
Cette notation permet de choisir un élément parmi une liste. LDR
formulation pour LDR {B}.
| LDR
B est par exemple une autre
Un élément parmi une liste <>
La notation <> représente exactement un élément parmi une liste. La liste est en générale soit une collection de
valeur ou un espace d’adressage.
Les éléments facultatifs {}
Les éléments facultatifs dans une expression sont définies entres accolades. La notation LDR{B} est par
exemple une abréviation pour LDR | LDRB.
Les noms de registre
Rd, Rm, Rn, Rs, RdHi & RdLo sont des registres ARM r0-r15.
Ld, Lm, Ln & Ls représentent les registres ARM inférieur r0-r7.
Hd, Hm, Hn & Hs représentent les registres ARM supérieurs r8-r15.
Cd, Cm & Cn sont des registres du coprocesseur dans la zone c0-c15
Version 3.1, juin 2008
Page 62
Informatique 3
Jeu d’instruction du processeur ARM V5
sp, lr et pc sont des synonymes pour r13, r14 et r15.
Rn[a] représente le bit a de la valeurs, qui est stockée dans le registre Rn.
Rn[a:b] représente la suite des bits depuis la position a jusqu’à b du contenu du registres Rn.
RdHi:RdLo représente une valeur 64 bits. RdHi est ainsi le mot de poids le plus fort et RdLo le mot de poids
le plus faible.
Les valeurs constantes
<immedN> représente une valeur entière, qui est représentée avec N bits. Ainsi <immed8> représente une
valeur dans le domaine 0..255.
<immedN>*size représente une suite de nombres, avec des pas successifs size. Ainsi <immed5>*4
représente une valeur parmi 0, 4, 8, …, 124.
<AddressN> est une adresse de case mémoire, représenté avec un déplacement (offset) relatif. L’adresse doit
se situer dans la zone pc-2N <= adresse < pc+2N.
<A-B> représente une valeur entière dans la zone A à B.
<rotated_immed> est une valeur 32 bits, qui est représentée par une valeur 8 bits non signées et qui peut être
déplacé vers la gauche ou vers la droite par pas de deux bits. C'est-à-dire que par exemple <rotated_immed>
est équivalent à <immed8> ROR (<immed4>*2).
Le code d’état du programme
<cond> représente tous les bits du registres d’état du processeur ARM selon le Tableau 14.
Les opérations de décalage
<imm_shift> représente l’argument de décalage, qui est une constante. Le domaine de validité de cette
constante dépend naturellement du type de l’opération de décalage, comme Par exemple : LSR: #<1-31>,
ASR: #<1-32>.
<reg_shift> est l’argument de décalage, qui est représenté par le contenu d’un registre.
<shift> comprend à la fois <imm_shift> et <reg_shift>.
4.1.3 Exécution d’instruction conditionnelle
Presque toutes les instructions peuvent être exécutées de façon conditionnelle. Les sauts conditionnels peuvent
ainsi être évités dans la plupart des procédures. Les sauts nécessitent une vidange du pipeline des instructions. Ce
qui engendre des temps d’attente supplémentaires.
Les conditions, qui doivent être évaluées pour l’exécution des instructions conditionnelles, sont lues à partir des
bits du registre d’état courant du programme (CPSR). Ces derniers sont normalement fixés par l’instruction, qui
a été exécutée en dernier par le processeur (en générale des opérations de comparaison). La condition est notée
comme suffixe (ou code de condition) après l’instruction. Le Tableau 14 contient les différentes conditions.
Les opérations non comparatives, qui sont exécutées par l’unité arithmétique (ALU), peuvent également
influencer les bits d’état. Dans ce cas il faut ajouter un S au code d’opération. Les opérations arithmétiques
peuvent influencer les bits N, Z, C et V ; les opérations logiques les bits N et Z ; et le décalage à barillet (barrelshifter) uniquement le bit C.
Version 3.1, juin 2008
Page 63
Jeu d’instruction du processeur ARM V5
Informatique 3
Condition
EQ
NE
CS,HS
CC,LO
MI
PL
VS
VC
HI
LS
GE
LT
GT
LE
Drapeau (flag)
Z
!Z
C
!C
N
!N
V
!V
C && !Z
!C && Z
(N == V)
(N != V)
!Z et (N == V)
Z ou (N != V)
Description
Egalité
Inégalité
Plus grand que ou égalité (non signé)
Plus petit (non signé)
Minus, négatif
Positif ou nul
Dépassement de capacité (Overflow)
Pas de dépassement de capacité
Plus grand que (non signé)
Plus petit que ou égalité (non signé)
Plus grand que ou égalité (signé)
Plus petit que (signé)
Plus grand que (signé)
Plus petit que ou égalité (signé)
Tableau 14 : Les conditions (condition code) pour les instructions conditionnelles
Les instructions LO ou HS peuvent être utilisées au lieu de CC ou CS. Ces dernières, comme les instructions LS
et HI, se réfèrent à des opérations de comparaison non signée. Par contre LT, GE, LE et GT se réfèrent à des
opérations de comparaison signée. Le suffixe AL (always) doit être mentionné pour des raisons d’intégralité. Ce
dernier existe de façon formelle et représente la condition standard en absence de suffixe. Toutefois l’assembleur
gcc ne l’admet pas comme suffixe en présence d’instructions.
Exemple :
Définition du GGT (a, b), qui peut être défini dans un langage de programmation évoluée à l’aide d’une
division en chaîne de la manière suivante :
while (a != b)
if (a > b)
a -= b;
else
b -= a;
Un première implémentation en assembleur ARM avec les registres r1 et r2 pour le stockage respectif de a et
b:
ggt: CMP
BEQ
BLT
SUB
B
aIsSmaller:
SUB
B
endIf:
r1, r2
endIf
aIsSmaller
r1, r1, r2
ggt
r2, r2, r1
ggt
Cette solution est basée sur des sauts de programme. A chaque saut il faut vider le pipeline des instructions, ce
qui ralenti fortement le temps d’exécution du programme. Les instructions conditionnelles permettent de réduire
ce temps d’exécution. De plus le programme devient plus court.
ggt: CMP
SUBGT
SUBLT
BNE
endIf:
r1, r2
r1, r1, r2
r2, r2, r1
ggt
Le registre de compteur de programme peut être utilisé comme registre de destination avec toutes les opérations
ALU. Les processeurs ARM soutiennent les formats petit et gros boutiste (little and big endian). Le standard est
cependant petit boutiste.
4.1.4 Le jeu d’instruction Thumb
Le jeu d’instruction Thumb est un jeu d’instruction à 16 bits. Ce dernier est pratiquement équivalent au jeu
d’instruction ARM à 32 bits. Il permet de densifier le code (souvent à plus de 50%). Ce qui entraîne une
amélioration de la performance dans de nombreux cas. Le jeu d’instruction Thumb n’est cependant pas aussi
Version 3.1, juin 2008
Page 64
Informatique 3
Jeu d’instruction du processeur ARM V5
clairement structuré que celui d’ARM. Le chapitre 6 traite ce sujet plus en détails.
4.1.5 Les coprocesseurs
La plupart des processeurs ARM sont implémentés en tant que cœur de processeur. Souvent ils contiennent des
coprocesseurs pour les opérations de calcul vectoriel à virgule flottante (en anglais Vector Floating Point et
abrégé par VFP), la gestion de la mémoire (MMU) et le traitement du signal (DSP).
Le coprocesseur CP15 est destiné au contrôle du système. Il permet de gérer la mémoire cache, la mémoire
externe (MMU), les opérations d’écriture et de lecture à l’aide de tampon et d’autre option du système.
Les processeurs, qui soutiennent le VFP, contiennent le CP10 pour les opérations arithmétique à virgule flottante
de précision simple et le CP11 pour les opérations de précision double. L’ARM V5TE, qui est utilisé avec la
carte de développement CARME, ne possède pas de coprocesseur à virgule flottante.
4.2 La vue d’ensemble du jeu d’instructions
Les opérations du jeu d’instruction ARM peuvent être réparties dans les groupes suivants :
• Les transferts de données
• Les instructions arithmétique et logiques
- L’arithmétique des entiers
- Les instructions logiques
- Les instructions de décalage et de rotation
- Les manipulations de bit
• Sauts de programme
- Sauts non conditionnels
- Sauts conditionnels
• System Control
Les chapitres suivants traitent ces groupes d’instructions.
4.3 Les transferts de données
Le processeur ARM, de par son architecture RISC, ne connaît que les opérations de transfert de données entres
registres (MOV), depuis la mémoire externes aux registres (LDR ) et depuis les registres à la mémoire externes
(STR). Les transferts de données entres mémoires externes ne sont pas possibles. Ils peuvent être réalisés de
façon byte (8 bits), demi mot (16 bits) et mot (32 bits). Cependant, l’accès mot ne peut être réalisée qu’avec
adressage mot, c'est-à-dire modulo 4 (.align 4).
Version 3.1, juin 2008
Page 65
Jeu d’instruction du processeur ARM V5
Informatique 3
Instruction
SWP
Opérande
Reg1,Reg2,Reg3
MOV
Reg,Op2
Opération
Reg2 -> [Reg3],
Reg1 <- [Reg3]
Reg := Op2
MVN
Reg,Op2
Reg := ~OP2
LDR
Reg, Address
Reg := [address]
STR
Reg, Address
[address] := Reg
MSR
Reg
PSR := Reg
MRS
Reg
Reg := PSR
MCR
p#, op, cReg,
Reg1, Reg2
cReg := Reg1 {op Reg2}
MRC
p#, op, Reg1,
Reg2
Reg := cReg1 {op cReg2}
LDC
cReg := [Address]
LDM
p#, cReg,
Address
p#, cReg,
Address
Rbase,{Rlist}
STM
Rbase,{Rlist}
{Rlist} -> [Rbase]
STC
[Address] := cReg
[Rbase] -> {Rlist}
Description
Echange le contenu du registre avec la
mémoire
Copier le contenu d’un registre ou une
valeur constante dans un registre
Copier le complément à un du contenu
d’un registre ou d’une valeur constante
dans un registre
Charger le contenu de la mémoire dans
un registre
Stocker le contenu d’un registre dans la
mémoire
Copier le contenu du registre dans le
registre d’état du programme PSR
(Status/Flags)
Copier le contenu du registre PSR
(Status/Flags) dans un registre
Exécuter l’opération op à l’aide du
coprocesseur p# et stocker le résultat
dans le registre du coprocesseur.
Exécuter l’opération op à l’aide du
coprocesseur p# et stocker le résultat
dans le registre Reg2.
Charger le registre du coprocesseur
avec le contenu de la mémoire
Charger le registre du coprocesseur
avec le contenu de la mémoire
Charger plusieurs registres avec le
contenu de la mémoire (pile pop)
Stocker le contenu de plusieurs dans la
mémoire (pile push)
Tableau 15 : Les instructions de transfert de données, entre registres et depuis les registres à la mémoire
externe.
4.3.1 Les instruction de transfert de données entre registres MOV,
MVN
Ces instructions permettent de transférer les données entre registres mais, également, de charger les registres
avec des valeurs constantes.
La syntaxe générale est la suivante :
<MOV|MVN>{<cond>}{S}
Rd, N
Le code d’opération MOV charge une valeur alors que MVN en charge le complément. Un suffise <cond>, qui
correspond au code de condition fourni au Tableau 14, peut être ajouté pour des réalisations conditionnelles.
Quand au suffixe S, il permet à l’opération de changer les bits d’état courant du processeur. L’opérande Rd
représente toujours le registre de destination, alors que l’opérande N peut représenter soit le contenu d’un registre
(éventuellement décalé) ou une valeur constante.
Exemple :
MOV
MOVS
MVN
MOV
r0,
r0,
r1,
pc,
r1
#10
r0
lr
@
@
@
@
r0 := r1
r0 := 10, fixe les bit d’état courant du programme
r1 := ~r0
retour depuis la sous-routine
4.3.2 Le décalage à barilier (Barrel Shifter)
Les opérandes, qui sont contenus dans des registres (Rm), peuvent être prés décalés à l’aide du décalage à
Version 3.1, juin 2008
Page 66
Jeu d’instruction du processeur ARM V5
Informatique 3
barilier. La valeur de cet opérande peut ainsi être déplacée de 0 à 32 bits vers la gauche ou vers la droite, en
fonction de l’instruction. L’opération de décalage est toujours réalisée en un seul cycle d’horloge,
indépendamment du nombre de bits du décalage. La valeur originale du registre Rm n’est pas changée.
L’ALU traite effectivement la valeur contenue dans le registre Rn et celle fournie par le décalage à barilier N.
Rn
Rm
Barrel-Shifter
Zwischenresultat N
ALU
Rd
Figure 67 : ALU avec le décalage à barilier
Certaines instructions de traitement de données comme MUL, CLZ ou QADD ne sont pas en mesure d’utiliser le
décalage à barilier. Dans ces cas, la valeur du registre Rm ne peut être utilisé que de façon directe.
Exemple :
Avant l’opération arithmétique, le contenu du registre Rm est décalé de deux bits vers la droite (LSR). Ce qui
correspond à une division par 4 de la valeur du registre. L’opération de décalage est équivalent à l’opérateur >>
du langage de programmation C.
Avant :
r0 = 0x11
r1 = 0x22
MOV
r0, r1, LSR #2
@ r0 = r1 / 4
Après :
r0 = 0x8
r1 = 0x22
Le décalage à barilier connaît 5 sortes d’opération de décalage. Ces derniers sont fournis dans le Tableau 16 :
Instruction
Effet
Opération
Résultat
LSL
LSR
ASR
Décalage logique vers la gauche
Décalage logique vers la droite
Décalage arithmétique vers la
droite
Rotation vers la droite
Extension de la rotation vers la
droite
x LSL y
x LSR y
x ASR y
x << y
(non signé) x >> y
(signé) x >> y
Domaine de
décalage
#0-31 ou Rs
#1-31 ou Rs
#1-31 ou Rs
x ROR y
x RRX
((non signé) x>>y) | (x << (32-y))
(cflag << 31)|((non signé) >> 1)
#1-31 ou Rs
1 (fixe)
ROR
RRX
Tableau 16 : Les opérations du décalage à barilier,
ou x représente la valeur à décaler et y le nombre de bit du décalage.
La syntaxe du décalage permet de définir le nombre de bit à décaler soit sous forme direct #shift ou à l’aide
d’un registre Rs, qui contient le nombre de bit du décalage. Le Tableau 17 illustre pratiquement toutes les
formulations possibles.
Version 3.1, juin 2008
Page 67
Jeu d’instruction du processeur ARM V5
Informatique 3
Opération de décalage pour N
Décaler selon la valeur constante #shift
La valeur du registre
Décalage logique vers la gauche en fonction de la valeur constante #shift
Décalage logique vers la gauche en fonction du registre Rs
Décalage logique vers la droite en fonction de la valeur constante #shift
Décalage logique vers la droite en fonction du registre Rs
Décalage arithmétique vers la droite en fonction de la valeur constante #shift
Décalage arithmétique vers la droite en fonction registre Rs
Rotation vers la droite en fonction de la valeur constante #shift
Rotation vers la droite en fonction du registre Rs
Rotation vers la droite étendue (33-Bit Rotation)
Syntaxe
#shift
Rm
Rm, LSL
Rm, LSL
Rm, LSR
Rm, LSR
Rm, ASR
Rm, ASR
Rm, ROR
Rm, ROR
Rm, RRX
#shift
Rs
#shift
Rs
#shift
Rs
#shift
Rs
Tableau 17 : La syntaxe des différentes opérations du décalage à barilier.
Exemple :
L’opération MOVS copie le contenu du registre r1, préalablement décalé de un bit vers la gauche, dans le
registre r0. Du fait que l’instruction contient le suffixe S, elle est en mesure de changer le contenu du registre
d’état courant du programme. Le bit 31 du registre r1 est ainsi copié dans le bit de carry.
Avant :
CPSR = nzcvqift_USER
r0 = 0x00000000
r1 = 0x80008001
MOVS
(Majuscule: mise à un, minuscule: mise à zéro)
r0, r1, LSL #1
Après :
CPSR = nzCvqift_USER
r0 = 0x00010002
r1 = 0x80008001
n z c v
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
0 0 0 0
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
cpsr
r1
r0
0 0 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
n z c v
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
0
Werden gesetzt bei einer
Instruktion mit S-Suffix
Figure 68 : L’instruction MOVS avec une opération de décalage LSR #1. Le bit 31 est copié dans le bit de carry
du registre d’état courant du processeur, car l’instruction MOV a été définie avec le suffixe S.
4.3.3 Les instructions de chargement de données LDR
et STR
Les instructions de chargement de données permettent de transférer les données depuis la mémoire aux registres,
ou inversement. Le chargement d’une valeur constante dans un registre, qui ne peut pas être réalisé directement
avec les instructions MOV ou MVN, est également réalisé avec l’instruction LDR . Toutes les instructions de
chargement, mis à part LDRD et STRD, peuvent être exécutées pour des types de données mot, demi mot ou
byte. Le Tableau 18 fournit une vue d’aperçu de ces instructions.
Version 3.1, juin 2008
Page 68
Jeu d’instruction du processeur ARM V5
Informatique 3
Instruction
LDR
STR
LDRB
STRB
LDRH
STRH
LDRSB
LDRSH
Description
Charger un mot dans un registre
Stocker un mot à partir d’un registre
Charger un byte dans un registre
Stocker un byte à partir d’un registre
Charger un demi mot dans un registre
Stocker un demi mot à partir d’un registre
Charger un byte signé dans un registre
Charger un demi mot signé dans un registre
STRD
Stocker deux mots à partir de registres (DSP)
LDRD
Stocker deux mots dans des registres (DSP)
Effet
Rd := mem32[Adresse]
Mem32[Adresse] := Rd
Rd := mem8[Adresse]
mem8[Adresse]:= Rd
Rd := mem16[Adresse]
mem16[Adresse] := Rd
Rd := (signExtend) mem8[Adresse]
Rd := (signExtend)
mem16[Adresse]
Mem32[Adresse] := Rd
Mem32[Adresse+4] := R(d+1)
Rd=Mem32[Adresse]
R(d+1)=Mem32[Adresse+4]
Tableau 18 : Les opérations de chargement. Le bit de signe est dupliqué avec les transferts de données signées.
La syntaxe des instructions LDR et STR est la suivante :
<LDR|STR>{<cond>}{B|H|D}
LDR{<cond>}{SB|SH}
Rd, <Address>
Rd, <Address>
L’adresse de la case mémoire peut être définie de plusieurs manières. Dans les cas les plus simples, cette
dernière peut être une constante ou un registre. Les modes d’adressage sont traités plus en détails dans le chapitre
suivant.
Les instructions LDR
D et STRD sont des extensions du jeu d’instruction DSP. Ces dernières permettent
respectivement de charger et de stocker le contenu de deux registres juxtaposés. La condition pour Rd est un
registre avec un numéro paire. Par exemple, l’instruction STRD avec Rd = r2 stockent le contenu des registres
r3 et r4 dans la mémoire.
Exemple :
Les instructions LDR et STR permettent respectivement de charger et de stocker les données dans la mémoire.
La condition pour l’adressage de la case mémoire est son alignement avec les types de données à transférer.
C'est-à-dire que cette dernière doit être modulo 4 pour les accès mot et paires pour les accès demi mot.
/* Charge le registre r0 avec la valeur contenu par la case mémoire,
qui est adressée par le registre r5. */
LDR
r0, [r5]
/* Stocker le contenu du registre r0 dans la case mémoire,
qui est adressée par le registre r5. */
STR
r0, [r5]
/* Charge le registre r0 avec la valeur contenu par la case mémoire,
qui est adressée par le symbole myvar
(myvar doit être définie dans le même segment). */
STR
r0, myvar
4.3.4 Modes d’adressage pour les instructions de chargement et de
stockage
L’architecture ARM prévoit de nombreux modes d’adressage. L’adresse de la case mémoire à accéder est
toujours composée d’une adresse de base et d’un indexe (c. à d. un déplacement). La base est contenue dans
n’importe quel registre, mis à part celui du compteur de programme pc.
Selon la formule de lecture ARM, les modes d’adressage sont qualifiés de « méthode d’indexation ». Il existe
fondamentalement trois méthodes d’indexations. Ces dernières peuvent être complétés avec des nombreuses
variantes de calcul du déplacement (offset).
Version 3.1, juin 2008
Page 69
Jeu d’instruction du processeur ARM V5
Informatique 3
Méthode d’indexation
Données
Pré indexation avec retour
Pré indexation
Post indexation
mem[Basis+Offset]
mem[Basis+Offset]
mem[Basis+Offset]
Registre contenant
l’adresse de base
Basis+Offset
Basis+Offset
Basis+Offset
Exemple
LDR r0,[r1,#2]!
LDR r0,[r1,#2]
LDR r0,[r1],#2
Tableau 19 : Les méthodes d’adressage (d’indexation) pour l’accès à la mémoire. Le déplacement est toujours
une grandeur signée. Par exemple, ce dernier peut être défini comme une valeur ± 12 bits.
Dans la méthode pré indexation, l’adresse de la case mémoire est obtenue par addition du contenu du registre de
base avec le déplacement. Le contenu du registre de base reste constant durant toute l’opération de transfert.
Cependant, si l’on défini une récriture en retour (write back) avec « ! », la nouvelle adresse est copié dans le
registre de base avant le transfert de données.
La méthode post indexation reprend également la nouvelle adresse, mais après le transfert de données.
Les méthodes post et pré indexation avec write back sont surtout utilisées pour les accès aux Tableaux (array).
Quant à la méthode pré indexation, elle est souvent utilisée pour accéder aux structures de données.
Exemple :
L’exemple suivant montre les accès avec les modes d’adressage selon le Tableau 19, avec les valeurs des
registres avant et après l’exécution du transfert de données. Toutes les instructions possèdent la même situation
initiale.
Avant :
r0 = 0x000000000
r1 = 0x000100000
mem32[0x00010000]=0x10101010
mem32[0x00010004]=0x20202020
Pré indexation avec write back
LDR
r0, [r1, #4]!
Après :
r0 = 0x20202020
r1 = 0x00010004
Pré indexation :
LDR r0,[r1,#4]
Après :
r0 = 0x20202020
r1 = 0x00010000
Post indexation :
LDR r0,[r1],#4
Après :
r0 = 0x10101010
r1 = 0x00010004
Il existe de nombreuses variantes pour le calcul du déplacement (offset) : des valeurs direct, des contenus de
registre ou des contenus de registre décalés. Tableau 20 fournit une vue d’aperçu des modes d’adressage pour les
accès du type mot ou byte non signés.
Version 3.1, juin 2008
Page 70
Jeu d’instruction du processeur ARM V5
Informatique 3
Mode d’adressage
Pré indexation avec un offset constant
Pré indexation avec un offset registre
Pré indexation avec un décalage de l’offset registre
Pré indexation avec write back et un offset constant
Pré indexation avec write back et un offset registre
Pré indexation avec write back et un décalage de l’offset
registre
Post indexation avec un offset constant
Post indexation avec un offset registre
Post indexation avec un décalage de l’offset registre
Syntaxe
[Rn, #±<offset12>]
[Rn, ±Rm]
[Rn, ±Rm, shift #<shift_value>]
[Rn, #±offset12]!
[Rn, ±Rm]!
[Rn, ±Rm, shift #<shift_value>]!
[Rn], #±<offset12>
[Rn], ±Rm
[Rn], ±Rm, shift #<shift_value>
Tableau 20 : La syntaxe des modes d’adressage pour les accès simple de type mot
Des limitations existent pour les autres instructions. Par exemple, les instructions STRSB, STRSH, STRH et
STRB ne peuvent pas utiliser le décalage à barilier (barrel-shifter). De plus le déplacement est limité à +/- 8 bits
autour de l’adresse de base.
Mode d’adressage
Pré indexation avec un offset constant
Pré indexation avec un offset registre
Pré indexation avec write back et un offset constant
Pré indexation avec write back et un offset registre
Post indexation avec un offset constant
Post indexation avec un offset registre
Syntaxe
[Rn, #±<offset8>]
[Rn, ±Rm]
[Rn, #±<offset8>]!
[Rn, ±Rm]!
[Rn], #±<offset8>
[Rn], ±Rm
Tableau 21 : Les méthodes d’adressage autorisées pour les types de données signés et non signés.
Exemple en conclusion :
@ stock r1 in [r2+r4] and copy the base address r2+r4 in r2
str
r1, [r2, r4]!
str
r1, [r2], r4
@ stock r1 in [r2] and copy the base address r2+r4 in r2
str
r1, place
@ stock r1 pc relative in place
ldr
r1, [r2, #16]
@ load r1 with [r2+16]. r2 will not change
ldr
r1, [r2, r3, LSL#2]
@ load r1 with [r2+r3*4] laden
@ conditional load the byte of r1 with [r2+5].
@ the bits D8 up to D31 will be full with zero.
ldreqb r1,[r2,#5]
4.3.5 L’instruction SWP
L’instruction SWP permute le contenu d’un registre avec celui d’une case mémoire. Elle représente ainsi une
combinaison des instructions STR et LDR . Elle est exécuté comme une instruction atomique à l’aide du
système de bus, et ne peut ainsi pas être interrompue par une interruption jusqu’à ce que le transfert de données
ne
soit
terminé.
La syntaxe est la suivante :
SWP{<cond>}{B}
Rd, Rm, [Rn]
Instruction
SWP
Description
Echange de mot entre le registre et
la mémoire
SWPB
Echange de byte entre le registre et
la mémoire
Déroulement interne
tmp = mem32[Rn]
mem32[Rn] = Rm
Rd = tmp
tmp = mem8[Rn]
mem8[Rn] = Rm
Rd=tmp
Tableau 22 : Effet des instruction SWP et SWPB
Version 3.1, juin 2008
Page 71
Jeu d’instruction du processeur ARM V5
Informatique 3
Exemple :
L’instruction SWP charge la donnée depuis la case mémoire 0x0001A000 dans le registre r0 et copie le
contenu du registre r1 dans la case mémoire 0x0001A000.
Avant :
r0 = 0x555555555
r1 = 0xAAAAAAAAA
r2 = 0x0001A0000
mem32[0x0001A000]=0x10101010
SWP
r0, r1, [r2]
Après :
r0 = 0x10101010
r1 = 0xAAAAAAAAA
r2 = 0x0001A0000
mem32[0x0001A000]=0xAAAAAAAA
ARM- Prozessorregister
r0
0x55555555
0x10101010
r1
0xAAAAAAAA
r2
0x0001A000
Arbeitsspeicher (RAM)
0x19FFC
0x10101010
0xAAAAAAAA
r3
0x1A004
r4
0x1A008
r5
0x1A00C
r6
0x1A010
r7
0x1A014
r15
4.3.6 Chargement et stockage multiple LDM et STM
Les opérations de chargement et de stockage multiple LDM et STM permettent de transférer le contenu d’un bloc
de registres ou de mémoire avec une seule instruction. Ce type de transfert est plus efficace que celui avec
plusieurs instructions de transfert simples.
L’exécution des instructions LDM et STM nécessite 2+N*t cycles d’horloge ; ou N représente le nombre de
registres à transférer et t le nombre de cycle d’horloge nécessaire pour accéder à la mémoire externe. Ces
instructions sont également atomiques, c'est-à-dire qu’elles ne peuvent pas être interrompues par des
interruptions. L’utilisation des instructions LDM et STM peut par conséquent détériorer le temps de latence du
traitement des interruptions.
La syntaxe des instructions LDM et STM est la suivante :
<LDM|STM>{<cond>}<AddressMode>
Rn{!}, <RegisterBloc>{^}
Le mode d’adressage définit l’accès mémoire selon le Tableau 23. Il est possible de travailler avec des adresses
croissantes (incrémentation) ou décroissantes (décrémentation). De plus, le calcul de la nouvelle adresse peut
être effectué avant ou après le transfert des données. La nouvelle adresse peut également être écrite dans le
registre Rn, comme la pré indexation avec l’écriture en retour (write back) !
Mode d’adressage
IA
IB
DA
DB
Description
Incrémenter après
Incrémenter avant
Décrémenter après
Décrémenter avant
Adresse de départ
Rn
Rn+4
Rn-4*N+4
Rn-4*N
Adresse d’arrivée
Rn+4*N-4
Rn+4*N
Rn
Rn-4
Rn!
Rn+4*N
Rn+4*N
Rn-4*N
Rn-4*N
Tableau 23 : Les modes d’adressage pour les instructions LDM et STM.
Ces derniers définissent la méthode de calcul de l’adresse de la case mémoire.
Le registre Rn contient l’adresse mémoire, ou les données ont été lues ou déposées dans la mémoire. Si le
registre a été défini avec un opérateur d’écriture en retour (!), la nouvelle adresse sera écrite dans le registre,
Version 3.1, juin 2008
Page 72
Jeu d’instruction du processeur ARM V5
Informatique 3
comme avec les instruction LDR et STR. Le bloc de registre est défini entre accolades. Ce dernier contient tous
les registres, dont le contenu doit être transféré, soit par énumération avec des virgules ({r0, r3, r6}) ou
sous forme de domaine avec un trait d’union ({r0-r3}). Il n’y a pas de règle concernant la définition par
énumération des registres. Cependant, les registres avec les numéros les plus bas sont transportés en premier.
Lorsque cette instruction est exécutée dans un mode privilégié, l’opérateur « ^ » permet d’accéder aux registres
appartenant au mode utilisateur. La condition pour cela est de ne pas mentionner le registre pc et le bloc des
registres.
Exemple :
Les exemples suivants montrent l’effet des quatre modes d’adressage du Tableau 23, pour le stockage des
registres r0, r4 et r1 dans la mémoire à partir de l’adresse 0x00010000.
STMIA r9!,{r0,r1,r4}
r9start
r0
0x00010000
STMIB r9!,{r0,r1,r4}
r9start
0x00010000
r0
r1
r4
r1
r9end
r9end
r4
0x00010010
0x00010010
STMDA r9!,{r0,r1,r4}
STMDB r9!,{r0,r1,r4}
0x0000FFF0
r9end
0x0000FFF0
r9end
r1
r0
r4
r1
r9start
r4
r0
0x00010000
r9start
0x00010000
Exercice :
Le bloc des registres r0 à r4 doit être stocké dans la mémoire à partir de l’adresse 0x0001A000, dans un
ordre croissant. Le registre r6 doit être utilisé comme pointeur et il doit contenir, à la fin de l’instruction, la
dernière adresse mémoire. C'est-à-dire qu’il doit adresser le contenu du registre r4.
Solution :
Premièrement, il faut utiliser l’opérateur d’écriture en retour (!), afin que r6 contienne la dernière adresse après
l’exécution de l’instruction. Ensuite, il faut choisir le mode incrémenter avant, pour que r6 adresse le dernier
élément. Finalement, il faut soustraire 4 à l’adresse mémoire, afin que le programme écrive le contenu du
premier registre à l’adresse 0x0001A000.
ARM- Prozessorregister
Arbeitsspeicher (RAM)
r0
LDR
r6,0x0001A000-4
STMIB r6!,{r0-r4}
r1
r2
r3
0x0001A000-4
r6start
r0
0x0001A000
r4
r5
r6 0x0001A000-4
0x0001A010
r7
r1
r2
r4
0x0001A000
r6 start
r0
0x0001A004
r1
0x0001A008
r2
0x0001A00C
r3
0x0001A010
r4
r6end
0x0001A014
r3
r6end
0x00019FFC
0x0001A010
r15
4.3.7 Les instructions de la pile
Le processeur ARM ne connaît pas d’instruction pour la pile, contrairement aux autres processeurs. Les accès
pile sont réalisés avec les instructions LDM et STM. La gestion de la pile s’effectue à l’aide du pointeur de pile
sp. Ce dernier est associé de façon conventionnelle au registre r13.
Les architectures ARM permettent de conFigurer librement le fonctionnement de la pile. Par exemple, la pile
Version 3.1, juin 2008
Page 73
Jeu d’instruction du processeur ARM V5
Informatique 3
peut croître soit de façon ascendante (vers les adresses les plus hautes) ou de façon descendante (vers les
adresses les plus bas). Le mode d’adressage du pointeur de pile est également configurable. Ce dernier peut
adresser soit le dernier élément stocké, en mode plein (Full), ou la prochaine case libre, en mode vide (Empty).
La pile devrait être configurée soit de façon conventionnelle ou en fonction de codes déjà existants. Le standard
d’appel de procédure ARM-Thumb (ARM-Thumb Procedure Call Standard ≡ ATPCS) recommande d’utiliser la
pile en modes décroissant et plein (Full Descending). Les opérations « push » sont ainsi réalisées avec STMFD et
celles « pop » avec LDMFD (voir Tableau 24).
Le Tableau 24 illustre les différentes opérations push et pop en fonction des modes de configuration introduit cidessus :
Mode
d’adressage
FA
FD
EA
ED
Description
pop
=LDM
push
=STM
Full Ascending
Full Descending
Empty Ascending
Empty Descending
LDMFA
LDMFD
LDMEA
LDMED
LDMDA
LDMIA
LDMDB
LDMIB
STMFA
STMFD
STMEA
STMED
STMIB
STMDB
STMIA
STMDA
Tableau 24 : Les modes d’adressage pour les accès pile push et pop,
avec leur réalisation à l’aide des instructions LDM et STM.
Exemple :
Selon ATPCS, les opérations avec la pile doivent être réalisées en mode FD. La pile croît ainsi de façon
descendante et le pointeur de pile adresse son dernier élément.
STMFD sp!,{r1,r2}
Vorher:
r1=0x00000005
r2=0x00000006
sp=0x00020014
leer (undefiniert)
Nachher:
r1=0x00000005
r2=0x00000006
sp=0x0002000C
sp
0x00000005
leer (undefiniert)
sp
0x00000002
0x0002000C
0x00000006
0x00020014
0x00000002
0x00000001
0x00000001
L’ajout du caractère « ^ » après les accolades a les conséquences suivantes :
1. Lorsque le registre pc fait parti de la liste des registres de l’instruction LDM, le contenu du registre CPSR
sera également rechargé. Avec l’instruction STM, ce dernier sera toujours stocké.
2. Avec les modes privilégiés, lorsque le registre pc n’est pas mentionnés dans la liste des instructions LDM et
STM, l’accès est réalisé sur les registres d’origine du mode utilisateur et sur les copies (Par exemple : r8 à
r12 dans le mode FIQ) de r13 et r14.
Exemple :
L’opération push avec STMED a pour conséquence, que le pointeur de pile adresse la prochaine case vide de la
pile.
STMED sp!,{r1,r2}
Vorher:
r1=0x00000005
r2=0x00000006
sp=0x00020014
leer (undefiniert)
Nachher:
sp
leer (undefiniert)
sp
leer (undefiniert) 0x00020014
r1=0x00000005
r2=0x00000006
sp=0x0002000C
leer (undefiniert)
0x0002000C
0x00000005
0x00000006
0x00000002
0x00000002
0x00000001
0x00000001
4.3.8 Les instructions d’état MRS et MSR
Les instructions d’état permettent de transférer des données dans le registre d’état du programme (Program
Version 3.1, juin 2008
Page 74
Jeu d’instruction du processeur ARM V5
Informatique 3
Status Register ≡ PSR). L’instruction MSR permet d’écrire dans les registres CPSR (current program status
register) et SPSR (saved program status register). Inversement l’instruction MRS permet d’écrire le contenu des
registres CPSR et SPSR dans la mémoire.
La syntaxe des instruction MRS et MSR et la suivante :
MRS{<cond>}
Rd, <CPSR|SPSR>
MSR{<cond>}
<CPSR|SPSR>_<field>,Rm
MSR{<cond>}
<CPSR|SPSR>_<field>,#Directvalue
L’étiquette « field » définie la zone du registre CPSR, dans laquelle if faut écrire (voir Figure 69). field
peut être une combinaison des caractère suivants : Control (c), Extension (x), Status (s) et Flags (f). Donc Par
exemple : CPSR_c ou CPSR_cf.
Fields
Flags [24:31]
Status [16-23]
Extension [8:15]
Bit 31 30 29 28 27
Control [0:7]
7 6 5 4
N Z C V Q
not used
I
F T
0
Mode
Figure 69 : Organisation des bits d’état dans le registre CPSR
Exemple :
Contrairement aux nombreux autres types de processeurs, les processeurs ARM ne possèdent pas d’instructions
pour libérer ou masquer les interruptions. Cela est réalisé avec la mis à un ou à zéro du bit 6 pour le FIQ et du bit
7 pour le IRQ. La mise à zéro du drapeau I dans le champ de contrôle permet de libérer les interruptions IRQ.
Pour cela il faut d’abord sauver le contenu du registre CPSR dans un registre de travail (dans cet exemple r1).
Ensuite il faut effacer le bit 7. Et finalement il faut transférer le nouvel état dans le registre CPSR.
Avant :
CPSR = nzcvqIFt_SYS
@ Enable IRQ interruption
MRS
r1, CPSR
BIC
r1, r1, #x80
MSR
CPSR_c, r1
@ Clear bit 7
Après :
CPSR = nzcvqiFt_SYS
Cet exemple part du principe que le processeur se trouve dans un mode privilégié (dans cet exemple le mode
SYS). Dans le mode utilisateur, le processeur est capable de lire le contenu du registre CPSR, mais il ne peut
changer que les bits du champ des drapeaux (les bits 24 à 31).
4.3.9 Les instructions du coprocesseur LDC, STC, MRC, MCR et CDP
Les instructions LDC, STC, MRC et MCR permettent de transférer les données depuis et au coprocesseur selon le
Tableau 25. Ces instructions fonctionnent de la même manière que celles LDR
et STR. Les instructions
coprocesseur représentent une extension du jeu d’instruction de base du processeur. Dans l’architecture ARM, la
gestion de la mémoire (MMU, cache) et les autres ajustements du système sont réalisés par le coprocesseur. Le
calcul effectif est démarré dans le processeur principal avec CDP.
La syntaxe des instructions coprocesseur est la suivante :
<LDC | STC>{<cond>}
<MRC | MCR>{<cond>}
CDP{<cond>}
CDP2
<MRC2 | MCR2>
<LDC2 | STC2>
Version 3.1, juin 2008
cp,
cp,
cp,
cp,
cp,
cp,
cd, AddressMode
opcode1, rd, cd, cm {, opcode2}
opcode1, cd, cn {,opcode2}
opcode1, cd, cn {,opcode2}
opcode1, rd, cd, cm {, opcode2}
cd, AddressMode
Page 75
Jeu d’instruction du processeur ARM V5
Informatique 3
cp représente le numéro du coprocesseur. Ce dernier se situe entre cp0 et cp15. Le coprocesseur 15 (CP15) est
réservé pour la configuration du système. Ce qui comprend la gestion de la mémoire et du cache. Les registres
cn, cm et cd sont les registres internes du coprocesseur. L’opération effective du coprocesseur est définie avec
le code d’opération opcode. Ce dernier est spécifique au coprocesseur.
Instruction
LDC STC LDC2 STC2
MRC MCR MCR2 MRC2
CDP CDP2
Description
Transfert de données entre le coprocesseur et la mémoire
Transfert de données entre le coprocesseur et les registres
Exécution de l’instruction coprocesseur
Tableau 25 : Aperçu des instructions coprocesseur destinées aux transferts de données
et à démarrer les actions du coprocesseur.
Il existe quatre modes d’adressage, avec lesquels le coprocesseur peut accéder à la mémoire. Ces derniers sont
fournis dans le Tableau 26.
Mode d’adressage
Pré indexation avec un offset constant
Pré indexation avec écriture en retour et un offset constant
Post indexation avec un offset constant
Sans indexe mais avec une option spécifique au coprocesseur
Syntaxe
[Rn,#+/-offset8]
[Rn,#+/-offset8]!
[Rn], #+/-offset8
[Rn], <option>
Tableau 26: Un aperçu des modes d’adressage du coprocesseur.
Exemple
Le registre c0 du CP15 contient le numéro d’identification du coprocesseur. Ce dernier est transféré depuis le
CP15 dans le registre de travail r0.
Avant :
r0=0x00000000
MRC p15,0,r0,c0,0
Après :
r0 = 0x69054117
Interprétation du résultat pour les bord de développement CARME : Les bit [24:31]=0x69 spécifient le
fabriquant Intel. Les bits [16:23]=0x05 représente l’architecture et la variante 5TE. Les bits [4:15]=0x411
correspondent au numéro d’article (Implemented Defined Part Number) et les bits [0:3]=0x7 le numéro de la
révision (Implemented Defined Revision Number). Référence : ARM Architecture Reference Manual, p. B2-7:
Main ID Register – Post ARM7 Processors.
4.4 Les instructions arithmétiques et logiques
Les instructions arithmétiques et logiques constituent la plus grande partie des opérations de traitement de
données. Comme chez la plupart des processeurs RISC, ces dernières ne peuvent s’exécuter qu’avec des
registres. Les instructions, qui traitent directement les données de la mémoire, ne sont donc pas possibles. Les
opérandes et le résultat des opérations arithmétiques et logiques possèdent un format unique de 32 bits.
Toutefois, certaines opérations peuvent livrer un résultat de 64 bits, qui sera alors stocké dans deux registres.
Les instructions de comparaison et de test représentent des cas spéciaux d’opérations logiques. Ces derniers
modifient les bits d’état du registre CPSR. Les bits d’état constituent les bases de décision pour l’exécution des
instructions conditionnelles.
La spécialité des processeurs ARM est que leurs instructions arithmétiques et logiques ne modifient pas ses bits
d’état courant. Toutefois, cela peut être forcé avec le suffixe « S », qu’il faut ajouter à la fin de l’instruction. Les
opérations étendues, comme par exemple les instructions DSP (QADD, SMLA etc.) qui ne font pas partie du jeu
d’instruction du noyau, ne peuvent pas être complétées avec ce suffixe. Elles ne sont donc pas en mesure de
modifier les bits d’état.
Les instructions du Tableau 27 seront décrites dans les chapitres suivants :
Version 3.1, juin 2008
Page 76
Informatique 3
Instruction
ADD
ADC
AND
BIC
CMP
CMN
EOR
MUL
MLA
ORR
QADD
QDADD
QDSUB
QSUB
RSB
RSC
SMLA
SMLAL
SMLAW
SMUL
SMULW
SUB
UMLULL
Jeu d’instruction du processeur ARM V5
Description
Adition 32 bits
Adition 32 bits avec report de la retenu
Opération logique ET
Effacer un bit (NICHT UND)
Comparaison
Comparaison inverse
Opération logique OU exclusive
Multiplication 32 bits
Multiplication et addition 32 bits
Opération logique OU
Addition 32 bits avec protection contre les dépassements de capacité (DSP)
Addition 32 bits avec protection contre les dépassements de capacité (DSP)
Soustraction 32 bits avec protection contre les dépassements de capacité (DSP)
Soustraction 32 bits avec protection contre les dépassements de capacité (DSP)
Soustraction 32 bits inverser
Soustraction 32 bits inverser avec report de la retenu
Multiplication 16 bits / addition 32 bits signées (DSP)
Multiplication 16 bits / addition 64 bits signées (DSP)
Multiplication 32x16 bits / addition signées (DSP)
Multiplication 16 bits signée (DSP)
Multiplication 32x16 bits signée (DSP)
Soustraction 32 bits
Multiplication 32 bits non signée
Tableau 27 : Aperçu des instructions arithmétiques et logiques.
Cette famille comprend également celles de comparaison et de test.
4.4.1 L’arithmétique des entiers
Ces instructions comportent les opérations de calcul de base et les comparaisons arithmétiques.
Version 3.1, juin 2008
Page 77
Jeu d’instruction du processeur ARM V5
Informatique 3
Instruction
ADD
Opérande
Rd, Rn, N
Description
Addition 32 bits
Opération
Rd=(Rn+N)
ADC
MUL
MLA
Addition 32 bits avec report
Multiplication 32 bits
Multiplication / Addition 32 bits
Rd=Rn+N+Carryflag
Rd=Rn*Rs
Rd=Rn*Rs+Rm
Multiplication 32 bits / Addition
32 bits signées
Multiplication 16 bits / Addition
32 bits signées
Multiplication 32 bits / Addition
64 bits signées
Multiplication 32x16 bits /
Addition signées
Multiplication 16 bits signée
Rd= Rn+Rm*Rs
Multiplication 32x16 bits signée
Rd= (Rm* Rs.<y>)>>16
Multiplication longue signée
[RdHi,RdLo]= Rm*Rs
QDADD
Rd, Rm, Rn
QDSUB
Rd, Rm, Rn
QSUB
Rd, Rm, Rn
SBC
SUB
RSB
RSC
Rd,
Rd,
Rd,
Rd,
CMP
CMN
TEQ
TST
Rn,N
Rn,N
Rn,N
Rn,N
Multiplication longue / addition
non signées
Multiplication longue non
signées
Addition 32 bits avec protection
anti-dépassement de capacité
Addition 32 bits avec protection
anti-dépassement de capacité
Soustraction 32 bits avec
protection anti-dépassement de
capacité
Soustraction 32 bits avec
protection anti-dépassement de
capacité
Soustraction 32 bits avec report
Soustraction 32 bits
Soustraction 32 bits inverse
Soustraction 32 bits inverse
avec report
Comparaison
Comparaison inverse
Tester l’égalité
Tester un bit
[RdHi,RdLo]= [RdHi,RdLo]+Rm*Rs
QADD
Rd, Rn, N
Rd, Rn, Rs
Rd, Rn, Rs,
Rm
Rd, Rm, Rs,
Rn
Rd, Rm, Rs,
Rn
RdLo, RdHi,
Rm, Rs
RdLo, RdHi,
Rm, Rs
RdLo, RdHi,
Rm, Rs
RdLo, RdHi,
Rm, Rs
RdLo, RdHi,
Rm, Rs
RdLo, RdHi,
Rm, Rs
RdLo, RdHi,
Rm, Rs
Rd, Rm, Rn
SMLA<x><y>
SMLAL
SMLAL<x><y>
SMLAW<y>
SMUL<x><y>
SMULW
SMULL
UMLAL
UMULL
Rn,
Rn,
Rn,
Rn,
N
N
N
N
Rd= Rn+(Rm.<x>*Rs.<y>)
[RdHi,RdLo]=
[RdHi,RdLo]+Rm.<x>*Rs.<y>
Rd=Rn+(((signed)Rm*Rs.<y>)>>16)
Rd= Rm.<x>* Rs.<y>
[RdHi,RdLo]= Rm*Rs
Rd=sat32(Rm+Rn)
Rd=sat32(Rm+sat32(2*Rn))
Rd=sat32(Rm-sat32(2*Rn))
Rd=sat32(Rm-Rn)
Rd=Rn-N-!(Carryflag)
Rd=Rn-N
Rd=N-Rn
Rd=N1-Rn-!(Carryflag)
Drapeau en fonction de Rn-N
Drapeau en fonction de Rn+N
Drapeau en fonction de Rn^N
Drapeau en fonction de Rn&N
Tableau 28 : Instructions arithmétiques sur des entiers et de comparaisons
L’opérande N peut être une valeur direct (constante avec #), le valeur d’un registre ou le contenu d’un registre
décalé. Les résultats 64 bits sont toujours déposés dans une paire de registres.
Les suffixes <x> et <y> peuvent être soi B ou T. Ces suffixes limitent les bits à traiter du registre : B au 16 bits
de poids plus faibles [0 - 15] et T au 16 bits de poids plus fort [16-31]. Ici <x> se réfère au registre Rm et <y> au
registre Rs.
Certaines instructions DSP possèdent un préfixe Q, qui spécifie un traitement avec de l’arithmétique saturée. Ce
qui permet d’éviter les dépassements de capacité. Dans ce cas, lorsqu’il y a dépassement de capacité, le résultat
est la valeur maximale ou minimale qui peut être représentée avec 32 bits.
Du fait que l’opérande N peut avoir plusieurs formes, il est logique de pouvoir réaliser la soustraction également
à l’envers. Les instructions de soustraction à l’envers RSB et RSC sont à disposition pour cela. Les instruction
Version 3.1, juin 2008
Page 78
Jeu d’instruction du processeur ARM V5
Informatique 3
CMP, CMN, TEQ, TST réalisent respectivement les opérations SUB, ADD, EOR et AND, mais elles n’en stockent
pas le résultat dans un registre. Les instructions MUL et MLA ont la limitation suivante : le registre Rd ne peut pas
être pc ou Rn.
Seules les opérations de comparaison sont en mesure de modifier les bits d’état courant du programme, contenus
dans le registre CPSR. Les opérations arithmétique ne peuvent donc par modifier ces bits par défaut. Toutefois,
si cela devait être le cas, il faudrait leur ajouter un suffixe « S » à la fin.
Le jeu d’instruction ARM ne prévoit pas d’opérations de division. Ces dernières doivent donc être implémentées
avec des opérations de décalage et de soustraction. L’arithmétique BCD n’est également pas soutenue de façon
directe par le processeur.
Exemple :
L’instruction SUB permet de réaliser une simple soustraction. Le code suivant soustrait la valeur du registre r2
à celle du registre r1 et stocke le résultat dans le registre r0
Avant :
r0 = 0x00000000
r1 = 0x00000005
r2 = 0x00000002
SUB
r0, r1, r2
Après :
r0 = 0x00000003
Exemple :
Le jeu d’instruction ARM ne comprend pas les instructions d’inversion. Cela peut être réalisé avec une
soustraction inversée, en soustrayant la valeur 0 de la manière suivante : –z=0-z.
Avant :
r0 = 0x00000002
RSB
0, r0, #0
Après :
r0 = 0xFFFFFFFE
Exemple :
Une boucle de compteur peut être réalisée facilement avec l’instruction SUBS. Le code suivant décrémente la
valeur du registre r1. Le résultat, dans ce cas nulle, est stocké dans le registre r1. Parallèlement, Le drapeau Z du
registre d’état CPSR est mis à un. Ce qui pourrait être la base pour un saut conditionnel.
Avant :
CPSR = nzcvqIFt_USR
r1 = 0x00000001
SUBS
r1, r1, #1
Après :
CPSR = nZcvqIFt_USR
r1 = 0x00000000
Exemple :
Les processeurs ARM V5 avec l’extension E possèdent de nombreuses instructions DSP. Cela concerne
également des opérations, qui ne traitent qu’une partie de l’opérande. Le suffixe B permet dans ces cas de
spécifier le demi mot inférieur (bits 0-15) et le suffixe T le demi mot supérieur (bits 16-31).
Avant :
r0
r1
r2
r3
=
=
=
=
0x11111111
0x22222222
0x33334444
0x11112222
SMLALBT
Version 3.1, juin 2008
r0, r1, r2, r3
@ [r0,r1]=[r0,r1]+Lo(r2)*Hi(r3)
Page 79
Jeu d’instruction du processeur ARM V5
Informatique 3
Après :
r0
r1
r2
r3
=
=
=
=
0x159E1D95
0x22222222
0x33334444
0x11112222
4.4.2 Les instruction logiques
Ces instructions réalisent les opérations logiques ET, OU, OU exclusive et NON. Ces opérations permettent de
manipuler les bits (par exemple effacer, mettre à un ou compléter un bit) ou de créer les condition pour les saut
de programme.
Instruction
AND
ORR
EOR
Opérande
Rd, Rn, N
Rd, Rn, N
Rd, Rn, N
BIC
Rd, Rn, N
Description
Opération logique ET entre deux valeurs 32 bits
Opération logique OU entre deux valeurs 32 bits
Opération logique OU exclusive entre deux valeurs
32 bits
Effacer le bit (AND NOT)
Opération
Rd=Rn & N
Rd=Rn | N
Rd=Rn ^ N
Rd=Rn & ~N
Tableau 29: Les instructions logiques
La syntaxe de instructions logiques est la suivante :
<Instruction>{<cond>}{S}
Rd, Rn, N
L’opérande N peut être une valeur direct (constante avec #), la contenu d’un registre ou le contenu d’un registre
décalé. Contrairement aux nombreux autres processeurs, les opérations logiques n’influencent pas par défaut les
drapeaux du registre d’état courant CPSR. Si toutefois cela devrait être le cas, il faut ajouter un suffixe S à la fin
du code d’opération.
Exemple :
L’instruction BIC permet d’effacer certains bits dans un mot, sans en influencer les autres. Dans l’exemple
suivant, tous les bits de r2, dont la valeur correspond à « 1 », sont effacés dans le registre r1, et le résultat est
stocké dans r0.
Avant :
r1=0b1111
r2=0b0101
BIC
r0, r1, r2
Après :
r0 =0b1010
Exemple :
L’instruction ORR réalise une opération logique OU. Dans l’exemple suivante, cette opération est réalisée entre
les valeurs des registres r1 et r2, et le résultat est stocké dans r0.
Avant :
r0=0x00000000
r1=0x10305070
r2=0x02040608
ORR
r0, r1, r2
Après :
r0=0x12345678
4.4.3 Les instructions de décalage et de rotation
Les instructions de décalage et de rotation permettent de réaliser des opérations de déplacement binaire. Les
processeurs ARM ne soutiennent pas directement ce type d’opération. Toutefois, ces dernières peuvent être
réalisée indirectement à l’aide du décalage à barillet.
Version 3.1, juin 2008
Page 80
Jeu d’instruction du processeur ARM V5
Informatique 3
Le jeu d’instruction Thumb possède par contre ses propres instructions de décalage et de rotation. La raison est
que ce jeu d’instruction n’a pas accès au décalage à barillet.
Exemple :
Le contenu du registre r0 doit être déplacé de un bit vers la gauche. Ce qui correspond à une multiplication par
2. L’instruction MOV est la solution la plus simple pour ce problème.
Avant :
r0
= 0x00004321
CPSR = nzCvqIFt_SYS
MOVS
r0, r0, LSL #1
Après :
r0
= 0x00008642
CPSR = nzcvqIFt_SYS
n z c v
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
0 0 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 1 0 0 1 0 0 0 0 1
cpsr
r0
r0
0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 1 0 0 1 0 0 0 0 1 0
n z c v
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
0
Werden gesetzt bei einer
Instruktion mit S-Suffix
4.5 Saut de programme
4.5.1 Généralité
Les sauts de programme peuvent être répartis selon les critères suivants :
a) Saut conditionnel ou inconditionnel
b) Saut absolu ou relatif
Un saut de programme conditionnel n’est exécuté que si certaines conditions (bit d’état courant) sont réalisées.
Par contre, un saut de programme inconditionnel est toujours exécuté.
Les sauts de programme absolus engendrent des sauts à des adresses fixes. Ce type de sauts n’est pas soutenu par
les processeurs ARM. Les sauts de programme relatifs engendrent des sauts relatifs, c'est-à-dire avec un certain
déplacement (offset) par rapport à l’adresse courante. Ce déplacement est calculé automatiquement par
l’assembleur. Les processeurs ARM soutiennent uniquement les sauts relatifs.
Saut absolu (par exemple Intel x86, Motorola 68x mais pas ARM!)
Départ du programme à l’adresse 0x0000 :
0x0000
0x6000
Version 3.1, juin 2008
prog. Start
...
...
JMP 0x6000
...
...
instruktion 1
Le même programme est démarré à l’adresse 0x2000 :
0x0000
0x2000
0x6000
prog. Start
...
...
JMP 0x6000
...
instruktion x
0x8000
instruktion 1
Page 81
Jeu d’instruction du processeur ARM V5
Informatique 3
Le programme de gauche, qui est exécuté à partir de l’adresse 0x0000 (Figure de gauche), saute à l’adresse
0x6000 après l’instruction « JMP 0x6000 ». Ce qui est juste. Si ce même programme est exécuté à partir de
l’adresse 0x2000 (Figure de droite), le programme saute toujours à l’adresse 0x6000 après l’instruction
« JMP 0x6000 ». Ce qui est faux.
Æ Les programmes, qui contiennent des sauts absolus, ne peuvent pas être déplacés dans la mémoire.
Saut de programme relatif
Départ du programme à l’adresse 0x0000 :
0x0000
0x6000
prog. Start
...
...
B label1
...
...
Le même programme est démarré à l’adresse 0x2000 :
0x0000
Offset
label1:
0x2000
0x6000
prog. Start
...
...
B label1
...
instruktion x
0x8000
label1:
Offset
Le programme, qui est exécuté à partir de l’adresse 0x0000 (Figure de gauche), exécute un saut relatif (Branch)
d’une certaine distance (offset) à l’étiquette label1. Si ce programme est déplacé dans la mémoire (image de
droite), alors il continuera de fonctionner correctement. Car la distance entre l’instruction « B lable1 » et
l’étiquette lable1 reste constante.
Les programmes, qui contiennent des sauts relatifs, peuvent être déplacés dans la mémoire.
4.5.2 Les sauts de programme inconditionnels
Les sauts de programme inconditionnel sont des instructions, qui permettent d’interrompre le déroulement
séquentiel du programme. Certain de ces instructions sont utilisées pour les appelles de sous-routines ou les
changements de mode ARM → Thumb.
La syntaxe du saut de programme inconditionnel est la suivante :
<B | BL>
BX
BLX
<label>
Rm
<label> | Rm
L’étiquette (label) représente, en tant que constante symbolique, l’adresse à laquelle le programme doit sauter.
L’assembleur calcul le déplacement (offset), par rapport au contenu du registre compteur de programme pc.
C’est à dire en tenant compte de l’adresse de l’instruction courante. La destination doit se situer dans une zone
de ± 32 Méga bytes, par rapport à l’instruction courante. Alors que les instruction B et BL nécessitent une
constante symbolique comme adresse de destination ; les instruction BX et BLX peuvent réaliser un saut en se
basant sur le contenu d’un registre. Cela est spécialement utile, lorsque l’adresse de destination est calculée
durant le déroulement du programme ou lue à partir d’un Tableau.
Le Tableau 30 illustre les quatre instructions destinées aux sauts de programme ARM.
Version 3.1, juin 2008
Page 82
Jeu d’instruction du processeur ARM V5
Informatique 3
Instruction
B
BL
Distance de
saut (offset)
± 32MB
± 32MB
BX
± 32MB
BLX
± 32MB
Description
Effet
Saut de programme général
Appel de sous-routine.
Saut de programme avec sauvegarde de l’adresse
de retour dans le registre du relieur lr
Identique à B, mais possibilité de passage dans le
mode Thumb
Identique à BL, mais possibilité de passage dans
le mode Thumb.
pc = offset (label)
pc = offset (label)
lr = Adresse de l’instruction
qui suit BL
pc = Rm & 0xfffffffe
T = Rm &1
pc = Rm & 0xfffffffe
T = Rm &1
lr = Adresse de l’instruction
qui suit BL
Tableau 30 : Les instructions de saut de programme
L’appelle d’une sous routine (sous programme) est réalisé avec l’instruction BL. BL stocke également l’adresse
de l’instruction, qui suit celle du saut, dans le registre de reliage lr (r14). Cette dernière sert d’adresse de
retour depuis la sous-routine.
La distance de saut maximale est limitée aux 24 bits de codage pour l’offset. Ce qui correspond à environ ± 32
Méga bytes.
Au changement dans le mode Thumb, avec une adresse de destination dans le registre Rm, l’adresse de
destination doit être incrémentée (+1). Les processeurs ARM ignorent le bit de poids plus faible, car ils réalisent
le saut selon RM & 0xFFFF’FFFE. Ainsi il n’y a pas de changement de mode, lorsque le registre Rm contient
une adresse paire.
Lorsque l’instruction BLX est utilisée avec une adresse directe, le processeur entre dans le mode Thumb sans que
cette dernière ne doive être incrémentée (+1).
Exemple :
Les sauts de programme peuvent être réalisés soit en avant ou en arrière. Le calcul de l’offset est effectué
automatiquement par l’assembleur. L’exemple suivant illustre des sauts non conditionnels. Le premier saut
franchit les trois opérations d’addition et arrive directement à la première soustraction. Le deuxième saut réalise
un retour en arrière et produit ainsi une boucle infinie.
B
ADD
ADD
ADD
ahead
r1,r2,#4
r0,r6,#2
r3,r7,#4
SUB
r1,r2,#4
ADD
SUB
ADD
B
r1,r2,#4
r1,r2,#4
r4,r6,r7
back
ahead:
back:
Exemple :
Les sous-routines sont appelées normalement avec l’instruction BL. Le retour s’effectue avec l’adresse de retour,
qui a été stockée avec BL dans r14. L’exemple suivant illustre le principe des appelles de sous-routines et le
retour à partir de ces dernières.
...
BL
ADD
...
subroutine
r0, r1, r2
subroutine:
<Subroutine code >
MOV
pc, lr
@ Return from subroutine
L’assembleur ARM ne prévoit pas d’instruction spécifique pour le retour à partir des sous-routines. Cette
Version 3.1, juin 2008
Page 83
Jeu d’instruction du processeur ARM V5
Informatique 3
dernières est toujours réalisée soit avec l’instruction « MOV
retour depuis la pile.
pc, lr », ou avec la lecture de l’adresse de
4.5.3 Les sauts de programmes conditionnels
Le concept d’exécution conditionnelle des instructions de ARM permet d’exécuter toutes les opérations de façon
conditionnelle. Cella concerne également les sauts de programme. Tous les sauts de programme du Tableau 30
peuvent ainsi être complété avec un suffixe.
La syntaxe pour les sauts de programme conditionnels est la suivante :
<B|BL>{<cond>}
BX{<cond>}
BLX{<cond>}
label
Rm
Rm
L’expression <cond> est le code condition sous forme de suffise selon le Tableau 31. Le reste est identique au
chapitre 4.5.2.
Condition
EQ
NE
CS,HS
CC,LO
MI
PL
VS
VC
HI
LS
GE
LT
GT
LE
Description
Equal
Not Equal
Unsigned higher or same
Unsigned lower
Minus, Negative
Positive or zero
Overflow
No overflow
Unsigned higher
Unsigned lower or same
Signed greater or equal
Signed less than
Signed greater than
Less or equal
Drapeau
Z
!Z
C
!C
N
!N
V
!V
C && !Z
!C && Z
(N == V)
(N != V)
!Z && (N == V)
Z || (N != V)
Tableau 31 : Les codes de condition pour l’exécution conditionnelle des instructions.
Exemple :
Une sous-routine doit calculer la faculté d’un nombre entier positif. Ce dernier est transmis à la sous-routine
avec le registre r0. La sous-routine doit ensuite enchaîner les multiplications et retourner le résultat avec le
registre r0.
start:
MOV
BL
B
r0, #5
FacSuB
start
@ Example 5!
@ Compute (r0!)
// Subroutine for the faculty computation
// n! = 1 * n * (n-1) * (n-2) * ... * 3 * 2
// Input r0: Argument n
// Output r0: Resultat n!
// Used register: r1
FacSub:
MOVS
r1, r0
@ Counter registre
MOVLE r0, #0
@ If n<=0,then result=0
BLE
endFac
MOV
r0, #1
Version 3.1, juin 2008
Page 84
Jeu d’instruction du processeur ARM V5
Informatique 3
loop:
MUL
SUB
CMP
BGT
endFac:
MOV
r0, r1, r0
r1, r1, #1
r1, #1
loop
@ multiplication n*(n-1)*(n-2)*...*3*2
pc,lr
@ return to the calling subroutine
4.6 Les autres instructions ARM
Ce chapitre décrit des instructions, qui seront traitées de façon plus détaillées dans les chapitres suivants. Ce qui
comprend les instructions break points et interruption software, ou les instruction qui n’ont pas de rapport
thématiques avec les chapitres précédents.
4.6.1 Les interruptions software SWI
Les interruptions SWI sont des outils, qui sont mis à disposition pour appeler des routines de services. Dans un
mode non privilégié, ces instructions permettent d’appeler les fonctions du système d’exploitation, qui doivent
être exécuté dans un mode privilégié. Le Tableau 32 traite plus de détail sur le déroulement des interruptions
software. Les exceptions et les interruptions sont traitées plus en détail dans le chapitre 7.
L’instruction SWI engendre un saut de programme à l’adresse 0x00000008, dans le Tableau des vecteurs
d’interruption.
la syntaxe de l’instruction SWI est la suivante :
SWI{<cond>}
SWI_Number
Le numéro SWI est une valeur entre 0x000000 et 0xFFFFFF. Ce dernier ne concerne pas le processeur mais
le traiteur des interruptions software SWI.
Instruction
SWI
Opérande
Numéro
SWI
Description
Interruption
software
Effet
lr_SVC = Adresse de l’instruction, qui suit SWI
SPSR_SVC = CPSR
pc = vector base + 0x8
CPSR_mode = SVC
CPSR_I = 1 (masquer IRQ)
Tableau 32 : Description du déroulement des interruptions software
Exemple :
Le code suivante illustre génère un SWI avec le numéro 0x123456, qui est utilisé par le débuggeur.
Avant :
CPSR
pc =
lr =
r0 =
SWI
= nzcvqift_USR
0x00008000
r14= 0x003FFFFF
0x12
0x123456
Après :
CPSR
SPSR
pc =
lr =
r0 =
= nzcvqIft_SVC
= nzcvqift_USR
0x00000008
r14= 0x0008004
0x12
4.6.2 Les points d’arrêt BKPT
L’instruction BKPT génère une exception du type « prefetch data abort », si elle n’est pas traitée par le hardware
du débuggeur. L’opérande <immed16> permet de transmettre une valeur 16 bits à l’instruction BKPT. Le
Version 3.1, juin 2008
Page 85
Jeu d’instruction du processeur ARM V5
Informatique 3
débuggeur peut traiter cette information et identifier le point d’arrêt avec ce numéro.
La syntaxe de l’instruction BKPT est la suivante :
BKPT
{<immed16>}
La valeur nulle est utilisé par défaut, en absence de la spécification <immed16>.
4.6.3 Le comptage des zéros CLZ
Cette instruction compte le nombre de bits zéro, qui précèdent dans une valeur binaire.
La syntaxe de l’instruction CLZ est la suivante :
CLZ{<cond>}
Rd, Rm
Le registre Rm ne peut pas être le registre du compteur de programme pc. L’instruction CLZ retourne la valeur
32 lorsque Rm = 0.
Exemple :
Le nombre de bits zéro, qui précèdent dans une valeur binaire, indique de combien une valeur peut être décalée
vers la gauche, sans qu’il n’y ait un dépassement de capacité.
Avant :
r0 = 0x12
r1 = 0x1234
CLZ
r0, r1
Après :
r0 = 0x13
r1 = 0x1234
Exemple :
La séquence d’instruction suivante normalise la valeur contenue dans le registre r0. Le premier bit, qui est
différent de zéro, se trouvera ainsi dans D31. L’exemple admet que la valeur à normaliser est différente de 0.
Avant :
r0 = 0x8421
CLZ
MOV
r1, r0
r0, r0, LSL r1
@ Nombre de déplacement vers la gauche pour la normalisation
@ Normalisation, afin que le bit 31 soit mis à un
Après :
r0 = 0x84210000
r1 = 0x10
Version 3.1, juin 2008
Page 86
Les directives de l’assembleur
Informtique 3
5 Les directives de l’assembleur
5.1 Introduction
Les directives de l’assembleur sont des pseudo instructions, qui permettent de gérer l’assemblage du programme.
Contrairement aux instructions réelles, ces dernières ne sont pas traduites en code machine.
Les directives de l’assembleur dépendent de l’assembleur. En générales les fonctionnalités suivantes sont mises à
disposition :
• Contrôle de l’assembleur
• Contrôle du relieur (Sections et leurs adresses de départ)
• Définition des variables et des constantes
• Formatage de fichiers
5.2 Aperçu
Le Tableau suivant fournit un aperçu des directives les plus importantes de l’assembleur :
Champ des noms Champ des
instructions
.arm
.thumb
.global
.extern
.align
.balign
.p2align
Nom de symbole .ascii, .asciz
Nom de symbole .byte
.2byte, .hword
.4byte, .word
Nom de symbole .space
.include
.equ, .set, =
.org
.section
.text, .data,
.bss
.end
.if
.ifdef
.ifndef
.else
.macro
.rep
.irp
.endm
.endr
.endif
Champ des opérateurs
Description
Nom de symbole
Nom de symbole
Alignement, valeur
Définition du jeu d’instruction ARM (32-Bit)
Définition du jeu d’instruction Thumb (16-Bit)
Exporter un symbole
Importer un symbole
Alignement de l’adressage de la mémoire
Chaînes de caractères
Valeurs
Définition de chaînes de caractères constantes
Définition de constantes de type byte, demi mot
et mot
Nombre, valeur
Réserver de l’espace mémoire avec initialisation
du bloc en question
Insérer le contenu d’un fichier
Attribuer une valeur à un symbole
Attribuer une adresse absolue
Définition de segments de mémoire
{chemin} nom de fichier
Nom de symbole, valeur
Adresse
Nom de symbole
{, drapeau}
Les sections standard
Condition
Nom de symbole
{Paramètre}
Nombre
Paramètre
Fin du code source
Assemblage conditionnel du programme
Définition d’une macro
Répétition des blocs de code
Fin d’une macro ou d’une structure de contrôle
Tableau 33: Les directives de l’assembleur
Version 3.1, juin 2008
Page 87
Les directives de l’assembleur
Informtique 3
5.3 .arm, .thumb
La directive .arm introduit un segment de code, qui est programmé avec le jeu d’instruction ARM. Alors que la
directive .thumb indique un segment de code, programmé avec le jeu d’instruction Thumb. La syntaxe du
mode Thumb est légèrement différente de celle d’ARM. Il ne comprend que les instructions et les registres
Thumb. Les deux directives possèdent respectivement les synonymes suivants : .code32 et .code16.
Exemple :
.arm
...
.thumb
...
@ 32-Bit ARM Instruction
@ 16-Bit Thumb Instruction
5.4 .global, .extern
Un symbole (sous-routine, variable etc.) peut être rendu publique avec les directives .global et .extern.
Ces symboles peuvent ainsi être utilisés (exportés) dans les autres modules.
La directive .extern est acceptée pour des raisons de compatibilité avec les autres langages de programmation
assembleurs. Cependant elle n’a pas d’effet, car l’assembleur considère tous les symboles comme étant externes.
La directive .extern peut toutefois être utilisée pour la documentation de l’interface du module.
Exemple:
main.s
.extern InitDisplay
...
...
...
...
bl InitDisplay
lcd.s
.global InitDisplay
...
...
InitDisplay:
...
...
mov pc,lr
La sous routine InitDisplay est appelée dans le fichier main.s (le chapitre 6 traite les sous-routines de
façon plus détaillée). La sous-routine InitDisplay est définie et exportée avec la directive .global dans le
fichier lcd.s. L’oubli de la directive .global génère des erreurs de relieur.
Pour des raisons de documentation, la directive .extern permet de montrer que le symbole InitDisplay a
été défini dans un autre module. La directive .extern n’est pas nécessaire pour le relieur (linker).
Contrairement au langage de programmation C, les informations concernant la transmission des paramètres et la
restitution du résultat ne sont pas disponibles en assembleur. En C ces informations sont fournies par la
déclaration de la fonction : extern void func (int). En assembleur c’est le programmeur, qui est
responsable de la programmation correcte du transfert des arguments et de la restitution du résultat des sous
routines.
Exemple :
Un programme minimal en assembleur, qui exécute une boucle infinie, a été défini dans le segment .text. Le
code de démarrage doit effectuer un saut à l’étiquette start, après avoir initialisé le hardware.
Version 3.1, juin 2008
Page 88
Les directives de l’assembleur
Informtique 3
start:
.arm
.global
start
.text
B
start
5.5 .align
La directive .align permet de s’aligner sur une adresse 32 bits (modulo 4). Cette directive insère par
conséquent zéro à trois bytes. Les processeurs ARM exigent que les instructions et les données du type mot
(word) du programme soient déposées à des adresses 32 bits.
Exemple :
0000 AA55
0002 0000
0004 48616C6C
6F00
.byte
.align
.asciz
0xaa, 0x55
@ 2 bytes 0x00 vont être inseres a cet endroi
"Hallo"
La syntaxe suivante est valable pour cette directive :
.align
AL {, FB}
L’opérande AL permet de spécifier le déplacement. Ce dernier dépend de la plateforme. Par exemple, la directive
« .align 3 » n’a pas la même signification chez les processeurs ARM et i386. Cette dernière correspond
respectivement à un déplacement de huit et zéro bytes. L’opérande FB permet de définir les bytes de
remplissage.
Exemple :
Le code suivant illustre les effets des directives .align. Dans cet exemple, la directive .align 3 permet de
s’aligner sur la prochaine adresse, qui est un modulo de 23 = 8.
0000 AA
0001 FFFFFFFF
FFFFFF
0008 48616C6C
6F00
000e 0000
.byte
.align
0xaa
3, 0xFF
.asciz
″Hello″
@ alignement modulo 2^3=8 et remplissage avec 0xFF
Du fait que la directive .align dépend des plateformes, deux nouvelles directives d’alignement ont été
spécifiées par le standard GNU : balign et .p2align. Ces dernières ne dépendent plus des plateformes.
Exemple :
La directive .align 8 engendre un alignement à la prochaine adresse modulo 28 = 256:
0000 55
0001 11111111
11111111
11111111
11111111
11111111
0100 FF
0101 00000000
.data
.byte
.align
0x55
8, 0x11
.byte
0xff
5.5.1 .balign
La directive .balign (byte align) fonctionne comme .align, mis à part que le paramètre d’alignement AL
est toujours défini en byte. Ce dernier décrit la valeur modulo, sur laquelle l’alignement doit avoir lieu. La
Version 3.1, juin 2008
Page 89
Les directives de l’assembleur
Informtique 3
directive .balign 8 engendre, indépendamment de la plateforme, un alignement sur une adresse modulo 8
bytes.
Les directives .balignw et .balignl sont des cas particuliers de .balign. En effet, ces derniers
considèrent le byte de remplissage comme un demi mot (2 bytes) ou un mot (4 bytes).
Exemple :
La directive .balign peut être utilisée de façon universelle. Le paramètre d’alignement doit toujours être
défini en byte et doit être une puissance de 2. Les autres valeurs engendrent un message d’erreur.
.data
.byte
.balign
.byte
.balign
.byte
.balign
.byte
.balign
.byte
0000 FF
0001 FF
0002
0003
0004
0005
0008
FF
00
FF
000000
FF
0xFF
0xFF
2
0xFF
4
0xFF
8
0xFF
Exemple :
La directive « .balignw 4,0x1234 » exécute un alignement à une adresse modulo 4. Si un déplacement de
2 bytes a lieu, il sera rempli avec la valeur 0x1234. La déposition des bytes dans la mémoire dépend du mode
boutiste du processeur. Les déplacements de un ou trois bytes engendrent des messages d’erreurs.
0000 FFFFFFFF
0004
0004 FFFF
0006 3412
b1:
b2:
.data
.byte
.balignw
.byte
.balignw
0xFF, 0xFF, 0xFF, 0xFF
4, 0x1234
0xFF, 0xFF
4, 0x1234
5.5.2 .p2align
La directive .p2align (power of 2 align) fonctionne comme .align, mis à part que le paramètre de
déplacement AL y est défini sous la forme exponentielle. Cette dernière fournit la valeur modulo, sur laquelle il
faut s’aligner. La directive « .p2align 3 » engendre, indépendamment de la plateforme, un alignement sur
une adresse modulo 8 bytes.
Les cas particulier sont ici .p2alignw et .p2alignl. Ces derniers considèrent les bytes de remplissage
respectivement comme des demi mots et des mots.
Exemple :
La directive « .p2align 3 » se réfère toujours sur des adresses, qui sont des multiples de 8. Les espace de
déplacement sont remplis avec des valeurs nulles.
0000 10
0001 00000000
00000
0008 33
b1:
.data
.byte
.p2align
0x10
3
b2:
.byte
0x33
Exemple :
Les directives « .p2alignw
2, 0x1234 » génèrent des déplacements sur des adresses, qui sont des
multiples de 4. Les espaces de déplacement du type mot sont remplis avec la valeur 0x1234. La suite des bytes
dépend du mode boutiste du processeur. Les déplacements de un ou trois bytes engendrent des messages
Version 3.1, juin 2008
Page 90
Les directives de l’assembleur
Informtique 3
d’erreurs.
0000
0001
0004
0006
FF
565656
FFFF
3412
b1:
b2:
.data
.byte
.p2align
.byte
.p2alignw
0xFF
2, 0x56
0xFF, 0xFF
2, 0x1234
5.6 .ascii, .asciz
Les directives .ascii et .asciz permettent d’insérer des chaînes de caractères constantes dans le code.
Plusieurs chaînes de caractères peuvent être définies avec une seule directive. Ces dernières doivent toutefois
être séparées par des virgules. Les valeurs ASCII des différents caractères sont directement déposées dans la
mémoire. La directive .asciz termine automatiquement la chaîne de caractère avec le byte de fin de chaîne
(byte nul).
La syntaxe de .ascii et .asciz est la suivante :
{Label :}
<.ascii|.asciz>
{,<string>} ...
Exemple :
0000 48616C6C
6F
0005 57656C74
2100
.ascii
″Hello″
.asciz
"World!"
5.7 .byte
La directive .byte permet d’insérer des constantes et des variables du type byte dans le code. Plusieurs valeurs
séparées par des virgules peuvent être définies. Ces dernières sont déposées dans le même ordre dans la
mémoire.
La syntaxe de .byte est la suivante :
{label:}
.byte
<byte1> {,<byte2>} . . .
L’étiquette (label) représente le nom de la constante. Cette dernière est utilisée comme adresse symbolique afin
de pouvoir accéder à la constante. Les valeurs négatives sont stockées en complément à deux. Les valeurs hexa
décimales commencent avec 0x ou 0X, les valeurs octales avec un 0 et les valeurs binaires avec 0b ou 0B. Les
valeurs décimales ne commencent avec un chiffre différent de zéro.
Exemple :
0000
0003
0005
0007
416225
20D0
F608
0A
.byte
.byte
.byte
.byte
'A', 'b', 37
0x20, -0x30
-10, 010
0B1010
5.7.1 .2byte, .hword
Les directives .2byte et .hword permettent d’insérer des constantes et des variables du type demi mot (16
bits) dans le code. Ces directives fonctionnent de la même manière que .byte.
La syntaxe de .2byte et .hword est la suivante :
{label:}
Version 3.1, juin 2008
<.2byte|.hword>
<short1> {, <short2>} ...
Page 91
Les directives de l’assembleur
Informtique 3
Exemple :
Les directives .2byte et .hword sont des synonymes. Elles déposent les constantes à 16 bits en respectant
l’ordre de leurs énumérations.
0000
0002
0006
0008
1100
33224400
1100
33224400
h1:
h2:
h3:
h4:
.data
.2byte
.2byte
.hword
.hword
0x11
0x2233, 0x44
0x11
0x2233, 0x44
5.7.2 .word, .4byte
Les directives .word et .4byte permettent d’insérer des constantes et des variables du type mot (32 bits). Ces
directives fonctionnent de la même manière que .byte et .2byte.
La syntaxe de .word et .4byte est la suivante :
{label:}
<.4byte|.word>
<word1> {, <word2>} . . .
Exemple :
Les directives .4byte et .word sont des synonymes. Elles déposent les constantes à 32 bits en respectant
l’ordre de leurs énumérations.
0000 11000000
0004 55443322
66000000
000c 11000000
0010 55443322
66000000
w1:
w2:
.data
.4byte
.4byte
0x11
0x22334455, 0x66
w3:
w4:
.word
.word
0x11
0x22334455, 0x66
5.8 .space
La directive .space réserve de l’espace mémoire pour un bloc, contenant un certain nombre de bytes. Ce
dernier est normalement utilisé pour le stockage de données.
La syntaxe de .space est la suivante :
{label:}
.space
<AB> {, <FB>} ...
Le paramètre AB spécifie le nombre de bytes, qui doivent être réservés pour le bloc. Le paramètre en option FB
défini le byte de remplissage, qui sera utilisé pour tout le bloc.
Exemple :
Les blocs de données sont des bytes, qui sont stockés successivement dans la mémoire. Ces derniers peuvent
également être initialisés. Dans les applications embarquées, l’initialisation de cette zone de mémoire est la tâche
du chargeur de démarrage (boot loader).
Version 3.1, juin 2008
Page 92
Les directives de l’assembleur
Informtique 3
00000 00000000
00000000
00000000
00000000
00010 AAAAAAAA
AAAAAAAA
AAAAAAAA
AAAAAAAA
AAAAAAAA
10010 00000000
00000000
00000000
00000000
00000000
.data
.space
0x10
.space
0x10000, 0xAA
.space
0x1234
5.9 .include
La directive .include copie du code le contenu du fichier à inclure dans le code source. Cette opération est
effectuée durant le processus d’assemblage du programme. Le fichier à inclure doit se trouver dans le répertoire
courant du projet. C'est-à-dire celui, qui contient les fichiers objets. L’option –I de la ligne de commande permet
de spécifier le chemin d’accès aux fichiers à inclure.
La syntaxe de .include est la suivante :
.include
"NomFichier"
Exemple :
.include
"pxa270.s"
La ligne .include "pxa270.s" sera remplacée par le contenu du fichier « pxa270 ».
5.10 .equ, .set, =
Les directives .equ, .set et = attribuent une valeur à un symbole. Ces directives sont des synonymes et
fonctionnent toutes de la même manière.
Exemple :
1
2
3
4
5
6
7
8
9
10
11
12
13
0000
0004
0008
000c
0A00A0E3
9710A0E3
011000E0
0930A0E3
0010 6400A0E3
.text
.equ
.set
TAB = 011
newline, 0xa
bitmask, 0b10010111
MOV
MOV
and
MOV
r0,
r1,
r1,
r3,
.equ
newline, 100
MOV
r0, #newline
#newline
#bitmask
r0, r1
#TAB
/* Redefinion of newlin */
Les symboles newline, bitmask et TAB sont dotés de valeurs numériques. La programmation peut être
effectuée avec ces symboles au lieu de leurs valeurs numériques. Cette définition centrale augment la lisibilité du
code et facilite son entretient. La définition directe de valeurs numérique dans le code devrait constituer une
exception.
Version 3.1, juin 2008
Page 93
Les directives de l’assembleur
Informtique 3
5.11 .org
La directive .org défini une adresse absolue, à partir de laquelle les instructions (ou les données) du programme
doivent être déposées dans la mémoire. La définition des segments avec .org constitue une exception, avec les
processeurs ARM. Cela provient du fait que les sauts de programme y sont toujours réalisés de façon relative.
Exemple :
mysub:
.org
...
MOV
0xa0000800
pc,lr
Dans l’exemple de ci-dessus l’adresse de départ de la sous-routine « mysub » est fixée à 0xa0000800. En
règle générale, l’utilisation de la directive .section est beaucoup plus élégante.
5.12 .section
L’espace mémoire des instructions et des données du programme peut être partagé en plusieurs blocs (segments
ou sections). On distingue fondamentalement le segment du code et celui des données. Le segment du code
(.text) contient les instructions du programme, qui sont stockées en générale dans une ROM. Le segment des
données est composé de variables, de la pile (stack) et d’autres types de grandeurs. On distingue ici l’espace
mémoire à initialiser (.data) et celui à ne pas initialiser (.bss). Le gestionnaire d’amorçage (boot loader) est
responsable de l’initialisation de l’espace .data. Dans les programmes C, ce gestionnaire est appelé par le code
de démarrage du module crt0.s.
Plusieurs segments peuvent être regroupés dans une classe. Les classes les plus importantes sont les suivantes :
.text, .data et .bss. Dans ces classes il est possible de définir des sous classes (segments).
Des nouveaux segments ne doivent en générales pas être définis dans des petits programmes. En générale les
classes prédéfinies, .text, .data et .bss, sont suffisent pour ces derniers. La définition des nouveaux
segments est en revanche nécessaire avec les programmes plus complexes, qui utilisent des modules étrangers.
La directive .section permet de définir des nouveaux segments, ou de modifier ceux qui existent déjà. Toutes
les instructions, qui suivent la directive .section, sont affectées à ce dernier. Contrairement à .org,
l’attribution de l’adresse de départ au segment n’est pas absolue. Cette dernière est réalisée par le processus de
reliage (linker).
Dans l’environnement de développement CARME, l’attribution des adresses absolues aux segments .section
s’effectue avec le script de reliage « ldscript_ram ».
La syntaxe de .section est la suivante :
.section
<NomSection>
{,"flags"}
Le symbole <NomSection> permet de définir un nouveau segment. Le drapeau "flag" permet de spécifier
les droits d’accès sur le segment. Le Tableau 34 contient les différents drapeaux et leur signification. Les droits
d’accès des classes de bases restent valables en absence de spécification.
Flag
A
W
X
Signification
Segment pour l’allocation de mémoire
Segment en écriture
Segment contenant du code exécutable
Tableau 34 : Droit d’accès des segments
Version 3.1, juin 2008
Page 94
Les directives de l’assembleur
Informtique 3
Nom de segment (Section)
.text
.data
.bss
.startup
.rodata, .rodata*
.glue_7, .glue_7t
Segment de base
.text
.data
.bss
.text
.text
.text (ev. .data)
Contenu
Code du programme
Variables initialisées
Variables non initialisées
Code de démarrage
Données en lecture (strings, constants)
Code d’interface ARM - Thumb
Tableau 35 : Nom de segment prédéfini
Les changements de segment, qui ne sont pas en rapport avec les segments de base, doivent être défini avec la
directive .section. Cette dernière peut être omis avec les classes de base :
.text
.data
.bss
.section
.section
.section
.section
.subroutines, "x"
.text
.startup
MySection, "w"
@ Synonyme to .text
Exemple :
Lorsque des nouvelles sections sont nécessaires, il faut les définir dans le module assembleur. Dans l’exemple
suivant, deux sous-routines sont définies dans le segment « subroutines » :
.text
start:
BL
BL
B
mysub1
mysub2
start
mysub1:
.section
MOV
.subroutines
pc,lr
b1:
msg:
.data
.byte
.asciz
0x22,0x33
″Hello″
mysub2:
.section
MOV
.subroutines
pc,lr
L’affectation du segment subroutines aux classes de base (.text, .data ou .bss) est spécifiée dans le
script du relieur « ldscript_ram ». Ce dernier devrait être affecté logiquement à la classe de base .text.
Dans le manuscrit de reliage de la Figure 70, les segments de l’exemple de ci-dessus sont insérés dans les parties
prédéfinies. Il est ainsi possible de spécifier l’ordre, avec lequel ces segments doivent être stockés dans la
mémoire. Il est évident que les modifications du plan de reliage (linkmap) doivent être effectuées avec la plus
grande précaution et en bonne connaissance des choses. Les éventuelles erreurs peuvent provoquer des chutes de
systèmes.
Version 3.1, juin 2008
Page 95
Les directives de l’assembleur
Informtique 3
/* identify the Entry Point ***************************************************/
ENTRY(_startup)
/* specify the colibri memory areas *******************************************/
MEMORY
{
flash
ram
}
: ORIGIN = 0x00000000, LENGTH = 0x02000000
: ORIGIN = 0xA0000000, LENGTH = 0x02000000
/* 32MB FLASH */
/* 64MB RAM
*/
/* specify sections ***********************************************************/
SECTIONS
{
/* startup code */
.text :
{
. = ALIGN(4);
/* advance location counter to the next 32bit boundary*/
*(.startup)
*(.glue_7)
*(.glue_7t)
} >ram
/* collect all sections that should go into ram after startup
*/
/* User defined .subroutines section */
.text :
{
. = ALIGN(4);
/* advance location counter to the next 32bit boundary*/
*(.text)
/* all .text sections (executable code)
*/
*(.subroutines)
/* all .subroutines sections (user defined sec.)
*/
_etext = .;
/* define a symbol _etext after the last code byte
*/
} >ram
/* collect all sections that should go into ram after startup
*/
.text :
{
. = ALIGN(4);
/* advance location counter to the next 32bit boundary*/
*(.text)
/* all .text sections (executable code)
*/
*(.rodata)
/* all .rodata sections (constants, strings, etc.)
*/
*(.rodata*)
/* all .rodata* sections (constants, strings, etc.)
*/
_etext = .;
/* define a symbol _etext after the last code byte
*/
} >ram
Figure 70: Extrait du manuscrit de reliage pour l’exemple de ci-dessus. Les attributions propres à l’exemple on
été mises en évidence avec des caractères gras.
Les adresses absolues, avec lesquelles les différents objets ont été stockés dans la mémoire, peuvent être
consultées dans le plan de mémoire. Pour cela il faut activer dans les options du relieur sous
« Miscellaneous » les flags « -Wl,-Map=Filename » (voir
Figure 71).
Version 3.1, juin 2008
Page 96
Les directives de l’assembleur
Informtique 3
Figure 71: Menu de l’environnement de développement, qui permet d’activer la génération d’un plan de
mémoire (linkmap) pour l’exemple de ci dessus.
Memory Configuration
Name
flash
ram
*default*
Origin
0x00000000
0xa0000000
0x00000000
Length
0x02000000
0x02000000
0xffffffff
Attributes
Linker script and memory map
LOAD startup/crt0.o
LOAD startup/BSP_STARTUP.o
LOAD AsmSectionAnweisung.o
LOAD D:\Programme/CarmeIDE/carme/lib\libBSP.a
START GROUP
LOAD D:/Programme/CarmeIDE/yagarto//lib/gcc/arm-elf/4.1.1\libgcc.a
LOAD d:/programme/carmeide/yagarto/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\libc.
END GROUP
.text
*(.startup)
.startup
.startup
*(.glue_7)
.glue_7
.glue_7
.glue_7
*(.glue_7t)
.glue_7t
.glue_7t
.glue_7t
Version 3.1, juin 2008
0xa0000000
0xa0000000
0x8b8
. = ALIGN (0x4)
0xa0000000
0xa0000000
0xa00000c0
0xc0 startup/crt0.o
_startup
0x4 AsmSectionAnweisung.o
0xa00000c4
0xa00000c4
0xa00000c4
0x0 startup/crt0.o
0x0 startup/BSP_STARTUP.o
0x0 AsmSectionAnweisung.o
0xa00000c4
0xa00000c4
0xa00000c4
0xa00000c4
0x0 startup/crt0.o
0x0 startup/BSP_STARTUP.o
0x0 AsmSectionAnweisung.o
. = ALIGN (0x4)
Page 97
Les directives de l’assembleur
Informtique 3
*(.text)
.text
.text
0xa00000c4
0xa00000c4
0xa0000598
0xa0000194
0xa00001a8
0xa0000180
0xa0000834
0xa0000214
0xa0000308
0xa0000120
0xa00003d0
0xa00001bc
0xa00000c4
0xa00008a8
0xa00008a8
.text
0x0 startup/crt0.o
0x7e4 startup/BSP_STARTUP.o
BSP_STARTUP_init
UNDEF_Routine
DA_Routine
SWI_Routine
_sbrk_r
pxa27x_set_core_freq
pxa27x_get_freq
FIQ_Routine
InitMemoryController
PA_Routine
IRQ_Routine
0xc AsmSectionAnweisung.o
start
*(.subroutines)
.subroutines
0xa00008b4
0xa00008b8
0xa00008b8
*(.text)
0x4 AsmSectionAnweisung.o
_etext = .
. = ALIGN (0x4)
Figure 72 : Extrait du plan de reliage (linkmap) pour l’exemple de ci-dessus
5.13 .end
La directive .end indique la fin du code source. Toutes les instructions, qui suivent .end, sont ignorées par
l’assembleur. La directive .end est facultative avec l’assembleur ARM_GNU.
Exemple :
mysub:
...
MOV
.end
pc, lr
@ dernière instruction
@ les instructions suivantes seront ignorées par l’assembleur
5.14 Les opérations assembleur
De nombreux opérateurs sont mis à disposition pour exécuter des calculs à l’intérieur des opérandes. Ces
derniers sont essentiellement utilisés pour le calcul des offsets et des adresses de stockage, comme par exemple
pour les accès Tableaux. Les opérandes de ces opérateurs doivent posséder des valeurs, qui sont fixes durant le
processus d’assemblage. Par conséquent, ces derniers doivent être des constantes.
L’assembleur GCC connaît deux opérateurs signés, qui sont équivalent à ceux de C.
Opérateur
~
Descriptions
Inversion arithmétique (complément à 2)
Inversion binaire (complément à 2)
Tableau 36: Les opérateurs signés de l’assembleur
Les opérateurs arithmétiques et logiques sont décrits dans le Tableau 37. La priorité de ces opérateurs est
identique à celle des opérateurs ANSI-C.
Version 3.1, juin 2008
Page 98
Les directives de l’assembleur
Informtique 3
Opérateur
/
*
%
<<
>>
|
^
&
!
+
==
<>
<
>
<=
>=
&&
||
Priorité
1
1
1
1
1
2
2
2
2
3
3
3
3
3
3
3
3
4
5
Description
Division (entier)
Multiplication
Reste de la division (Modulo)
Décalage vers la gauche
Décalage vers la gauche
OU binaire
OU Exclusif binaire
ET binaire
NON binaire
Addition
Soustraction
Egalité
Inégalité
Plus petit que
Plus grand que
Plus petit que ou égalité
Plus grand que ou égalité
ET logique
OU logique
Tableau 37 : Les opérateurs assembleur
Le résultat d’une opération de comparaison est toujours une valeur numérique. La valeur -1 représente ainsi vrai
et celle 0 faux. Toutes les opérations de comparaisons permettent de comparer des valeurs non signées.
Les opérations logiques livrent une valeurs 1 correspond à vrai et celle 0 à faux.
Les calculs arithmétiques ne sont pas possibles si les opérandes se situent dans des sections différentes.
5.15 Les structures de contrôle en assembleur
Les structures de contrôle en assembleurs sont destinées au processus d’assemblage. Il est ainsi possible de
générer des versions différentes du code en fonction de conditions prédéterminées. Par exemple du code
supplémentaire peut être inséré dans le programme afin de pouvoir le tester. Ce code, qui n’est plus nécessaire
dans la version finale du programme, peut ainsi être facilement omis.
5.15.1 L’assemblage conditionnel avec .if
La directive .if permet d’assembler de façon conditionnelle le bloque de code, qui suit cette dernière jusqu’aux
directives .endif ou .else. Le code n’est ainsi assemblé, que si la condition se réalise.
La syntaxe de .if est la suivante :
.if <ExpressionLogique>
...
{.else}
.endif
Lorsque la condition de l’expression « ExpressionLogique» est vrai, le bloque .if sera assemblé. Si non
c’est le bloque .else, qui sera assemblé.
Exemple :
La macro suivante permet de décaler a, soit vers la gauche ou vers la droite, en fonction du signe de b.
Version 3.1, juin 2008
Page 99
Les directives de l’assembleur
Informtique 3
.macro SHIFTLEFT a, B
.if \b < 0
MOV
\a, \a, ASR #-\b
.else
MOV
\a, \a, LSL #\b
.endif
.endm
5.15.2 L’assemblage conditionnel avec .ifdef
La directive .ifdef ne permet d’assembler un bloc de code que si son symbole existe. Par conséquent, ce
dernier doit être défini auparavant en tant qu’étiquette (label), avec les directives .set, .equ ou =.
La syntaxe de .ifdef est la suivante :
.ifdef <Symbole>
...
{.else}
.endif
Exemple :
Du code supplémentaire peut être inséré dans un programme, afin de pouvoir le tester. Dans l’exemple suivant,
le point d’arrêt n’est exécuté que si le symbole DEBUG a été défini auparavant.
.set
DEBUG, 1
LDR
.ifdef
BKPT
.endif
LDR
r0, =0x80
DEBUG
start:
r1, =0x80
5.15.3 L’assemblage conditionnel avec .ifndef
La directive .ifndef ne permet d’assembler un bloc de code que si son symbole n’existe pas. Le principe de
fonctionnement est identique à celui de .ifdef
La syntaxe .ifndef est la suivante :
.ifndef
...
{.else}
<Symbole>
.endif
5.16 La définition de macro avec .macro
La directive .macro permet de définir un symbole pour une certaine quantité de texte. Cette création de texte
peut également être paramétrée. La directive macro n’agit qu’au niveau substitution de texte. Toutes les
définitions de macro doivent se terminer avec la directive .endm.
La syntaxe de .macro est la suivante :
.macro <Nom>
{BlocCode}
.endm
{<arg1>} {, <arg2>} {, <arg3>} ... {, <argN>}
Le nom doit remplir les critères, qui régissent les noms des symboles. La convention veut que l’on définisse les
Version 3.1, juin 2008
Page 100
Les directives de l’assembleur
Informtique 3
noms de macro avec des majuscules. Les arguments représentent formellement les paramètres, comme pour une
fonction C. L’accès à ces paramètres doit s’effectuer dans la macro avec un caractère back slash ‘\’. Une
instruction macro peut être quittée avec la directive .exitm. Cela est toutefois en désaccord avec la
programmation structurée, mais peut dans certain cas simplifier le codage de la macro.
Exemple :
.exitm permet de définir une macro sans la directive .else.
Avant:
r0 = 0x80
r1 = 0x80
.macro SHIFTLEFT a, b
.if \b < 0
MOV
\a, \a, ASR #-\b
.exitm
.endif
MOV
\a, \a, LSL #\b
.endm
SHIFTLEFT
SHIFTLEFT
r0, 2
r1, -2
Après:
r0 = 0x200
r1 = 0x20
Exemple :
La macro ADR est une macro prédéfinie pour charger l’adresse des objets. Cette dernière exécute
automatiquement le calcul de l’offset par rapport au registre du compteur de programme pc. La macro peut être
utilisée comme une instruction du processeur.
La syntaxe de ADR est la suivante:
ADR
Rd, <Label>
Exemple :
Le chargement de l’adresse de base d’un Tableau peut être effectué très simplement avec la macro :
.text
...
ADR
...
Tab:
.data
.word
r0,Tab
0, 1, 2, 3, 4
5.17 Les structures de répétitions en assembleur
Les structures de répétition peuvent être considérées comme des macros, parce que ces derniers génèrent
également du texte. Les structures de répétitions permettent d’insérer un bloc de code plusieurs fois dans le
programme. Ce bloc peut être composé d’instructions ou de caractères. L’assembleur GNU met à disposition
pour cela les directives suivantes :
• .rept (répétition)
• .irp (répétition indéfinie)
Version 3.1, juin 2008
Page 101
Les directives de l’assembleur
Informtique 3
5.17.1 La répétition avec .rept
La directive .rept permet d’insérer un bloc de code un certain nombre de fois.
La syntaxe de .rept est la suivante :
.rept <Quantite>
{BlocCode}
.endr
Exemple :
Les mots 0x55AA55AA, 0x00000000, 0xAA55AA55, 0x11111111 doivent être insérés 16 fois dans la
mémoire. La directive .rept permet de réaliser cela de façon compacte :
.rept 16
.word
.word
.word
.word
.endr
0x55AA55AA
0x00000000
0xAA55AA55
0x11111111
Le débuggeur permet de voir, comment ces valeurs ont été déposées dans la mémoire :
Figure 73 : La déposition de structure dans la mémoire avec .rept
Exemple :
.rept permet également de générer un Tableau contenant des valeurs pré calculées à l’aide de symbole.
L’exemple suivant montre la construction d’un Tableau du type byte contenant des valeurs allant de 0 à 255.
Version 3.1, juin 2008
Page 102
Les directives de l’assembleur
Informtique 3
.set
L1, 0
.rept
256
.byte
L1
.set
L1, L1+1
.endr
@ L1 is a local symbole with a start value
5.17.2 La répétition paramétrée avec .irp
La directive .irp permet d’exécuter une suite d’instruction avec plusieurs opérandes. Cette directive est en
quelque sorte une version simplifiée d’une macro avec un nombre de paramètres variable. Le premier paramètre
est le symbole de l’opérande. Ensuite suivent un certain nombre de paramètres, qui seront utilisés l’un après
l’autre dans le bloc de code.
La syntaxe de .irp est la suivante :
.irp <Symbole> {, <Valeur>}{, < Valeur >} ...
{BlocCode}
.endr
Les paramètres « Valeur » doivent être des valeurs entières.
Exemple :
La directive .irp permet de répéter un bloc en fonction d’une liste de paramètres. Le code suivant additionne
tous les paramètres au registre r0 à l’aide du registre r1.
.irp
MOV
ADD
.endr
param, 1, 2, 3, 4
r1, #\param
r0, r0, r1
La macro est étendu à l’assemblage du programme :
.irp
MOV
ADD
.endr
MOV
ADD
MOV
ADD
MOV
ADD
MOV
ADD
param, 1, 2, 3, 4
r1, #\param
r0, r0, r1
r1,
r0,
r1,
r0,
r1,
r0,
r1,
r0,
#1
r0,
#2
r0,
#3
r0,
#4
r0,
@ 0x1
r1
@ 0x2
r1
@ 0x3
r1
@ 0x4
r1
Figure 74 : Extension de la macro .irp de l’exemple de ci-dessus
Version 3.1, juin 2008
Page 103
Les sous routines
Informtique 3
6 Les sous routines
6.1 Introduction
Les sous routines sont des sous programme en assembleur. Ils correspondent, par conséquent, aux fonctions ou
aux procédures des langages de programmation évolués.
Une sous routine possède les propriétés suivantes :
• Une sous routine est une séquence d’instructions, avec une fonctionnalité et une interface (paramètres).
• Une sous routine est une boîte noire pour la fonction appelante, qui doit respecter scrupuleusement l’interface
(Information Hiding).
• Les sous routines peuvent être appelées plusieurs fois.
Les sous routines possèdent les avantages suivants :
• Modularité : Une application peut être divisée en plusieurs sous routines. Ce qui augmente sa lisibilité et
facilite son entretient.
• Travail d’équipe : La programmation peut être effectuée par plusieurs personnes.
• Réduction de la taille du programme : Une séquence de codes, qui est exécutée plusieurs fois, n’est stockée
qu’une seule fois dans la mémoire.
• Augmentation de la qualité : Les sous routines permettent de mieux tester et documenter le programme.
• Reprise : Les sous routines peuvent être également utilisées dans des autres projets. Ce qui réduit l’effort de
programmation.
Dans les langages de programmation évolués, le compilateur gère l’appel des sous programmes (callee) à partir
des programmes appelants (caller). Cela n’est malheureusement pas le cas dans les langages de programmation
en assembleur : ici le programmeur est l’unique responsable du déroulement de cet appel. Typiquement, les
problèmes suivants doivent être considérés par ce dernier :
• Appel de la sous routine et retour depuis cette dernière
• Echange de données entre la fonction appelante et la sous routine (transfert des paramètres)
• Les variables locales
6.2 Appel et retour de sous routine
6.2.1 Appel de sous routine
=
=
Programme principal
Sous routine 1
subr1:
bsr
1. instruction
subr1
instruction suivante
instruction suivante
n. instruction
retour
Figure 75 : Appel d’une sous routine
Dans l’exemple de la Figure 75, la sous-routine subr1 est appelée à partir du programme principal. A la fin de
l’exécution subr1, le programme retourne dans la routine principale, afin d’y exécuter les instructions
Version 3.1, juin 2008
Page 104
Les sous routines
Informtique 3
suivantes.
Dans l’architecture ARM, les appelles de sous routine sont réalisés avec les instructions « Branch-and-Link »
(BL). Cette instruction initialise le compteur de programme (PC) avec l’adresse de départ de la sous routine et
stocke simultanément l’adresse de retour (l’adresse de l’instruction qui suit l’appel de la sous routine dans le
programme appelant) dans le registre de reliage (lr).
ProgrammePrincipale:
BL
subr1
...
subr1:
...
MOV
@ branch to subr1 and save return address in "lr" (r14)
@ next instruction
@ start subroutine
@ return
pc, lr
L’instruction « MOV
pc, lr » est mise à disposition pour le retour depuis la sous routine. Le contenu du
registre de reliage (l’adresse de retour) est ainsi copié dans le compteur de programme. Cette opération peut
également être définie de la manière suivante : « MOV r15, r14 ».
La sous routine ne devrait pas modifier le contenu du registre de reliage, car ce dernier contient l’adresse de
retour. En particulier, la sous routine ne devrait pas appeler d’autre sous routine, sans sauver préalablement le
contenu du registre de reliage.
6.2.2 Appel emboîté de sous routine, pile
Une sous routine peut à son tour appeler une autre sous routine. Cet appel est illustré à l’aide de l’exemple
suivant. Le programme principal appelle la sous routine « subr1 », qui appelle une seconde sous routine
« subr2 ».
=
=
Programme principal
Sous routine 1
Sous routine 2
subr1
subr2
bsr subr1
1. instruction
Instruction
suivante
bsr subr2
1. Instruction
i
t
Instruction
suivante
n. instruction
retour
n. Instruction
i
t
retour
Figure 76: Appel emboîté de sous routine
Une sous routine peut s’appeler elle-même, générant ainsi un code récursif. Avec les codes récursifs, il faut faire
attention à la condition d’arrêt. Si non, la pile (stack) pourrait déborder.
Les adresses de retour doivent être systématiquement déposées sur la pile (stack), avec les appels emboîtés de
sous routines. Pour cela il faut :
a) Définir le domaine de la pile avec un le plan de mémoire
b) Initialiser de la pile
La pile est une structure de donnée dynamique, qui fonctionne selon le principe « Last In, First Out ». Les
opérations suivantes sont mises à disposition pour gérer cette dernière :
• Initialisation
• Push (poser un élément sur la pile)
Version 3.1, juin 2008
Page 105
Les sous routines
Informtique 3
• Pop (chercher le dernier élément de la pile)
Un nouvel élément est posé sur la pile avec l’opération « push ». L’élément, qui a été déposé en dernier sur la
pile, peut être recherché avec l’opération « pop ». Ces opérations modifient la taille de la pile.
1. Elément
Début de la pile
2. Elément
3. Elément
Pointeur de pile
push
pop
Figure 77 : La pile (stack)
Le pointeur de pile (stack pointer) adresse la fin de la pile, c. à d. l’endroit où la prochaine opération aura lieu.
Le registre r13 sert de pointeur de pile dans les processeurs ARM. Il est également possible de définir « sp » au
lieu de r13.
Les piles peuvent être implémenté de différentes manières :
• La pile peut croître « vers le bas » (descending). Dans ce cas les données sont déposées sur la pile en
décrémentant le pointeur de la pile. La pile peut égalent croître « vers le haut » (ascending). Dans ce cas les
données sont déposées sur la pile en incrémentant le pointeur de pile.
• Le pointeur de pile peut adresser soit la dernière case utilisée, c'est-à-dire l’endroit où le dernier élément a été
déposé sur la pile (« full )»); ou la prochaine case libre, c'est-à-dire l’endroit où le prochain élément peut être
déposé sur la pile (« empty )»).
Par conséquent, il est important que la même version de la pile soit utilisée par le compilateur et le programmeur
en assembleur. Le standard d’appel de procédure ARM (ARM Procedure Call Standard, APCS, voir chapitre
6.5) spécifie pour la pile le mode de fonctionnement « full descending ». Les opérations push sont alors
réalisées avec les instructions STR (sauvegarder uniquement du contenu du registre de reliage) et STMFD ("store
multiple full descending", afin de pouvoir sauver plusieurs registres simultanément). Les opérations pop peuvent
être réalisés soit avec les instructions LDR
(recherche uniquement du contenu du registre de reliage) et
LDMFD ("load multiple full descending", afin de rechercher le contenu de plusieurs registre à partir de la pile).
L’instruction STMDB ("store multiple decrement before") peut être également utilisée au lieu de STMFD. Car les
deux instructions sont équivalentes. Pour les même raisons, l’instruction LDMFD peut être remplacée par
LDMIA ("load multiple increment after").
Le code du programme principal et de la sous-routine subr1 de la Figure 76 devient ainsi :
Hauptprogramm:
BL
…
subr1
@ branch to subr1, save return address in "lr" (r14)
@ next instruction
lr, [sp, #-4]!
@
@
@
@
subr1:
STR
…
BL
LDR
subr2
pc, [sp], #4
push lr on the stack
code subroutine 1
call subroutine 2
return, pop return adress from stack to pc and increment sp
L’instruction STR décrémente d’abord le pointeur de pile de 4 bytes (la pile croît vers le bas). L’adresse de
retour du registre lr est ensuite déposée sur la pile.
Version 3.1, juin 2008
Page 106
Les sous routines
Informtique 3
Point de départ de l’exemple:
PC = 0x2000,
adresse de la sous routine 0x1000,
SP = 0x3200
Adresse
Code
0x2000
0x2004
0x1000
Opérations de pile au sein de subr1:
0x3200
1
0x31FC
0x00002004
lr auf
2 Stack
sp-4
BL
subr1
Next instruction
...
subr1:
STR
lr, [sp, #-4]!
...
Figure 78: Déposition de l’adresse de retour sur la pile
L’opération contraire est réalisée à la fin de la sous routine : L’adresse de retour est d’abord transférée depuis la
pile dans le registre compteur de programme pc. Le pointeur de pile est en suite corrigé de 4 bytes vers le haut.
Le programme retourne finalement dans la routine appelante. C'est-à-dire, qu’il exécute l’instruction qui suit
l’appel de la sous routine. Cette dernière se situe dans l’exemple de ci-dessus à l’adresse 0x2004.
L’initialisation de la pile exige d’une part la définition du domaine d’adressage, et d’autre part l’initialisation du
pointeur de pile. L’extrait de code suivant montre comment cela est réalisé :
Définition:
.set
.set
SVC_STACK_SIZE, 0x00000200
MODE_SVC, 0x13
@ stack size for supervisor mode
@ supervisor mode
Code de démarrage :
LDR
MSR
MOV
SUB
r0, =_stack_top_address
CPSR_c, #MODE_SVC
sp, r0
r0, r0, # SVC_STACK_SIZE
@ copy start address of stack into r0
@ switch to supervisor mode
@ initialize supervisor stack pointer
@ start address next stack
Remarque: Les processeurs ARM sont capables de fonctionner dans différents modes (voir chapitre 2). Chaque
mode possède sa propre pile (stack) avec son propre pointeur de pile. Le segment de code de ci-dessus initialise
par exemple la pile du mode superviseur. Les piles des autres modes (fiq, irq etc.) doivent être initialisés de la
même manière. Vous trouverez le code de démarrage (startup code), qui initialise toutes le piles, dans le fichier
« crt0.s ».
Les instructions pour les appelles et les retours de sous routines sont fournies dans le Tableau suivant :
Instruction
Branch-and-Link
Syntaxe
BL
subr_name
push simple
STR
lr, [sp, #-4]!
push multiple
STMFD
sp!, {r0-r2, lr}
Variante: STMDB
LDR
pc, [sp], #4
pop simple
+ Adresse de retour
pop multiple
+ Adresse de retour
LDMFD
sp!, {r0-r2, pc}
Variante: LDMIA
Opération
lr Å Adresse de retour
pc Å pc + distance de saut
sp Å sp – 4
Stack Å Adresse de retour
sp Å sp – n
Stack Å Adresse de retour + registre de travail
pc Å Adresse de retour
sp Å sp + 4
return
registre de travail Å Stack
sp Å sp + n
return
Tableau 38 : Opération de pile pour les appelles et les retours de sous routines.
Version 3.1, juin 2008
Page 107
Les sous routines
Informtique 3
La pile de l’exemple de la Figure 76 contient les valeurs suivantes :
sp
0x3200
return
Adr 1
return
Adr 1
sp
0x31FC
Stack
a)
return
Adr 2
b)
sp
0x31F8
c)
Figure 79 : Déposition des adresses de retour sur la pile
a) Contenu de la pile, lorsque le programme se trouve dans la routine principale
b) Contenu de la pile, lorsque le programme se trouve dans « subr1 »
c) Contenu de la pile, lorsque le programme se trouve dans « subr2 »
6.3 La sauvegarde du contenu des registres
Considérons le code suivant, qui appelle la sous routine « subr3 » 10 fois à partir d’une boucle.
Programme principale :
start:
loop:
MOV
BL
ADD
CMP
BNE
...
r4, #0
subr3
r4, r4, #1
r4, #10
loop
@
@
@
@
@
initialize loop variable r4
branch to subroutine
increment loop variable
check if 10 loops done
no Æ branch to label loop
lr, [sp, #-4]!
@ push lr on the stack
r4, #0
@ modify r4
pc, [sp], #4
@ return
Sous routine 3 :
subr3:
STR
...
MOV
...
LDR
Le problème de cette séquence de code est que le contenu du registre r4, qui est utilisé dans le programme
principale pour le stockage de la variable de compteur, est modifié dans la sous routine subr3 !
Dans ce cas la règle est le principe des contributions : Les contenus des registres, qui sont modifiés par la sousroutine, doivent être sauvés au début et restitués à la fin de cette dernière (exception voir chapitre 6.5). Les
instructions du Tableau 38 sont mises à dispositions pour ces opérations. Par conséquent, dans l‘exemple de cidessus, la sous routine subr3 doit également sauvegarder le contenu du registre r4.
La sous routine subr3 doit être modifiée de la manière suivante :
subr3:
STMFD
...
MOV
...
LDMFD
sp!, {r4, lr}
@ push registers to stack
r4, #0
@ modify r4
sp!, {r4, pc}
@ pop registers from stack
Remarque : L’instruction LDMFD copie directement l’adresse de retour dans le registre pc.
Version 3.1, juin 2008
Page 108
Les sous routines
Informtique 3
6.4 Le transfert des paramètres
Le transfert de paramètres entre le programme appelant et les sous routines peut être effectué de 2 manières :
1. Transfert de paramètres à l’aide de registres
2. Transfert de paramètres à l’aide de la pile (stack)
Les fonctions C et les sous routines en assembleur peuvent posséder plusieurs paramètres. Il est donc important
que le compilateur C et le programmeur en assembleur respectent les mêmes directives. Le standard d’appelle de
procédure ARM (ARM Procedure Call Standard, APCS) fixe les règles de transmission des paramètres pour les
processeurs ARM (voir chapitre 6.5) :
Les paramètres sont gérés à l’aide d’une liste. Les 4 premiers paramètres sont transmis avec les registres r0
à r3. Les autres paramètres sont transmis, dans un ordre inversé, à l’aide de la pile.
6.4.1 Le transfert de paramètres à l’aide de registre
Il existe fondamentalement deux types de transfert de paramètres :
Call by Value:
Une copie de la valeur originale est transmise en tant que paramètre à l’aide des registres (r0 à r3). Dans ce cas
la sous routine ne pas accéder à la variable originale.
Exemple: programme principale :
ADR
LDR
BL
r0, variable
r0, [r0]
mySubr
@ r0 points to address of variable
@ copy value of variable into r0
@ call subroutine, parameter is passed in r0
Call by Reference:
L’adresse de la variable est transmise en tant que paramètre à l’aide des registres (r0 à r3). Dans ce cas la sousroutine peut accéder à la variable originale.
Exemple: programme principale :
ADR
BL
r0, variable
mySubr
@ r0 points to address of variable
@ call subroutine, parameter is passed in r0
Exemple :
Considérons comme exemple une sous routine « sum », qui possèdent 3 paramètres. Cette dernière peut être
définie da la manière suivante en C :
int op1 = 2;
int op2 = 5;
int res;
void sum (int v1, int v2, int* res) {
*res = v1 + v2;
}
void main (void) {
sum (op1, op2, &res);
}
Version 3.1, juin 2008
Page 109
Les sous routines
Informtique 3
Le programme appelant peut être défini en assembleur de la manière suivante :
op1:
op2:
res:
.word
.word
.word
2
5
0
ADR
LDR
ADR
LDR
ADR
BL
r0,
r0,
r1,
r1,
r2,
sum
@ 1st operand
@ 2nd operand
@ result
main:
op1
[r0]
op2
[r1]
res
@
@
@
@
@
copy
read
copy
read
read
address op1 into r0
value op1, 1st parameter r0 by value
address op2 into r1
value op2, 2nd parameter r1 by value
address res, 3rd parameter r2 by reference
La sous-routine sum peut être définie en assembleur de la manière suivante :
• Calcul la somme des deux opérandes
• r3 est utilisé pour le stockage de la valeur intermédiaire
sum:
STR
ADD
STR
LDR
lr,
r3,
r3,
pc,
[sp, #-4]!
r0, r1
[r2]
[sp], #4
@
@
@
@
push lr
temp = op1 + op2
*res = temp
pop lr, return
Remarque : Le standard APCS n’exige pas de sauver le contenu du registre r3 à l’aide de la pile (voir chapitre
6.5).
6.4.2 Le transfert de paramètres avec la pile
Les 4 premiers paramètres sont transmis avec les registres r0 à r3. Les paramètres suivants sont transmis dans
un ordre inverse à l’aide de la pile.
Considérons comme exemple la sous routine « super_sum », qui possède l’interface C suivant :
int super_sum (int p1, int p2, int p3, int p4, int p5, int p6);
Cette sous routine ne retourne pas le résultat de façon « call by reference », mais à l’aide d’une valeur de
restitution. Cette restitution s’effectue avec le registre r0, selon le standard APCS.
Le code de la sous-routine « super_sum » peut être implémenté de la manière suivante :
• r4 est utilisé pour le stockage temporaire du résultat
• r5 est utilisé comme tampon pour la déposition momentanée des paramètres transmis avec la pile
• r4 et r5 doivent être sauvegardés à l’aide de la pile
super_sum:
STMFD
MOV
ADD
ADD
ADD
LDR
ADD
LDR
ADD
MOV
LDMFD
sp!, {r4, r5, lr}
r4, r0
r4, r1
r4, r2
r4, r3
r5, [sp, #12]
r4, r5
r5, [sp, #16]
r4, r5
r0, r4
sp!, {r4, r5, pc}
@
@
@
@
@
@
@
@
@
@
@
push r4, r5 and lr
temp = p1
temp += p2
temp += p3
temp += p4
buffer = p5
temp += p5
buffer = p6
temp += p6
copy return value to r0
pop r4, r5 and lr, return
Le contenu de la pile pour l’appelle de la sous routine « super_sum » est le suivant :
Version 3.1, juin 2008
Page 110
Les sous routines
Informtique 3
=
=
=
SP
0x3200 =
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
SK=
léÉê~å =
Ç=
=
=
RK=
=
léÉê~å =
Ç=
=
=
=
=
SP
=
=
0x31F8
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
SK=
léÉê~å
Ç=
RK=
léÉê~å
Ç=
=
äê=
=
=
êR=
êQ=
SP
0x31EC
=
=
=
=
=
=
=
=
NS=
=
=
=
NO=
=
=
=
U=
=
=
=
Q=
=
=
=
M=
=
=
Figure 80 : Transfert de paramètres à l’aide de la pile
a) Avant l’appelle de la sous-routine super_sum et la déposition des paramètres sur la pile
b) Après l’appelle de la sous routine, les paramètres 5 et 6 ont été déposé sur la pile
c) Dans la sous routine après l’instruction STMFD (push)
6.5 APCS
Le standard d’appelle de procédure ARM (ARM Procedure Call Standard, APCS) fixe l’utilisation des registres
de la CPU. Cette convention est importante, afin que les compilateurs et les assembleurs puissent utiliser les
mêmes conventions pour la transmission des paramètres, la sauvegarde des registres etc.
Registre
r0
r1
r2
r3
r4
r5
r6
r7
r8
r9
r10
r11
r12
r13
r14
r15
Nom APCS
a1
a2
a3
a4
v1
v2
v3
v4
v5
Sb / tr / v6
v7
v8
Ip
Sp
Lr
Pc
Brève description
Argument 1 / valeur de restitution à 32 bits/ registre scratch
Argument 2 / valeur de restitution à 64 bits / registre scratch
Argument 3 / registre scratch
Argument 4 / registre scratch
Variable registre 1
Variable registre 2
Variable registre 3
Variable registre 4
Variable registre 5
Dépend de la plateforme / Variable registre 6
Variable registre 7
Variable registre 8
Intra-Procedure-call / registre scratch
Pointer de pile (stack pointer)
Registre de reliage (link register)
Compteur de programme (Program-Counter)
Tableau 39 : Attribution de registre selon le standard APCS
Version 3.1, juin 2008
Page 111
Les sous routines
Informtique 3
• Les registres r0 à r3 (a1 à a4) sont utilisés pour transmettre les arguments aux sous routines. Ces dernières
ne doivent pas conserver leur contenu. Par conséquent, ces registres peuvent être utilisés comme registres
scratch (volatiles, utilisables à souhait et qui ne doivent pas être sauvés dans par les sous routine appelée).
Attention : cela veut dire que les fonctions appelantes doivent considérer, que le contenu de ces registres peut
être modifié par l’appelle de la sous routine ! Le registre r0 est utilisé pour le retour d’un résultat à 32 bits.
Les registres r0 et r1 sont utilisés lorsque ce résultat est de 64 bits.
• Les registres r4 à r8 (v1 à v5) et les registres r10 et r11 (v7 et v8) peuvent être utilisés comme registre
de variable (mémoire intermédiaire). Ces registres doivent retrouver leur valeur d’origine à la fin de la sous
routine. Ils doivent par conséquent être sauvés au début de cette dernière (callee-saved), voir chapitre 6.3.
• Le registre r9 dépend de la plateforme. Il peut être utilisé comme registre de base statique (static base, sb)
ou comme registre thread (thread register, tr). Si r9 n’est pas utilisé pour ces tâches, il peut être utilisé
comme registre de variable.
• Le registre r12 (ip, Interlink Pointer) peut être utilisé comme registre scratch entre les routines et les sous
routines.
• Le registre r13 est le pointeur de pile.
• Le registre r14 est le registre de reliage.
• Le registre r15 est le compteur de programme.
6.6 Définition de variable locales
Les variables locales sont souvent utilisés dans les langages de programmation évolués. Exemple en C :
void myFunc (void)
{
unsigned int myArray [10];
...
...
}
// 10 * 4 Byte local variable
Les variables locales sont définies normalement à l’aide des registres r4 à r8, r10 et r11. Lorsque des
variables locales supplémentaires sont nécessaires, il faut stocker ces dernières sur la pile. Dans ce cas une zone
de mémoire, dont la taille correspond au bloc de variables locales, est allouée sur la pile. Un registre de pointeur
de trame (Frame Pointer), qui est normalement le registre r11, est initialisé avec l’adresse de base de ce bloc.
Le code de la sous-routine « myFunc » peut être implémenté de la façon suivante :
myFunc:
STMFD
SUB
MOV
...
...
ADD
LDMFD
sp!, {r11, lr}
sp, sp, #40
r11, sp
@ push r11 and return address, (1)
@ allocate 10 * 4 bytes local variable space, (2)
@ r11 points to first local variable, (3)
sp, sp, #40
sp!, {r11, pc}
@ free local variable space
@ pop r11 and lr, return
Le stockage des variable locale à l’aide le la pile s’effectue de la manière suivante :
Version 3.1, juin 2008
Page 112
Informtique 3
Les sous routines
SP alt
lr
r11 alt
1
2 SP neu
lokaler
Variablenbereich
1
3
r11 neu
Figure 81 : Déposition des variables locales sur la pile
La zone de mémoire contenant les variables locales peut être adressée à l’aide du pointeur de trame r11 et d’un
offset positif. Le programmeur est responsable du calcul correct de cet offset, comme ce fut le cas pour le
transfert des paramètres !
Le pointeur de trame adresse la partie inférieure la zone de mémoire contenant les variables locales. Toutefois,
ce pointeur peut être initialisé afin qu’il adresse la partie supérieur de cette zone. L’offset, pour pouvoir accéder
aux variables locales, doit alors être négatifs. Une autre variante est l’utilisation du pointeur de pile au lieu du
pointeur de trame pour adresser ces variables locales.
Lorsque des variables locales sont utilisées simultanément avec une transmission de paramètre avec la pile (voir
chapitre 6.4.2), les paramètres peuvent également être adressés avec le pointeur de trame au lieu du pointeur de
pile. Remarque : certain compilateur C initialise toujours un pointeur de trame, même si la sous routine n’utilise
pas de variables locales alouées sur la pile. Le code est ainsi un peu plus lent mais, par contre, le calcul des
offsets pour l’accès aux paramètres devient beaucoup plus simple.
6.7 Sources d’erreurs
Il faut faire attention aux opérations suivantes concernant l’appel et la terminaison des sous routines :
• Appeler les sous routines avec « BL » et non « B » !
• Terminer les sous routine en copiant l’adresse de retour dans le registre de compteur de programme pc (soit
directement depuis le registre de reliage lr ou depuis la pile)
• Lorsque la sous routine utilise des registres (mis à part les registres scratch), elle doit sauver leur contenu sur
la pile (faire attention à la succession des opérations de sauvetage, c. à d. que le registre qui a été sauvé en
dernier doit être repris en premier). Le nombre des opérations « pop » doit correspondre au nombre des
opérations « push ».
• Définir la pile suffisamment grande, afin que des dépassements de capacité ne puissent pas avoir lieu.
• Erreur de calcul des offsets des paramètres transmis à l’aide de la pile
Les erreurs de gestion de la pile génèrent toujours des chutes de programme, car les adresses de retour ne sont
plus justes !
6.8 Comparaison entre sous routine et macro
Le code de la sous-routine n’est déposé qu’une fois dans la mémoire, même si cette dernière est appelée depuis
plusieurs endroits du programme. Par contre, le code de la macro est déposé à chaque appel de cette dernière
dans la mémoire : Ce qui augment d’une part la taille du programme et empêche d’autre part de définir des
macros récursifs.
Il s’en suit la question : pourquoi utilise-t-on les macros. La réponse est dans le comportement temporel : un
appel de sous routine avec l’instruction « BL » et le retour depuis cette dernière nécessite plus de temps (même si
cela ne concerne que deux instructions). Dans les applications, qui sont très critiques au niveau temps, cette
diminution de la vitesse d’exécution favorise la macro.
Version 3.1, juin 2008
Page 113
Informtique 3
Les sous routines
Dans des applications standards, il faut utiliser en générale des sous routines. Alors que dans les applications, qui
sont critique au niveau temps, il faut utiliser des macros.
Remarque: Un bon design software et des bons algorithmes sont beaucoup plus efficaces pour la performance du
processeur, que le remplacement systématique des sous routines par des macros.
Version 3.1, juin 2008
Page 114
Les interruptions et les exceptions
Informtique 3
7 Les interruptions et les exceptions
Les interruptions sont introduits au cours « d’informatique 2 » dans le cadre de la programmation proche du
hardware en C (firmware). Ce chapitre traite les interruptions et les exceptions (interruptions générées par des
erreurs dans le programme) au niveau de l’assembleur et du hardware.
7.1 Introduction
Les interruptions sont des évènements, qui peuvent survenir pendant l’exécution d’un programme et qui requiert
un traitement par ce dernier. Les interruptions ARM peuvent être partagés en 3 catégories :
1. Les interruptions et les exceptions, qui surviennent durant l’exécution d’une instruction. Ce type
d’interruption ou d’exception apparaît de façon synchrone au déroulement au programme. Cette catégorie
comprend les interruptions et les exceptions suivantes :
− Les interruptions software
− Les instructions non définies (l’instruction à exécuter est inconnue ou destinée à un coprocesseur
indisponible)
− Prefetch Abort (exception générée à cause d’une erreur d’accès mémoire durant sa lecture)
2. Les exceptions, qui apparaissent comme effet secondaire à une instruction. Ce type d’exception apparaît
également de façon synchrone au déroulement au programme. Les exceptions, qui composent cette catégorie,
sont les suivantes :
− Data Abort (exception à cause d’une erreur d’accès mémoire, durant la lecture ou l’écriture d’une donnée)
3. Les interruptions générées de façon externe. Ce type d’interruption apparaît de façon asynchrone au
déroulement du programme. C’est à dire que le programme peut être interrompu à n’importe quel instant. Les
interruptions, qui composent cette catégorie, sont les suivantes :
− Reset (mise sous alimentation, appui de la touche reset ou activation du « watch dog »)
− Les interruptions hardware : Les requêtes d’interruption standard (Interrupt ReQuest et abrégé avec IRQ)
et les requêtes d’interruption rapide (Fast Interrupt Request et abrégé avec FIR).
Lorsque des interruptions ou des exceptions surviennent dans uns système, ce dernier doit appeler des sous
routines pour leur traitement. Dans le cas d’une interruption on parle alors de « routine de
service d’interruption » (Interrupt Service Routine : ISR) et dans le cas d’une exception on parle de « traiteur
d’exception » (Exception Handler).
Le déroulement du programme est identique pour les trois catégories d’interruption : le programme principale est
interrompu et l’exception est traitée par le traiteur d’exception. Une description exacte du déroulement se trouve
aux chapitres 7.6 et 7.7.
Programme principale
Traiteur d’exception
Première
instruction
Exception
Instruction
courante
Instruction
suivante
Dernière
instruction
Figure 82 : Fonctionnement du programme à la suite d’une exception
Version 3.1, juin 2008
Page 115
Les interruptions et les exceptions
Informtique 3
7.2 Les propriétés des interruptions
Les interruptions possèdent les propriétés suivantes :
1) Les sous routines sont appelées directement avec les instructions de branchement BL. Ce qui n’est pas le cas
des routines de service d’interruption (ISR). En effet, ces dernières sont appelées par des évènements
externes. Le « Tableau des vecteurs d’exception » (vector table) est mise à disposition ici, pour gérer l’appel
de ces différents traiteurs d’exception (voir chapitres 7.6 et 7.7)
2) Le processeur change de mode, lorsque apparaît une interruption. Ce mode dépend de la nature de
l’interruption (voir chapitre 7.3).
3) Les interruptions possèdent des priorités différentes (voir chapitre 7.3)
4) Les requêtes d’interruption standard et les requêtes d’interruption rapides peuvent être masquées (voir
chapitre 7.5)
7.3 La priorité des exceptions et les modes du
processeur
Les questions suivantes apparaissent lorsque plusieurs exceptions surviennent simultanément :
• Quelle exception sera traitée en premier ?
• Est que les traiteurs d’exception peuvent être interrompue par d’autres exceptions ?
La plupart des contrôleurs possèdent des exceptions avec des priorités différentes. Certaines familles de
processeurs, dont celles des processeurs ARM, permettent également de spécifier ces priorités en fonction des
applications.
Chez les processeurs ARM, chaque type d’exception est exécuté dans un mode différent. Par conséquent,
certains registres du processeur ne doivent pas être sauvés dans la routine de service d’interruption. Ces registres
sont appelés des registres fantômes (banked registre).
Le Tableau suivant fournit un aperçu des priorités et des modes de traitement des différentes exceptions :
Exception
Reset
Data Abort
FIQ (Fast Interrupt Request)
IRQ (Interrupt Request)
Prefetch Abort
SWI (Software Interrupts)
Instruction non définie
Priorité
1
2
3
4
5
6
6
Mode du processeur
Superviseur
Abort
FIQ
IRQ
Abort
Superviseur
Non défini
Tableau 40 : Les priorités et les modes de traitement des exceptions
Exemple :
Le programme principal est interrompu par la requête d’interruption IRQ, dont le niveau de priorité est 4. Durant
le traitement de IRQ par sa routine de service d’interruption « irq_handler », apparaît une requête
d’interruption rapide FIQ, dont le niveau de priorité est 3. Par conséquent irq_handler sera interrompu au
détriment de la routine de service d’interruption rapide « fiq_handler ». La Figure suivante montre le
schéma temporel de cet
Version 3.1, juin 2008
Page 116
Les interruptions et les exceptions
Informtique 3
Exemple :
Priorité
fiq_handler
irq_handler
Programme
principale
Temps
IRQ
FIQ
Figure 83 : Emboîtement des interruptions
7.4 Les interruptions
Les interruptions peuvent être partagés en deux catégories : les interruptions hardwares et softwares.
Les interruptions hardware :
Les interruptions hardware surviennent de façon asynchrone au déroulement du programme. Ces dernières sont
très importantes pour accomplir les requêtes temps réel.
Les interruptions hardware sont toujours générées par des composants hardware périphériques. Par exemple le
timer, l’interface sérielle ou un port d’entrée quelconque. Les éventuelles sources d’interruptions dépendent donc
du processeur et de ses composants périphériques.
Dans les processeurs ARM, les composants périphériques peuvent générer soit un IRQ ou un FIQ. La gestion de
ces requêtes d’interruption est réalisée par un contrôleur d’interruption supplémentaire. Car le PXA270 possède
de nombreus composants périphériques capables de générer des interruptions (voir chapitre 7.8). Le registre de
contrôle des niveaux d’interruption (en anglais Interrupt Controller Level Register et abrégé par ICLR) permet
de définir le niveau de chaque source d’interruption (IRQ ou FIQ).
Exemple d’interruption hardware :
Le programme d’un microprocesseur gère un système contenant un affichage, des touches et une interface
sérielle. Il existe deux approches pour réaliser la lecture des données à partir des touches ou de l’interface
sérielle :
1. Les touches et l’interface sérielle sont lues périodiquement (polling). Le programme test de façon cyclique,
par exemple toutes les 10 millisecondes, si une touche a été appuyée ou si l’interface sérielle a reçu un
nouveau caractère. Cette approche présente néanmoins les défauts suivants :
− La lecture périodique des entrées nécessite beaucoup de temps de calcul. La plupart du temps le
programme constatera qu’aucune touche n’a été appuyée et qu’aucun caractère n’a été reçu.
− Un évènement peut être perdu à cause de la période du polling. Par exemple : si la lecture des touches ne
s’effectue que toutes les secondes et qu’une touche n’a été appuyée que pendant une demi seconde.
− Le temps nécessaire pour réagir à un évènement correspond, au pire des cas, à la période de polling.
2. Les touches et l’interface sérielle génèrent des requêtes d’interruption, lorsqu’elles doivent transmettre une
nouvelle information au programme. Cette approche présente les avantages suivants :
− Temps de réaction très rapide aux évènements
− Utilisation de la CPU qu’en cas de nécessité
Les interruptions software :
Les interruptions software sont traitées de la même manière que les interruptions hardware. Ces dernières
surviennent toutefois de façon synchrone au déroulement du programme. Par conséquent, elles représentent
quelque chose entre un appel de sous routine et un traitement d’interruption.
Les interruptions software sont souvent utilisées pour appeler des fonctions du système d’exploitation. Car ces
Version 3.1, juin 2008
Page 117
Les interruptions et les exceptions
Informtique 3
dernières font entrer le microprocesseur dans le mode superviseur. Ces fonctions ont ainsi la possibilité
d’accéder à tous les registres.
Il est possible de transmettre un paramètre aux interruptions software avec les processeurs ARM (SWI-number,
24 bits). Ce paramètre permet aux systèmes d’exploitation de définir la fonction à appeler.
7.5 Le masquage des interruptions
Les interruptions peuvent être activées (enabled) ou désactivées (disabled) dans la plupart des processeurs.
La gestion des interruptions peut être réalisée en deux étapes avec le PXA270 :
Dans une première étape, les interruptions IRQ et FIQ peuvent être activées ou désactivées. Cela peut être réalisé
à l’aide de leurs bits de contrôle, qui se situent dans le registre d’état courant du programme CPSR (Current
Program Status Register).
Fields
Flags
Status
Extension
Control
Bit 31 30 29 28
7 6 5
N Z C V Q
Function
not used
I
Condition
Flags
4
F T
Interrupt
Mask
0
Mode
Processor
Mode
Thumb
State
Figure 84 : Current Program Status Register
Le bit I permet de gérer l’interruption IRQ : 1 désactive cette interruption et 0 l’active. Le bit F gère
l’interruption FIQ de la même façon.
Dans une deuxième étape, les différentes interruptions peuvent être activées ou désactivées à l’aide du contrôleur
d’interruption. Le registre de masquage du contrôleur d’interruption ICMR (Interrupt Controller Mask Register)
permet de réaliser cela (voir chapitre 7.8).
InterruptController
InterruptQuelle
CPU
I/F-Bit
ICMR
InterruptVerarbeitung
CPSR
Figure 85 : Masquage des interruptions en deux étapes
7.6 Le Tableau des vecteurs d’exception
Lorsque apparaît une exception, la CPU interrompt l’exécution du programme pour exécuter la routine de
service d’interruption. L’adresse de cette routine est stockée dans le Tableau des vecteurs d’exception, qui
contient pour chaque type d’exception un vecteur d’exception.
Version 3.1, juin 2008
Page 118
Les interruptions et les exceptions
Informtique 3
L’adresse de base des Tableaux de vecteurs d’exception est normalement 0. Toutefois, du fait que le kit de
développement CARME possède une mémoire flash à cette adresse, ce Tableau y a été déplacé à l’adresse
0xA0000000 :
Exception
Reset
Instruction non définie
Interruption software
Prefetch Abort
Data Abort
IRQ
FIQ
Adresse de vecteur
0xA0000000
0xA0000004
0xA0000008
0xA000000C
0xA0000010
0xA0000018
0xA000001C
Tableau 41 : Tableau des vecteurs
Dans certaines familles de processeurs, le Tableau des vecteurs d’exception contient les adresses des différents
traiteurs d’exception (exception handler). Le processeur lit alors cette adresse et réalise le saut de programme
dans la routine de service.
Dans d’autres familles de processeurs, comme celles des processeurs ARM, le Tableau des vecteurs d’exception
contient uniquement des instructions. Dans ce cas, lorsque apparaît une exception, l’instruction, qui est stockée
dans son vecteur d’exception, est alors chargée et exécutée (Par exemple : avec IRQ ce sera l’instruction qui
est stockée à l’adresse 0xA0000018).
Le vecteur d’exception contient normalement une instruction de branchement relative, avec une distance de 24
bits. Si le processeur doit réaliser un saut de programme absolu, avec une adresse de 32 bits, il doit copier
indirectement cette adresse dans le compteur de programme.
Exemple d’un Tableau des vecteurs :
0xA0000000:
0xA0000004:
0xA0000008:
0xA000000C:
0xA0000010:
0xA0000014:
0xA0000018:
0xA000001C:
reset:
undef:
SWI:
pabt:
dabt:
IRQ
FIQ
B
B
LDR
B
B
B
B
B
reset_handler
und_handler
pc, [pc, #swi_handler]
pabt_handler
dabt_handler
notassigned
irq_handler
fiq_handler
@ branch with 24-Bit offset
@ indirect jump with LDR
load to pc
Le Tableau des vecteurs d’exception de ci-dessus est construit de manière statique. C'est-à-dire que les adresses
ont été définies de façon fixe pendant la programmation, et sont introduites par le relieur (linker) durant la
procédure de compilation.
Lorsque le Tableau des vecteurs d’exception est stocké dans une RAM, il peut être construit de façon
dynamique. Il peut ainsi être initialisé au démarrage du programme et changé durant son déroulement. :
1) Définition des déplacements (offset), c'est-à-dire les différences d’adresse entre les traiteurs et les vecteurs
d’exception.
2) Soustraire deux à ces déplacements.
3) Relier les offsets au code d’opération (opcode) de l’instruction de branchement (0xEA000000).
4) Copier les valeurs obtenues dans le Tableau des vecteurs d’exception
7.7 Déroulement d’une requête d’interruption
Cette section décrit le déroulement d’une requête d’interruption dans les processeurs ARM. Ce déroulement peut
être légèrement différent avec d’autres processeurs.
Entrée :
Version 3.1, juin 2008
Page 119
Informtique 3
Les interruptions et les exceptions
• La CPU termine l’exécution de l’instruction courante.
• Le mode de fonctionnement change en fonction du type de l’exception. Par exemple : une interruption IRQ
fait entrer le processeur dans le mode IRQ et une interruption software dans le mode superviseur.
• L’adresse de la dernière instruction (complétée avec un déplacement) est stockée dans le registre du relieur
(r14) du nouveau mode. Le déplacement dépend du type de l’exception et doit être considéré pour le calcul
de l’adresse de retour (voir Tableau 42).
• L’ancien contenu du registre CPSR et copié dans le registre SPSR du nouveau mode
• Le bit I est mis à un dans le registre CPSR avec les interruptions IRQ. Ce qui bloque uniquement les
interruptions IRQ. Le bit F est mis à un de la même manière avec les interruptions FIQ. Ce qui bloque les
deux types interruptions. Ce mécanisme empêche que te traiteur d’interruption ne soit interrompu par des
interruptions de priorité identique ou inférieur.
• Le compteur de programme est chargé avec l’adresse du vecteur d’exception correspondant à l’évènement. Ce
qui permet de continuer l’exécution du programme avec l’instruction, qui a été stockée dans le Tableau des
vecteurs d’interruption.
Dans le traiteur d’exception :
Les traiteurs d’exception (Exception Handler) sont toujours exécutés dans des modes privilégiés. Ces modes
mettent à disposition des registres fantômes (banked register), dont la quantité peut varier en fonction des modes.
Tous les modes mettent à disposition un pointeur de pile (r13) et un registre de reliage (r14), destiné au
stockage de l’adresse de retour. Le FIQ met également à disposition les registres r8 à r12.
Si des registres supplémentaires sont nécessaires dans le traiteur d’exception, il faut sauver et restituer leur
contenu initial à l’aide de la pile. Par conséquent, un traiteur d’exception possèdera toujours la structure
suivante :
• Sauvegarde des registres affectés
• Exécution de la tâche
• Restitution des registres préalablement sauvés
• Retour au programme principal
Retour au programme principal :
L’application doit continuer normalement, lorsque le traiteur d’exception a fini son travail. Pour cela il faut
rétablir l’état initial du processeur. En particulier, il faut faire attention aux points suivants :
• Tous les registres du processeur doivent contenir leur valeur initiale (après exécution de instruction, qui
précède le saut dans le traiteur d’exception)
• Le registre CPSR doit retrouver sa valeur d’origine. Cette dernière sera chargée à partir du registre SPSR du
mode d’exception.
• Le compteur de programme (PC) doit contenir l’adresse de la prochaine instruction du programme principale.
Le Tableau suivant permet de calculer l’adresse de la prochaine instruction à exécuter :
Exception
Reset
Instruction non définie
Interruption software
Pre fetch Abort
Data Abort
IRQ
FIQ
Adresse de retour
lr
lr
lr - 4
lr - 8
lr - 4
lr - 4
Tableau 42 : Adresse de retour en fonction des modes du processeur
Le retour depuis le irq_handler ou le fiq_handler peut être programmé de la manière suivante :
Version 3.1, juin 2008
Page 120
Les interruptions et les exceptions
Informtique 3
irq_handler:
...
<handler code>
...
SUBS
pc, lr, #4
@ pc = lr – 4, restore CPSR
L’instruction LDMDF peut également être utilisée, lorsque des registres doivent être sauvegardées dans le traiteur
d’exception :
irq_handler:
SUB
lr, lr, #4
STMFD
sp!, {r0-r3, r12, lr}
...
<handler code>
...
LDMFD
sp!, {r0-r3, r12, pc}^
@ lr = lr -4, subtract offset for return address
@ save context
@ restore context, return
Le caractères « ^ » à la fin de la liste des registres de l’instruction LDMDF signifie : qu’avant de charger le
compteur de programme avec la valeur du registre de reliage, il faut restituer l’ancien contenu du registre CPSR,
à partir du registre SPSR. Ainsi l’ancien mode du processeur avec les valeurs initiales des bits I et F (c'est-à-dire
avant l’arrivé de l’exception) peuvent être restitués.
Le déroulement du traitement des exceptions peut être schématisé à l’aide de l’exemple suivant :
Application
IRQ
instr 1
instr 2
instr3
LR = PC+4
Passage au mode IRQ
SPSR_irq = CPSR
PC = 0x00000018
PC = LR - 4
CPSR = SPSR_irq
Retour au mode utilisateur
Vector Table
B irq_handler
irq_handler:
instr a
instr b
SUB
pc, lr,
Figure 86 : Déroulement d’une requête d’interruption
Dans l’exemple de ci-dessus, les instructions 1 et 2 sont exécutées de façon séquentielle. Un IRQ interrompt
alors le programme principale (l’instruction 2 sera toutefois encore exécutée). La CPU lit ensuite la prochaine
instruction à exécuter dans le Tableau des vecteurs d’exception. Ce qui mène à un branchement dans le traiteur
d’IRQ. Finalement, l’état initial du processeur est rétabli et le programme continu avec l’exécution de
l’instruction 3.
7.8 Comportement temporel des interruptions
Le déroulement d’un traitement d’interruption peut être représenté graphiquement de la manière suivante :
Version 3.1, juin 2008
Page 121
Les interruptions et les exceptions
Informtique 3
Interrupt Request
User Program
User Program
CPU context saved
CPU context restored
User ISR Code
Interrupt Latency
Interrupt Recovery
Interrupt Response
Time
Figure 87 : Comportement temporel des interruptions
Le temps de latence d’interruption (Interrupt Latency) est le temps entre l’apparition de la requête d’interruption
(Interrupt Request) et l’exécution de la première instruction du traiteur d’interruption (interrupt handle) :
tILat = tdis + tcmod
tILat : Interrupt Latency
tdis : Temps maximal, pendant lequel l’interruption peut être désactivée
tcmod : Temps nécessaire pour le changement de mode
Le temps de réponse à l’interruption (Interrupt Response) est le temps entre l’apparition de la requête
d’interruption (Interrupt Request) et l’exécution de la première instruction de sa routine de service (ISR) :
tIRes = tIL + tcsw
tIRes : Interrupt Response
tILat : Interrupt Latency
tcsw : Temps nécessaire à la sauvegarde du contexte de la CPU
Le temps de recouvrement de l’interruption (Interrupt Recovery) est le temps nécessaire pour revenir dans le
programme principal après exécution de la routine de service (ISR) :
tIRec = tcsw2 + trti
tIRec : Interrupt Recovery
tcsw2 : Temps nécessaire pour restituer l’ancien contexte
trti : Temps nécessaire pour appeler la routine « return from interrupt »
7.9 Le contrôleur d’interruption du PXA270
Les chapitres précédents décrivent les deux interruptions externes, qui sont soutenus par les processeurs ARM :
IRQ et FIQ. Ces deux interruptions ne sont pas suffisantes pour les systèmes embarqués, où il faut pouvoir réagir
à de nombreux évènements externes. Par conséquent, le PXA270 contient également un contrôleur d’interruption
(Interrupt Controller). Ce dernier est schématiquement un multiplexeur, qui permet de gérer les diverses sources
d’interruption.
Chaque composant périphérique peut générer soit une interruption IRQ ou une interruption FIQ. Des priorités
Version 3.1, juin 2008
Page 122
Les interruptions et les exceptions
Informtique 3
allant de 0 à 39 peuvent être attribuées à ces composants, indépendamment du type d’interruption (IRQ ou FIQ).
Ces composants ne possèdent toutefois pas des vecteurs d’interruption propres.
Une description détaillée du contrôleur d’interruption est fournie par [2], Intel PXA27x Processor Family
Developer's Manual. Ce chapitre fournit un bref aperçu du contrôleur d’interruption et une brève description des
registres les plus importants.
La Figure suivante montre le schéma bloc du contrôleur d’interruption :
ICLR
ICMR
ICPR
ICIP
ICFP
ICHP
IPRx
Figure 88 : Diagramme de bloc du contrôleur d’interruption, Source : [2]
Les registres de configuration et de statut du contrôleur d’interruption sont décrits dans le Tableau suivant. Les
noms des registres commencent par « IC », ce qui signifie « Interrupt Controller ».
Version 3.1, juin 2008
Page 123
Les interruptions et les exceptions
Informtique 3
Nom
ICIP
Fonction
IRQ Pending Reg.
Adresse
0x40D0_0000
ICMR
Mask Register
0x40D0_0004
ICLR
Level Register
0x40D0_0008
ICFP
FIQ Pending Reg.
0x40D0_000C
ICPR
Pending Register
0x40D0_0010
ICCR
Control Register
0x40D0_0014
ICHP
Highest Priority R.
0x40D0_0018
IPR0 IPR31
Priority Register
0 – 31
0x40D0_001C
0x40D0_0098
ICIP2
ICMR2
ICLR2
ICFP2
IPPR2
IPR32 –
IPR39
IRQ Pending R. 2
Mask Register 2
Level Register 2
FIQ Pending Reg. 2
Pending Register 2
Priority Register
32 - 39
0x40D0_009C
0x40D0_00A0
0x40D0_00A4
0x40D0_00A8
0x40D0_00AC
0x40D0_00B0
0x40D0_00CC
Brève description
Indique les composants périphériques non masqués, qui
ont généré une IRQ (1 bit par source)
0: inactif
1: IRQ de cette source actif
Masquage ou activation des différentes sources
d’interruption (1 bit par source)
0: masqué (disabled)
1: non masqué (enabled)
Défini le type d’interruption (IRQ ou FIQ) généré par
le composant périphérique
0: IRQ
1: FIQ
Indique les composants périphériques non masqués, qui
ont généré un FIQ (1 bit par source).
0: inactif
1: FIQ de cette source actif
Montre l’état de toutes les sources d’interruption (1 bit
par composant périphérique)
0: inactif
1: Interruption est activé
Le bit de masquage Idle défini, si les interruptions
doivent être activées indépendamment du registre de
masquage (ICMR).
Montre pour IRQ et FIQ, la source d’interruption qui a
la plus haute priorité. L’identité de la source
périphérique est utilisée pour cela (voir Tableau 44).
Défini la priorité d’un composant périphérique. Chaque
priorité possède son propre registre IPRx, dans la
quelle il faut introduire l’identité du composant qui
génère l’interruption.
comme ICIP
comme ICMR
comme ICLR
comme ICFP
comme ICIP
comme IPRxx
Tableau 43 : Les registres de configuration et de statut du contrôleur d’interruption
Le Tableau suivant contient les différentes sources d’interruption et leur identité périphérique :
Version 3.1, juin 2008
Page 124
Informtique 3
Les interruptions et les exceptions
Tableau 44 : Identité périphérique (periphery-ID), source : [2]
7.10 Les variante pour le contrôleur d’interruption
Il existe différentes variantes pour implémenter un contrôleur d’interruption : « Nonnested Interrupt Handler »,
« Nested Interrupt Handler », « Reentrant Interrupt Handler », « Prioritized Simple Interrupt Handler » etc.
Toutes ces variantes ont été décrites de façon détaillée dans [10], « ARM System Developer's Guide ». Ce
chapitre ne contient que la description pour le « Nonnested Interrupt Handler ». Ce dernier possède les propriétés
suivantes :
• Traitement des interruptions de façon séquentiel. Le traitement d’une interruption ne peut pas être interrompu
par une interruption de priorité égale.
• Avantage : l’implémentation et les tests sont simples.
• Désavantage : Des temps de latence relativement lents. Ce qui peut être un désavantage pour les systèmes
embarqués avec plusieurs sources d’interruption.
Le « Nonnested Interrupt Handler » fonctionne de la manière suivante :
Version 3.1, juin 2008
Page 125
Les interruptions et les exceptions
Informtique 3
Interrupt
1
Disable Interrupts
spsr_mode = cpsr
pc = vector table entry
2
Save context
3
4
5
6
Interrupt Handler
Interrupt Service
Routine
Restore context
Enable Interrupts
pc = lr - 4
cpsr = spsr_mode
return
Figure 89 : « Nonnested Interrupt Handler », source: [10]
Le fonctionnement du « Nonnested Interrupt Handlers » est discuté à l’aide de l’exemple IRQ.
1) Le processeur ARM désactive toutes les interruptions IRQ. Ensuite il entre dans le mode IRQ, dans lequel il
sauve et le contenu du registre CPSR dans le registre SPSR. Le compteur de programme est finalement
chargé avec l’adresse du vecteur d’interruption (0x00000018).
2) Le contexte doit être sauvegardé : En cas d’appel de fonction C, il faut absolument sauvegarder les registres
r0 à r3 et r12 (voir APCS). Les registre r4 jusqu’à r11 sont sauvés automatiquement par le compilateur
dans les foncions C. S’il n’y a pas d’appel de fonction C, seul les registres affectés doivent être sauvés.
3) Le traiteur d’interruption identifie la source d’interruption et appelle la routine de service adéquate.
4) La routine de service traite l’interruption et désactive l’interruption.
5) Le contexte original est remis.
6) Les interruptions sont de nouveau activées, le registre CPSR est remis dans son état initial et le compteur de
programme est chargé avec l’adresse de retour.
Le code en assembleur pour le « Nonnested Interrupt Handler » pourrait être le suivant :
irq_handler:
SUB
STMFD
LDR
LDR
TST
BLNE
TST
...
LDMFD
Version 3.1, juin 2008
lr, lr, #4
sp!, {r0-r3, r12, lr}
r0, =ICIP
r0, [r0]
r0, #1<<PER_ID_OST
timer_isr
r0, <other source>
@
@
@
@
@
@
@
adjust link register for return address
save context
load IRQ status register address
read IRQ status register
test if operating system timer (OST) caused IRQ
if yes, call timer ISR
test other IRQ sources
sp!, {r0-r3, r12, pc}^
@ restore context and return
Page 126
Informtique 3
Les Structures de contrôle en assembleur
8 Les Structures de contrôle en
assembleur
8.1 Introduction
Le déroulement d’un programme peut être influencé à l’aide de structure de contrôle. Pour cela il existe les
procédures suivantes :
• Les séquences
• Les ramifications
• Les boucles
Une séquence est une suite d’instruction, qui est exécutée sans critères préalables. Alors que les ramifications et
les boucles ne sont exécutées qu’en fonction des critères externes, comme par exemple l’état du processeur.
Les langages de programmation évolués mettent à disposition des instructions standardisées pour définir des
structures de contrôle. Par exemple le langage de programmation C contient les instructions suivantes :
Pour les ramifications :
• if - else (Ramification simple)
• switch (Ramification multiple)
Pour les boucles :
• while (Boucle avec évaluation initiale)
• do - while (Boucle avec évaluation finale)
• for (Boucle d’itération)
Dans le langage de programmation assembleur, il est également possible d’utiliser ces structures de contrôle. Ce
qui permet de mieux structurer le code et, par conséquent, de faciliter son entretient.
Contrairement aux langages de programmations évolués, l’assembleur ne met pas à disposition des instructions
pour la définition des structures de contrôle. Toutefois, ces structures peuvent être réalisée avec des séquences
d’instructions en utilisant des chablons. Les chapitres suivants montrent, comment ces structures de contrôles
peuvent être réalisées en assembleur.
Version 3.1, juin 2008
Page 127
Les Structures de contrôle en assembleur
Informtique 3
8.2 La ramification simple
Dans la ramification simple, une condition est évaluée au début de l’instruction. Cette condition peut être
« réalisée » (true) ou « non réalisée » (false).
if condition
true
false
trueblock
falseblock
Figure 90 : La ramification simple
Lorsque la condition est réalisée, le programme exécute les instructions qui sont contenues dans le bloc
« then » ; sinon, il exécute les instructions du bloc « else ». Le bloc « else » est en option. C’est à dire
qu’une ramification simple ne peut contenir que du bloc « if ».
Exemple de code :
C
Assembler
if
(condition)
{
/* true-Block */
}
else
{
/* false-Block */
}
if:
TST
<condition>
BNE
...
B
false
true:
false:
@ true-block
endif
...
@ false-block
endif:
Tableau 45 : La ramification simple en C et en assembleur, avec un bloc « else »
Une ramification simple sans le bloc « else » peur être programmée de la manière suivante :
C
Assembler
if (condition)
{
/* true-Block */
}
if:
true:
TST
BNE
...
<condition>
endif
@ true-block
endif:
Tableau 46 : La ramification simple en C et en assembleur, sans le bloc « else »
Une ramification simple contient toujours une instruction d’entrée (ici « TST »), qui modifie les bits d’état le
registre CPSR (Current Program Status Register), suivie d’une instruction de saut de programme conditionnel
(ici « BNE »). Toutes les instructions, qui influencent les bits d’état, peuvent être utilisées comme instruction
d’entrée (TST, CMP, MOVS etc.) ; et toutes les instructions « Bcc » peuvent être utilisées comme sauts de
programme conditionnels.
Les architectures ARM soutiennent une autre forme de ramification simple : L’exécution conditionnelles des
instructions. Toutefois cela n’est raisonnable que pour des conditions simples, qui réunissent un à trois
instructions dans un bloc.
Version 3.1, juin 2008
Page 128
Les Structures de contrôle en assembleur
Informtique 3
Exemple (de [11]):
La recherche du maximum entre deux nombres peut être programmé en C de la manière suivante :
if (a > b)
c = a;
else
c = b;
En assembleur ARM, il est possible de programmer cet algorithme avec des instructions conditionnelles. Ce qui
évite l’utilisation des sauts conditionnels ou inconditionnelles de la structure proposée au Tableau 45 (les
variables a, b et c sont stockées dans les registres r0, r1 et r2) :
CMP
MOVGT
MOVLE
r0, r1
r2, r0
r2, r1
@ if (a > b)
@ c = a
@ c = b
8.3 La ramification multiple
La ramification multiple prend une décision entre plusieurs alternatives. Pour cela une expression d’entrée est
évaluée et le résultat est comparé avec les valeurs constantes de toutes les étiquettes case. En cas de
correspondance, le programme exécute les instructions du bloc appartenant à l’étiquette. S’il n’y a pas de
correspondance, le programme exécute le bloc par défaut.
switch expression
case const-expr1
const-expr1
block
case const-expr2
const-expr2
block
…
default
default
block
Figure 91 : La ramification multiple
Exemple de code :
Version 3.1, juin 2008
Page 129
Les Structures de contrôle en assembleur
Informtique 3
C
Assembler
switch (expression)
{
case (const-expr1):
...
break;
case (const-expr2):
...
break;
...
default:
...
break;
}
switch:
case1:
MOV
r0, #expression
CMP
BEQ
r0, #const_expr1
case1
CMP
BEQ
r0, #const_expr2
case2
...
B
default
...
B
...
B
...
case2:
default:
@ const-expr1 block
endSwitch
@ const-expr2 block
endSwitch
@ default block
endSwitch:
Tableau 47 : Ramification multiple en C et Assembler
Au début de la ramification multiple, l’expression à évaluer est copiée dans un registre, afin de pouvoir être
comparée avec les constantes des étiquettes case. Lorsqu’il y a correspondance, le programme effectue un saut
à l’étiquette correspondant à la constante, pour y exécuter les instructions.
Le code peut devenir très lent, lorsque l’instruction switch contient de nombreuses étiquettes case. Dans ce
cas, il est recommandé d’utiliser des Tableaux de sauts (jump table). Ces derniers peuvent être programmés de la
manière suivante :
switch: ADR
MOV
CMP
LDR
B
case1: ...
B
case2: ...
B
default:
...
endSwitch:
...
r1, jumptable
r0, #expression
r0, #tablemax
LO pc, [r1, r0, LSL #2]
default
jumptable:
.word
.word
.word
.set
@
@
@
@
@
@
load r1 with base address of jump table
load r0 with expression to test
check if value is in jump table
ok Æ load pc with label form jump table
expression > tablemax Æ default
const-expr1 block
endSwitch
@ const-expr2 block
endSwitch
@ default block
default
case1
case2
@ case 0 not defined Æ default
tablemax, 0x03
@ jump table has 4 entries
Les limitations des Tableaux de sauts sont les suivantes :
• Le Tableau ne devrait pas être trop grand. Elle ne peut pas contenir toutes les valeurs des expressions
constantes (entier de 32 bits). Un Tableau de saut n’est pas adéquat pour évaluer les expressions de 1 à 10000.
Cela nécessiterait un Tableau avec 10000 entrées.
• La taille du Tableau doit être testée durant l’exécution du programme (CMP
r0, #tablemax)
• Il faut introduire dans le Tableau le label par défaut pour les valeurs non définies (l’exemple de ci-dessus ne
contient pas le cas 0. Il faut donc introduire une valeur par défaut à l’indexe 0 du Tableau).
Version 3.1, juin 2008
Page 130
Les Structures de contrôle en assembleur
Informtique 3
8.4 La boucle avec évaluation de la condition au
début
La boucle avec une évaluation de la condition initiale (boucle while) exécute un bloc de code un certain
nombre de fois, qui n’est pas connu d’avance.
La condition est évaluée au début de la boucle. Si cette dernière est « vraie », le programme exécute les
instructions du corps de la boucle et réitère l’évaluation de la condition. Si cette dernière est « fausse », le
programme quitte la boucle et continue avec les instructions suivantes.
Avec ce genre de boucle, lorsque la condition est « fausse » depuis le début, les instructions de la boucle ne sont
jamais exécutées.
Condition de la boucle
Corps de la
boucle
Figure 92 : La boucle avec une évaluation de la condition au début
Exemple de code :
C
Assembler
while
(condition)
{
// Corps de la boucle
}
while:
TST
<condition>
BEQ
…
B
endwhile
@ Corps de la boucle
while
endwhile:
Tableau 48 : La boucle avec une évaluation de la condition au début en C et en Assembler
Les bits d’état courant du programme sont modifiés en fonction de l’instruction d’entrée (comme ce fut le cas
avec la ramification simple). Lorsque la condition « n’est pas réalisée », le programme effectue ensuite un saut
de programme conditionnel à la fin de la boucle. Après exécution des instructions du corps de la boucle, le
programme fait un saut de programme non conditionnel au début de la boucle, afin de réitérer l’évaluation de la
condition.
Le code du Tableau 48 n’est pas très efficace, car il nécessite deux sauts de programme (B et BEQ), qui doivent
être exécutés à chaque passage. Ce code peut être optimisé avec une réorganisation. Dans ce cas, un seul saut de
programme conditionnel (BNE) ne doit être exécuté par passage.
while:
loop:
test:
B
…
TST
BNE
test
Schleifenkörper
<condition>
loop
endwhile:
8.5 La boucle avec évaluation de la condition à la fin
La condition de la boucle est évaluée ici à la fin de la boucle (contrairement à la boucle avec évaluation de la
condition initiale). Lorsque la condition est « vraie », le programme exécute de nouveau les instructions du corps
de la boucle. Si la condition « n’est pas réalisée », le programme quitte la boucle et continu avec l’instruction
suivante. Avec ce genre de boucle, les instructions du corps de la boucle seront toujours réalisées au moins une
Version 3.1, juin 2008
Page 131
Les Structures de contrôle en assembleur
Informtique 3
fois.
Corps de la
boucle
Condition de la boucle
Figure 93 : La boucle avec évaluation de la condition à la fin
Exemple de code :
C
do
{
Assembler
do:
// Corps de la boucle
} while (condition);
…
TST
BNE
while:
@ Corps de la boucle
<condition>
do
enddowhile:
Tabelle 1: La boucle avec évaluation de la condition à la fin en C et en assembler
Les bits d’état sont également modifiés dans cet exemple en fonction de l’instruction d’évaluation (ici « TST »).
Lorsque la condition est « vraie », le programme effectue un saut de programme conditionnel au début de la
boucle. La boucle do - while correspond ainsi à la version optimisée de la boucle while, introduite au
chapitre 8.4, sans la première instruction de branchement.
8.6 La boucle itérative
La boucle itérative (boucle for) est un cas spécial de la boucle avec évaluation de la condition initiale. Dans le
langage de programmation C, toutes les instructions de contrôle sont mises en évidence au début de la boucle.
Normalement ce genre de boucle utilise une variable compteur, qui est initialisée tout au début (valeur départ).
La condition d’arrêt de la boucle est réalisée avec la comparaison de cette variable avec une valeur finale. Tant
que la condition est vraie, le programme exécute le corps de la boucle et incrémente le compteur. Les pas de ce
compteur peuvent être positif ou négatif.
for (valeur départ, valeur fin, Pas)
Corps de la
boucle
Figure 94 : La boucle itérative
Exemple de code :
Version 3.1, juin 2008
Page 132
Informtique 3
Les Structures de contrôle en assembleur
C
Assembler
for (expr1; expr2; expr3)
{
// Corps de la boucle
}
for:
loop:
MOV
CMP
BGE
...
ADD
bra
r0, #valeur_début
r0, #valeur_fin
endfor
@ Corps de la boucle
r0, r0, #pas
loop
endfor:
Tableau 49 : La boucle itérative en C et ne assembleur
Un registre rx (dans cet exemple r0) est utilisé comme variable compteur. Au début cette variable est initialisée
avec la valeur « valeur_début ». A l’étiquette « loop », le critère d’arrêt est évalué à l’aide de l’instruction
CMP, qui teste si la variable compteur a atteint la valeur « valeur_fin ». Si cette dernière atteint cette valeur
limite, le programme fait un saut de programme conditionnel (BGE) à la fin de la boucle. Si non, le programme
exécute les instructions du corps de la boucle et incrémente la variable compteur en fonction de la valeur
« pas ».
Des autres instructions que BGE peuvent également être utilisées pour évaluer la condition d’arrêt. L’instruction
ADD peut être remplacée par SUB afin de réaliser des pas de compteur décroissant.
Version 3.1, juin 2008
Page 133
Les structures de données en assembleur
Informtique 3
9 Les structures de données en
assembleur
9.1 Introduction
Les structures de données rassemblent plusieurs variables (de type simple ou composé) dans une structure. Voici
un exemple de structure de donnée en C :
struct Adresse
{
char Nom [MAX_CHAR];
char Prenom [MAX_CHAR];
char Route [MAX_CHAR];
int Numero;
char Lieu [MAX_CHAR];
};
Les langages de programmation évolués soutiennent les structures de données. Il en résulte les avantages
suivants :
• Compréhension et entretient facilité du programme
• Meilleur structure
En assembleur il est également possible de profiter des avantages des structures de données. Ce chapitre traite ce
sujet.
Les structures de données sont toujours orientées problème. C'est-à-dire, qu’ils essayent de reproduire au mieux
la réalité à l’aide d’un jeu de données (par exemple les données d’un processus). Il existe également une relation
étroite entre ces structures et le code du programme. Par conséquent, la modification d’une structure aura un
effet sur le code.
9.2 Les Tableaux unidimensionnels
Un Tableau (array) contient plusieurs éléments du même type. Ces éléments sont déposés dans la mémoire sans
lacune, l’un derrière l’autre. L’accès à ces éléments s’effectue à l’aide de leur indexe. Le premier élément
possède l’indexe 0 (array[0])
Exemple : Définition d’un Tableau contenant 4 éléments du type mot :
.data
array
.space
4*4, 0x12
@ array of 4 words, each initialized with 0x12121212
La directive « .space » permet de réserver un certain nombre de bytes, qui peuvent être initialisés. Dans cet
exemple 4 * 4 bytes ont été réservés au total et chaque byte a été initialisé avec la valeur 0x12. Si le Tableau ne
doit pas être initialisé, il peut également être défini dans la section « .bss ».
L’élément d’indexe 2 peut être effacé par exemple de la manière suivante :
.text
LDR
LDR
MOV
STR
r0,
r1,
r2,
r2,
=array
#2
#0
[r0, r1, LSL #2]
@
@
@
@
load r0 with base address of array
load r1 with index 2
value to write is 0
array[2] = 0
L’adresse de base du Tableau est d’abord copiée dans r0. Ce dernier adresse ainsi le premier élément du
Tableau (indexe 0). L’indexe de l’élément à accéder est ensuit copier dans r1. L’accès au Tableau est effectué
finalement avec l’instruction STR. L’adressage y est indirect et est obtenu avec « r0 + r1 * 4 ». La
Version 3.1, juin 2008
Page 134
Les structures de données en assembleur
Informtique 3
multiplication avec un facteur scalaire (défini dans cet exemple avec LSL #2) est importante, car les adresses
sont toujours calculées en byte.
Important : Un facteur scalaire est utilisé pour l’adressage indirect. Ce dernier possède les valeurs suivantes :
• 1 pour les bytes
• 2 pour les demis mots
• 4 pour les mots
Le code ci-dessus doit être modifié de la manière suivant avec un Tableau, qui contient des éléments du type
byte au lieu du type mot :
.data
array
.space
4, 0x34
@ array of 4 bytes, each initialized with 0x34
LDR
LDR
MOV
STRB
r0,
r1,
r2,
r2,
@
@
@
@
.text
=array
#2
#0
[r0, r1]
load r0 with base address of array
load r1 with index 2
value to write is 0
array[2] = 0 (Byte)
9.3 Les Tableaux multidimensionnels
Soit un Tableau avec 3 lignes et 4 colonnes du type mot (array [3][4]) :
array
.space
3*4*4
@ reserve 3 rows * 4 columns * 4 Bytes
Le Tableau peut être représenté de la manière suivante :
[0,0]
[1,0]
[2,0]
[0,1]
[1,1]
[2,1]
[0,2]
[1,2]
[2,2]
[0,3]
[1,3]
[2,3]
Tableau 50 : Tableau à deux dimensions
Les éléments de ce Tableau ne peuvent être stockés soit en ligne ou en colonne. Par exemple, le stockage en
ligne du Tableau, contenant 3 lignes et 4 colonnes, s’effectue de la manière suivante :
[0,0]
[0,1]
[0,2]
[0,3]
[1,0]
[1,1]
[1,2]
[1,3]
[2,0]
[2,1]
[2,2]
[2,3]
1. ligne
2. ligne
3. ligne
Tableau 51 : Stockage en ligne du Tableau
L’accès à l’élément d’indexes de ligne « i » et de colonnes « j » s’effectue de la manière suivante :
Adresse = 4 * i + j
Version 3.1, juin 2008
Page 135
Les structures de données en assembleur
Informtique 3
Cette formule n’est valable que pour des Tableaux, qui possèdent une adresse de base nulle et 4 colonnes du type
byte. La formule générale, qui contient également l’adresse de base du Tableau et la taille des éléments, est la
suivante :
Adresse de l’élément = Adresse de base + S * (SZ * i + j)
Les notations de cette formule ont les significations suivantes :
Adresse de base : Adresse de départ du Tableau
S : Facteur scalaire, byte = 1, mot = 2, long mot = 4
SZ : Nombre de colonnes
i : Index de ligne
j : Index de colonne
L’évaluation de cette formule peut s’avérer coûteuse, en fonction de la famille du processeur. Notamment
l’opération de multiplication « SZ * i » peut exiger un temps de calcul important. La multiplication avec le
facteur scalaire S peut, par contre, être effectuée avec des opérations de décalages (facteur 2 ou 4).
9.4 Les chaîne de caractères
Une chaîne de caractères (string) est une suite de caractères ASCII, qui se termine avec le caractère nul ou de fin
de chaîne de caractères (′\0′). La chaîne de caractères est définie de la manière suivante :
text:
.asciz
"abcABC0123"
@ null-terminated string
Remarque : Le caractère nul (′\0 ′) et celui du chiffre zéro (′0′) possèdent des valeurs ASCII différentes.
9.5 Les structures
Les structures de données permettent d’assembler des variables avec des types différents. Par exemple, la
structure pour stocker une date peut par être définie de la manière suivante :
date:
.byte
.byte
.hword
14
03
1879
@ day as byte (1-31)
@ month as byte (1-12)
@ year as halfword (e.g. 0000 – 3000)
La structure « date » possède deux membres de type byte et un membre de type demi mot. L’accès aux
membres de la structure s’effectue à l’aide de déplacements (offset), qui définissent la position relative des
membres dans la structure. Ces derniers sont les suivants pour la structure « date » :
.set
.set
OFFSET_MONTH, 1
OFFSET_YEAR, 2
Le membre « day » ne nécessite pas d’offset, car son adresse est identique à celle de base de la structure date.
L’écriture du membre année dans le registre r0 s’effectue par exemple de la manière suivante :
LDR
MOV
LDR
H
r1, =date
r2, #OFFSET_YEAR
r0, [r1, r2]
@ load r1 with base address
@ load r2 with offset
@ read year (halfword)
9.6 La pile (stack)
Le chapitre 6 concernant « les sous routines » fournit une description de la structure et du fonctionnement de la
Version 3.1, juin 2008
Page 136
Les structures de données en assembleur
Informtique 3
pile. Cette dernière était destinée au transfert des paramètres, à la sauvegarde des registres et la définition des
variables locales. Mais, l’utilisateur peut également définir des autres piles pour la gestion de données.
Directive pour l’implémentation de la pile :
• Les valeurs, qui doivent être déposées sur la pile (push) ou lues à partir de cette dernière (push), doivent se
trouver dans le registre r0. Les opérations de pile peuvent ainsi également être appelées par les fonctions C.
Car selon l’APCS, les paramètres sont transmis ou retournés à l’aide du registre r0.
• La pile de l’exemple est prévue pour les variables du type mots (word).
• La pile croît dans le sens négatif (adresses décroissantes).
• Le pointeur de pile adresse le dernier élément, qui a été déposé sur la pile (push : decrement before, pop :
increment after).
• Le pointeur de pile est une variable globale.
La pile et le pointeur de pile peuvent être définis de la manière suivante :
stack:
stackpointer:
.set
.data
.space
.word
STACK_SIZE, 1000
@ define stack size
STACK_SIZE, 0
stack + STACK_SIZE
@ reserve address space for stack
@ global variable, holds actual stack pointer
Le pointeur de pile doit adresser le début de la pile. Du fait que la pile croît dans le sens négatif, ce début est
l’adresse la plus grande de la pile. Le pointeur de pile est par conséquent initialisé avec « stack +
STACK_SIZE ».
La situation suivante prévaut après l’initialisation :
Pointeur
de pile
Adresses
hautes
Variable
pile
Adresses
basses
Figure 95 : La pile après son initialisation
Une opération « push » peut être implémenté de la manière suivante :
@
@
@
@
@
parameter r0 holds value to write to stack
r1 holds stackpointer address
r2 holds stackpointer value
r3 holds stack address
stack full error is not implemented
push:
stack_full:
endpush:
Version 3.1, juin 2008
STR
LDR
LDR
LDR
CMP
BLE
SUB
STR
STR
B
...
LDR
lr, [sp, #-4]!
r1, =stackpointer
r2, [r1]
r3, =stack
r2, r3
stack_full
r2, #4
r2, [r1]
r0, [r2]
endpush
pc, [sp], #4
@
@
@
@
@
save return address on system-stack
load r1 with stackpointer address
load r2 with stackpointer value
load r3 with stack address
check if stack is already full
@
@
@
@
@
@
decrement stackpointer (decrement before)
save new stackpointer value
push value to stack
Æ end
error code
return
Page 137
Les structures de données en assembleur
Informtique 3
Une opération « pop » peut être implémenté de la manière suivante :
@
@
@
@
@
parameter r0 is return value, element read from stack
r1 holds stackpointer address
r2 holds stackpointer value
r3 holds stack address
stack empty error is not implemented
pop:
stack_ empty:
endpop:
STR
LDR
LDR
LDR
ADD
CMP
BGE
LDR
ADD
STR
B
…
LDR
lr, [sp, #-4]!
r1, =stackpointer
r2, [r1]
r3, =stack
r3, #STACK_SIZE
r2, r3
stack_empty
r0, [r2]
r2, #4
r2, [r1]
end pop
pc, [sp], #4
@
@
@
@
@
@
save return address on system-stack
load r1 with stackpointer address
load r2 with stackpointer value
load r3 with stack address
r3 holds stack top address
check if stack is empty
@
@
@
@
@
@
pop value from stack, r0 is return value
increment stackpointer (increment after)
save new stackpointer value
Æ end
error code
return
Contrairement à la pile décrite au chapitre 6, qui ne contient pas de routine de contrôle pour les dépassements de
capacité, il est possible d’ajouter des fonctionnalités de contrôle, afin de pouvoir déceler les éventuels
dépassements.
9.7 Queues et anneaux de tampons (Queue / Ring
buffers)
Contrairement à la pile, une queue de tampons est accessible à ses deux bouts. Son principe est « first in, first
out ». Une queue de tampons fonctionne de la manière suivante :
Put
n. Element
Tail / écriture
2. Element
1. Element
Head / lecture
Get
Figure 96 : La queue de tampons
Directive pour l’implémentation de la queue de tampons:
• Head et Tail ne doivent se croiser
• La queue de tampons peut engloutir toute la mémoire
Dans la pratique, les queues de tampons sont remplacées par les anneaux de tampons. La problématique de
l’engloutissement de la mémoire est ainsi éliminée. Il existe deux types de réalisation :
Version 3.1, juin 2008
Page 138
Les structures de données en assembleur
Informtique 3
a) Head et Tail peuvent adresser le même élément de mémoire. Dans ce cas une variable supplémentaire
« size » est également nécessaire, afin de pouvoir stocker le nombre d’éléments contenus dans l’anneau.
Ainsi, size = 0 correspond à un anneau vide.
Apres écriture du
premier élément
Après
l’initialisation
Head
1. Element
2. Element
Tail
Head
Tail
size = 0
size = 1
n. Element
Figure 97: Les pointeurs Head et Tail dans une queue de tampons
b) Head et Tail ne peuvent pas adresser le même élément de mémoire. Un élément de mémoire est ainsi
sacrifié, mais la variable supplémentaire size n’est plus nécessaire (size = Tail – Head – 1). La
queue peut ainsi être initialisée avec « Head = 1 » et « Tail = 2 ».
Dans les deux cas il faut systématiquement contrôler les dépassements de capacités des pointeurs Head et
Tail. La Figure suivant illustre un exemple avec un dépassement de capacité de 8 à 1.
Dépassement
Head /
lecture
1
Tail /
écriture
8
2
7
3
6
4
5
Figure 98 : Anneau de tampons avec 8 éléments
Version 3.1, juin 2008
Page 139
Informtique 3
Le démarrage d’un programme C
10 Le démarrage d’un programme C
Les 3 derniers chapitres de ce manuscrit traitent les projets qui sont définis en C et assembleur.
10.1 Le processus de démarrage d’un programme C
Le processus de démarrage d’un programme désigne la partie du code, qui est exécuté entre de reset et
l’application. Le processus de Démarrage d’un programme en C est illustré schématiquement dans la Figure
suivante. Les différentes tâches de ce processus sont décrites dans les chapitres suivants.
Reset
Bootloader
Code de démarrage du système (CA RM E)
Code de démarrage de l’application
void main (void)
{
// Programme principale
}
Figure 99 : Processus de démarrage
10.2 Le reset
Au début fut le reset. Ce dernier peut être généré par les événements suivants :
• Allumage
• Watchdog
• Touche reset
• Software
Le reset conduit le processeur dans un état défini. Dans la plupart des contrôleurs le reset est le premier vecteur
d’interruption (souvent à l’adresse 0). Ce dernier contient l’adresse de la première fonction, qui doit être appelée
au démarrage du système. Ce qui est normalement le code de démarrage du système (boot loader), lorsque ce
dernier est disponible, ou le code de démarrage de l’application.
10.3 Le code de démarrage du système (boot loader)
Le boot loader est le code, qui initialise le système afin que qu’il puisse fonctionner. Les tâches du boot loader
sont les suivantes :
1. Initialisation des registres les plus importants, en particulier le « Chip-Select », afin que les composants de la
mémoire externe puissent être accédés.
2. Chargement de l’application à partir de la flash (ou d’un autre média de stockage non volatil) dans la mémoire
de travail (RAM).
Version 3.1, juin 2008
Page 140
Le démarrage d’un programme C
Informtique 3
3. Démarrage de l’application.
Remarque 1 : Le boot loader charge le système d’exploitation en premier, lorsque ce dernier est disponible. Les
applications sont chargées ensuite par le système d’exploitation.
Remarque 2 : Sur le kit de développement CARME, le boot loader contient un Tableau de vecteurs
d’interruption, qui se situe dans la mémoire flash à l’adresse 0. Les vecteurs de ce Tableau contiennent des
instructions de branchement sur tous les vecteurs d’interruption de l’application, qui se situent dans la mémoire
de travail à l’adresse 0xA0000000. La MMU ne sera pas utilisée pour les projets C et assembleur.
10.4 Le code de démarrage de l’application
Ce code de démarrage de l’application est exécuté normalement par une ou plusieurs routines assembleur, qui se
trouvent dans un fichier de démarrage. Les noms de ces fichiers dépendent des systèmes de développement.
Toutefois, ces derniers sont souvent appelés « crt0 » ou « startup ».
La programmation du processus de démarrage n’est pas requise avec les programmes en C. En effet, le
compilateur lit automatiquement le code de démarrage à partir d’une librairie et l’insère dans le projet.
L’application C démarre alors avec la fonction principale « main ». Cependant il existe de nombreux cas, où le
code de démarrage doit être modifié. Ce qui exige des connaissances en assembleur.
Le code de démarrage des projets CARME C se trouve dans le fichier « crt0.s », qui se trouve dans le sous
directoire « startup ».
Le code de démarrage doit réaliser les tâches suivantes :
• Définition du Tableau de vecteurs d’interruption de l’application
• Initialisation supplémentaire des registres CPU
• Initialisation de la pile
• Initialisation des variables globale
• Annuler les variables non initialisées
• Initialisation du paquet du support de bord (Board-Support-Package abrégé par BSP)
Définition du Tableau de vecteurs d’interruption de l’application
Le code de démarrage du système (boot loader) exécute en dernier un saut de programme à l’adresse
0xA0000000 (RAM), où se situe le Tableau des vecteurs d’interruption de l’application. Le vecteur
d’interruption reset de ce Tableau contient l’instruction « B Reset_Handler ». Ce traiteur de reset
(Reset_Handler) contient le code de démarrage de l’application. Cela est défini de la manière
suivante (fichier crt0.s) :
.global _startup
.section .startup
/* Exception vector table *****************************************************/
_startup:
reset:
B
Reset_Handler
/* 0x00 reset vector
undefvec:
B
UNDEF_Routine
/* 0x04 undef. instruction vector
wivec:
B
SWI_Routine
/* 0x08 software interrupt vector
pabtvec:
B
PA_Routine
/* 0x0c prefetch abort vector
dabtvec:
B
DA_Routine
/* 0x10 data abort vector
rsvdvec:
B
rsvdvec
/* 0x14 reserved (not used by XSCALE)
irqvec:
B
IRQ_Routine
/* 0x18 interrupt vector
fiqvec:
B
FIQ_Routine
/* 0x1c fast interrupt vector
*/
*/
*/
*/
*/
*/
*/
*/
Reset_Handler:
/* Startup-Code der Applikation */
…
Initialisation supplémentaire des registres CPU
Version 3.1, juin 2008
Page 141
Le démarrage d’un programme C
Informtique 3
Les registres les plus importants du système sont initialisés par le boot loader. Des registres supplémentaires
peuvent être initialisés à cet endroit, comme par exemple la vitesse de la CPU etc.
Initialisation du la pile
Le code de démarrage de l’application doit initialiser les piles (stack) pour les différents modes (Superviseur,
IRQ, FIQ etc.). En particulier, les pointeurs de piles doivent adresser les espaces mémoire, qui ont été réservés
pour ces piles.
La taille de chaque pile est définie dans le fichier crt0.s de l’environnement de développement CARME. Par
exemple pour le mode FIQ :
.global FIQ_STACK_SIZE
.set
FIQ_STACK_SIZE, 0x00000200
@ stack size for FIQ mode
Les zones de mémoire des différentes piles sont définies dans le fichier « ldscript_ram », dont voici un
aperçu :
...
. = ALIGN(4);
_irq_stack_top_address = .;
. += FIQ_STACK_SIZE;
. = ALIGN(4);
_fiq_stack_top_address = .;
...
@ IRQ-Stack top address
@ reserver FIQ stack size
@ FIQ-Stack top address
Les pointeurs de piles sont initialisés dans le fichier crt0.s. Par exemple pour la pile FIQ, cela est définie de la
manière suivante :
LDR
MSR
MOV
r0, =_fiq_stack_top_address
CPSR_c, #MODE_FIQ|I_BIT|F_BIT
sp, r0
@ load FIQ stack top address
@ switch to FIQ mode, interrupts disabled
@ load stack-pointer with stack address
Initialisation des variables globale initialisées
Les variables globales peuvent être initialisées en C, exemple:
static int myInt = 5;
Es ce que vous vous être déjà poser la question suivante : comment cette variable est elle initialisée ? Cette
instruction n’est exécutée par aucune fonction durant tout le déroulement du programme. Cette initialisation est
par conséquent une tâche supplémentaire du code de démarrage, qui est réalisée par un processus appelé « le
traitement ROM » (ROM-Processing).
Le graphique suivant illustre l’initialisation des variables globales :
RAM
_data
ROM/Flash
.data
/* variable globale
à initialiser
*/
static int myInt = 5;
_edata
Valeur d’initialisation
_etext
Figure 100 : L’initialisation des variables globales
Version 3.1, juin 2008
Page 142
Informtique 3
Le démarrage d’un programme C
Le code de démarrage copie les valeurs d’initialisation des variables globales, depuis le flash dans la RAM. Cela
peut être programmé de la manière suivante :
/* copy .data section, ininialized variables */
LDR
r1, =_etext
LDR
r2, =_data
LDR
r3, =_edata
cpydata_loop:
CMP
r2, r3
LDR LO r0, [r1], #4
STRLO
r0, [r2], #4
BLO
cpydata_loop
_etext est l’adresse de départ de la zone de la flash, qui contient les valeurs d’initialisation. _data et
_edata désignent respectivement le début et la fin de la zone .data, qui contient les variables globales à
initialiser. _etext, _data et _edata sont définies dans le fichier ldscript_ram.
Remarque : Lorsque vous travaillez avec le débuggeur, vous chargez le programme dans la RAM, à travers son
interface. Dans ce cas, le débuggeur initialise automatiquement les variables globales. Les systèmes, prêts pour
la commercialisation, ne contiennent plus de débuggeur pour réaliser cette initialisation. Dans ce cas, il faut
absolument utiliser le code de démarrage.
Mise à zéro des variables non initialisées
Les données non initialisées et la pile sont déposées dans la section .bss. Toutes ces variables sont initialisées
avec 0. Le code est identique à celui pour l’initialisation des variables :
/* Clear .bss section (uninitialized data, stack) */
MOV
r0, #0
LDR
r1, =_bss_start
LDR
r2, =_bss_end
zerobss_loop:
CMP
r1, r2
STRLO
r0, [r1], #4
BLO
zerobss_loop
Initialisation du paquet de support de la platine
Le paquet de support de la platine (Board-Support-Package abrégé par BSP) initialise les composants hardware
de la périphérie.
10.5 Le programme principale
Les applications simples ne nécessitent par de systèmes d’exploitation temps réel (Real Time Operating System
abrégé par RTOS). Le programme principal peut alors posséder la structure suivante :
Dans une première étape, il faut initialiser l’application :
• Les composants hardware de la périphérie, à l’aide de leurs registres de configuration
• Les données : les variables, les structures dynamiques etc.
L’initialisation du hardware peut être critique en temps lorsque, par exemple, les sorties du processeur doivent
être rapidement fixés à des niveaux prédéfinis (Exemple : contrôle de moteur). Cette initialisation doit
éventuellement être réalisée dans le code de démarrage ou de façon hardware.
Dans uns deuxième temps les fonctions des applications sont appelées de façon cyclique, à l’aide d’une boucle
infinie.
Il en résulte le diagramme de « Nassi-Schneidemann » suivant pour le programme principale :
Version 3.1, juin 2008
Page 143
Le démarrage d’un programme C
Informtique 3
=
Initialisation du hardware
Initialisation des données
Boucle infinie
1er Fonction de l’application
2ième Fonction de l’application
...
Nième Fonction de l’application
Figure 101 : Programme principale
Le travail avec les interruptions :
Lorsque vous travaillez avec des interruptions (ISR), il faut faire attention de ne pas perdre trop de temps dans
leurs routines des services. En effet il est fortement recommandé de n’y réaliser que les tâches les plus
importantes, comme par exemple l’activation et la désactivation de drapeaux (flag). Le reste du travail peut ainsi
être effectué à l’aide de machine d’état (state events) en dehors de la routine de service.
Exemple :
Lorsque des bytes sont reçus à l’aide d’une interface sérielle, qui génère des interruptions, il faudrait uniquement
stocker les bytes dans un tampon. Le traitement de ces bytes devrait être réalisé en dehors de la routine de
service.
Un point très important est l’échange de données entre les routines de services et les fonctions de l’application.
Ici la communication n’est possible qu’à l’aide de variables globales (a moins que le système possède un RTOS).
Mais il faut toujours faire attention au fait que les routines de service peuvent sur écrire les données, sans que les
fonctions de l’application principale ne le remarque. Cela est surtout critique avec les données structurées. Par
exemple supposons que le programme possède un tampon de réception de 10 bytes, qui sont remplis par une
routine de service et qui sont lus par les fonctions de l’application principale. Admettons que durant la lecture du
cinquième byte, par une des fonctions de l’application principale, une interruption apparaît pour indiquer la
réception de 10 nouveaux bytes. La routine de service sur écrit alors les 10 bytes du tampon de réception. La
fonction de l’application principale va continuer sa lecture avec le sixième byte, comme si rien ne s’était produit.
Finalement l’application va poursuivre son travaille avec des données inconsistantes. Il faut donc introduire des
mécanismes, qui permettent der verrouiller ces opérations mutuellement. C'est-à-dire qu’aucune interruption de
réception ne devrait être générée pendant que les données sont ne train d’être lues. Le tout peut devenir très
complexe, lorsque plusieurs applications sont exécutées simultanément. Si cette complexité n’est pas maîtrisée
(cela est sûrement le cas, lorsque des nouvelles fonctionnalités, qui n’étaient pas planifiées ont été ajoutée par la
suite), le système va chuter immanquablement.
Version 3.1, juin 2008
Page 144
Le démarrage d’un programme C
Informtique 3
1er fonction de
l’application
ième
n
fonction
de l’application
ième
n-1
fonction
de l’application
2ième fonction
de l’application
3ième fonction
de l’application
ISR
4ième fonction
de l’application
Variables
globales
Figure 102 : Transfert de données entre les routines de service et les fonctions de l’application
Un RTOS n’est pas nécessaire pour les applications simples. Par contre, un RTOS est recommandé pour les
applications complexes, si les ressources hardware le permettent (CPU, taille de la mémoire etc.). Le module
d’approfondissement « système d’exploitation temps réel » traite ce sujet plus en détail.
Version 3.1, juin 2008
Page 145
Informtique 3
L’interface C et assembleur
11 L’interface C et assembleur
11.1 Introduction
Aujourd’hui la plupart des microcontrôleurs sont programmés à l’aide de langages de programmation évolués,
comme le C et le C++. Toutefois, les parties du code, qui sont critiques soit en temps ou en mémoire, sont
toujours définies en assembleur. Ce qui est particulièrement le cas pour les fonctionnalités suivantes :
• Accès optimal au hardware, spécialement pour les driver
• Les algorithmes, qui exigent une puissance de calcul élevée, afin de pouvoir utiliser la CPU de façon optimal
(unité de multiplication et d’accumulation)
• Les fonctions qui sont souvent traitées, afin d’augmenter la performance du système
• Accès aux registres de la CPU, qui ne sont pas accessibles en C
Dans ce cas une attention particulière doit être apportée sur l’interface C/assembleur. Cette interface dépend
technologiquement de la famille des microcontrôleurs et de leur environnement de développement. Les points
suivants sont à considérer :
• Appel des sous routine assembleur depuis les fonctions C et inversement
• Transmission de paramètres et retour de valeur
• Utilisation de variable C en assembleur et inversement
• Assembleur en ligne
Les mécanismes décrits dans se chapitres se réfèrent au PXA27x de XScale, au compilateur GNU (gcc) et à
l’assembleur (gas) de cette famille de processeur.
11.2 Les appels des sous routines assembleur
depuis le C
Les sous routines en assembleur peuvent être appelées à partir des fonctions C et, inversement, les fonctions C
peuvent être appelées depuis les sous routines en assembleur. Pour cela il faut que les noms soient identiques.
Remarque : Dans certain environnement de développement il faut ajouter un « _ » au début du nom symbolique
assembleur. Cela n’est cependant pas le cas avec les compilateurs GNU.
Exemple pour le code C :
extern int asmsub (int par1, int par2);
int cfunc (int par1, int par2){
return (par1 + par2);
}
void main(void)
{
...
res = asmsub(par1, par2);
...
}
Exemple pour le code assembleur :
Version 3.1, juin 2008
Page 146
L’interface C et assembleur
Informtique 3
.global
.extern
asmsub:
STR
...
BL
...
LDR
asmsub
cfunc
@ gives symbol external linkage
@ specify that cfunc is defined in some other source code file
lr, [sp, #-4]!
@ assembler subroutine
@ save return address on stack
cfunc
@ call C-function
pc, [sp], #4
@ return
11.3 Transmission de paramètres aux sous routines
assembleur
Le chapitre 8 « les sous routines » traite la transmission des paramètres selon le standard APCS (ARM Procedure
Call Standard). Ce standard doit être respecté si l’on veut programmer en combinant les langages de
programmation C et assembleur.
Ce standard peut être résumé de la manière suivante :
• Les quatre premiers paramètres sont transmis avec les registres r0 à r3, indépendamment du fait que l’on
appel une fonction C ou une sous routine en assembleur.
• Les paramètres suivants sont transmis à l’aide de la pile.
• Le résultat est retourné avec le registre r0.
11.4 Les registres utilisés par le compilateur
L’APCS spécifie également l’utilisation des registres pour le compilateur. Ces registres doivent donc être utilisés
de la même façon par le programmeur assembleur (voir également le chapitre 8) :
r13 / sp : pointeur de pile
r14 / lr : registre du relieur (link register)
r15 / pc : compteur de programme (program counter)
11.5 L’utilisation de variables en commun
Les variables globales peuvent également être utilisées en commun, dans les parties C et assembleur. Pour cela il
faut faire attention, comme ce fut le cas pour les sous routines et les fonctions, que leurs noms soient identiques
en C comme en assembleur. Ces variables en commun peuvent être définies soit dans la partie C ou dans celle en
assembleur.
L’exemple suivant contient une variable globale définie en C (c_var) et une variable globale définie en
assembleur (asm_var) ainsi que les accès sur ces dernières :
Code C :
/* global variables */
int c_var;
extern int asm_var;
void ctest_var(void){
...
asm_var = 0x22;
c_var = 0x55;
}
// reserve memory for word-variable
// specified in assembler source
// modify assembler variable
// modify C variable
Code assembleur :
Version 3.1, juin 2008
Page 147
L’interface C et assembleur
Informtique 3
.global
.extern
...
asm_var
c_var
@ give asm_var external linkage
@ specified in C source
.data
asm_var: .space
4, 0x11
@ global asm_var, initialized with 0x11111111
.text
asmtest_var:
STR
LDR
MOV
STR
LDR
MOV
STR
LDR
lr,
r0,
r1,
r1,
r0,
r1,
r1,
pc,
@
@
@
@
@
@
@
@
[sp, #-4]
=c_var
#0x55
[r0]
=asm_var
#0x11
[r0]
[sp], #4
save return address on stack
r0 holds address of variable c_var
r1 holds value to write to c_var
c_var = 0x55
r0 holds address of variable asm_var
r1 holds value to write to asm_var
asm_var = 0x11
return
11.6 L’assembleur en ligne
L’assembleur en ligne permet d’insérer des lignes en assembleur directement dans le code C. Il est ainsi possible
d’exécuter les instructions ARM, qui ne sont pas soutenues par le compilateur C. Où le contenu des registres, qui
ne sont pas accessible en C, peut être modifié ; comme par exemple tous les registres de la CPU et du
coprocesseur.
L’utilisation de l’assembleur en ligne peut aider de temps en temps. Toutefois, des effets de bord non souhaités
peuvent apparaître ! Il faut par conséquent faire très attention.
L’instruction (statement) « asm » est mise à disposition par le compilateur GNU gcc pour insérer de
l’assembleur en ligne dans le code C. Cette instruction n’est pas définie par le standard ANSI-C. Par conséquent
cette dernière dépend de l’environnement de développement. Les autres compilateurs utilisent des expressions
comme ASM, __asm ou ASMLINE.
L’utilisation générale de l’instruction asm est la suivante :
asm volatile (code : output operand list : inpup operand list : clobber list);
Exemple :
asm volatile ("AND %0, %1, #0xFF" : "=r" (result) : "r" (value));
Cette instruction peut paraître un peu compliquée. « volatile » est obligatoire, afin que le compilateur C
n’optimise pas l’instruction asm. L’instruction en soit est composée de quatre colonnes :
1. Le code contient les instructions assembleur, qui ont été définies sous forme de chaîne de caractère :
"AND %0, %1, #0xFF"
2. Output operand list : Les opérandes de sortie, séparées par des virgules, peuvent être définies dans la liste
des opérandes de sortie : "=r" (result). Cette liste des opérandes permet d’accéder également aux
variables C. %0 se réfère au premier élément de la liste. "=r" Signifie que le compilateur peut utiliser un
registre, mais uniquement en mode écriture « write only ».
3. Input operand list : Les opérandes d’entrée, séparées par des virgules, peuvent être définies dans la liste
des opérandes d’entrée : "r" (value). Du fait que ce dernier est le deuxième opérande, %1 permet
d’accéder à la variable value. "r" signifie que le compilateur doit utiliser encore un registre
quelconque.
4. Clobber list : Cette liste informe le compilateur sur les registres, mémoire ou de statut, qui doivent être
modifiés par le code assembleur. La liste clobber est vide dans l’exemple de ci-dessus.
L’exemple le plus simple : Une seule ligne d’assembleur est programmé, sans opérande et sans liste clobber :
asm volatile ("MOV r0, r0");
// NOP (No Operation)
Lorsque plusieurs instructions assembleur peuvent être programmées de la manière suivante :
Version 3.1, juin 2008
Page 148
L’interface C et assembleur
Informtique 3
asm volatile (
"MOV r0, r0"
"MOV r0, r0"
);
"\n\t"
"\n\t" permet d’augmenter la lisibilité du code assembleur, qui est généré par le compilateur.
Si une variable C doit être utilisée en tant que paramètre d’entrée, elle peut être définie dans une liste des
opérandes d’entrée. L’exemple suivant ne contient pas de paramètres de sortie, la liste des opérandes de sortie est
ainsi vide. L’exemple illustre également l’accès au registre CPSR, ce qui ne serait pas possible en C :
asm volatile("MSR CPSR, %0" : : "r" (status));
// load CPSR register with value in status
Le compilateur génère à partir de cette instruction ASM le code objet (désassemblé) suivant :
LDR
LDR
MSR
r3, =status
r3, [r3]
CPSR, r3
La liste des opérandes d’entrée spécifie l’état "r" pour la variable status. Le compilateur peut ainsi choisir le
un registre quelconque pour exécuter l’instruction. Le registre r3 a été choisi dans l’exemple de ci-dessus.
Il faut informer le compilateur, lorsque l’instruction assembleur change le contenu d’un registre. Le compilateur
ne possède pas les moyens pour remarquer cela. Il dépend donc de cette information, afin qu’il n’y ait pas de
problèmes avec ses propres registres. La déclaration des registres, qui sont modifiés par l’instruction assembleur,
s’effectue dans la liste clobber :
asm volatile("MOV r1, r0" : : : "r1");
// register r1 modified
Finalement encore quelques mots concernant l’exemple du début de ce chapitre :
asm volatile("AND %0, %1, #0xFF" : "=r" (result) : "r" (value));
Ce code possède un paramètre d’entrée, qui est la variable value. value est combiné de façon AND avec la
valeur #0xFF, c'est-à-dire que les 3 bytes de poids plus fort sont effacés. Le résultat de l’opération est déposé
dans la variable result. L’exemple illustre comment l’instruction assembleur peut être étendue et complétée
avec des variables C. Cela n’est par conséquent plus une instruction assembleur pure, mais plutôt un mélange de
C et d’assembleur. Le compilateur génère à partir de cette instruction ASM le code objet (désassemblé) suivant :
LDR
LDR
AND
LDR
STR
r3,
r3,
r2,
r3,
r2,
=value
[r3]
r3, #255
=result
[r3]
Du fait que ce code a été généré par le compilateur, il ne faut pas déclarer les registre r2 et r3, qui ont été
modifiées, dans la liste clobber.
Version 3.1, juin 2008
Page 149
Informtique 3
L’adressage des registres en C
12 L’adressage des registres en C
Dans la programmation proche du hardware, il est souvent nécessaire de déposer des variables à des adresses
bien définies (comme par exemple les registres des microcontrôleur ou des éléments périphériques). Pour cela il
existe les techniques suivantes :
a) Avec #define selon ANSI-C
b) A l’aide de section absolue
c) A l’aide de mots clés spécifiques fournis par le fabriquant
12.1 L’adressage avec #define
Cette variante a été introduite dans le module « Informatique 2 » et est motionné dans ce cours pour des raisons
d’intégrité. C’est la seule méthode pour définir des variables à des adresses fixes, selon le standard ANSI-C.
1) Les variables sont définies de la manière suivante :
// für eine 8-bit Variable auf der Adresse 0x1000
#define reg_8 *((volatile unsigned char *) 0x1000)
// für eine 16-bit Variable auf der Adresse 0x2000
#define reg_16 *((volatile unsigned short *) 0x2000)
// für eine 32-bit Variable auf der Adresse 0x3000
#define reg_32 *((volatile unsigned long *) 0x3000)
2) L’accès aux variables s’effectue de la manière suivante :
reg_16 = 0x1234;
12.2 La définition de sections absolues
Les environnements de développement permettent de définir des nouvelles sections, qui possèdent leur propre
adresse.
Le compilateur GNU met à disposition le mot clé « __attribute__ », qui permet de spécifier des attributs
pour les variables. Les attributs sont définis entre parenthèses doubles après le mot clé « __attribute__ »,
et la section avec le mot clé « section ».
Exemple : Il faut définir une variable « led », qui permet d’accéder à la ligne de LED sut le kit de
développement CARME. Ces LED sont accessible à l’adresse 0x0C003000.
char
led
…
led = 0x55;
__attribute__ ((section (".LED"))) = 0;
La première ligne du code C défini une variable led de 8 bits. L’expression
« __attribute__ ((section (".LED"))) » indique que la variable led doit se trouver dans la
section ".LED". L’instruction « led = 0x55; » permet d’afficher un échantillon de bit sur les LED.
La section .LED doit être encore définie dans le script du relieur « ldscript_ram ». Pour cela deux étapes
sont nécessaires.
D’abord il faut spécifier les zones mémoire du kit de développement CARME IO1 :
#pragma separate myabsvar
MOMORY
{
flash
: ORIGIN = 0x00000000, LENGTH = 0x02000000
ram
: ORIGIN = 0xA0000000, LENGTH = 0x02000000
carmeIO1
: ORIGIN = 0x0C003000, LENGTH = 0x0410
}
Version 3.1, juin 2008
/* 32 MB FLASH */
/* 64 MB RAM */
/* CARME IO1 */
Page 150
L’adressage des registres en C
Informtique 3
Ensuite il faut spécifier la section .LED :
.CARME_IO1 :
{
. = ALIGN(4);
_carmeio1 = .;
*(.LED)
. += 0x1FF
*(.SWITCH)
. += 0x1FF
*(.PIO)
. += 0x10
} >carmeIO1
/*
/*
/*
/*
/*
/*
/*
/*
next 32-bit boundary */
defines a symbol for start of CARME IO1 */
LED section for CARME IO1 */
LED address is 0x0C003000 to 0x0C0031FF */
Switch section for CARME IO1 */
Switch address is 0x0C003200 to 0x0C0033FF */
PIO section for CARME IO1 */
PIO address is 0x0C003400 to 0xC003410 */
L’exemple ci-dessus du manuscrit du relieur montre, comment les registres de configuration des différentes
entrées et sorties du kit de développement CARNEIO1 peuvent être rassemblés en sections.
12.3 L’utilisation
fabriquant
de
mots
clés
spécifiques
du
Certain compilateur mettent à disposition des mots clés spécifiques, pour déposer les variables à des adresses
fixes, comme par exemple « _at_ » ou « _at ».
Exemple :
volatile unsigned short reg1 _at 0x1000;
Le compilateur GNU ne propose pas de tel mot clé.
Version 3.1, juin 2008
Page 151
Informtique 3
Annexe A: Stockage des nombres
Annexe A: Stockage des nombres
Les grandeurs suivantes sont mises à disposition pour stocker les nombres :
Bit (1 Bit): Domaine de représentation 0..1
0
Nibble (4 Bit): Domaine de représentation 0...15
3
0
Byte (8 Bit): Domaine de représentation 0..255
7
0
Halfword (16 Bit): Domaine de représentation 0…65535
15
0
Word (32 Bit): Domaine de représentation 0…429496729
31
0
Le bit le plus faible d’un nombre binaire (byte, demi mot et mot) est qualifié de LSB (Least Significant Bit). Le
bit le plus fort est le MSB (Most Significant Bit).
Un demi mot est composé de deux bytes : le « lower Byte » (les bits 0 à 7) et le « upper Byte » (les bits 8 à 15).
Un mot est composé de deux demi mots : « lower Halfword » (bit 0 bis 15) et le « upper Halfword » (bit 16 bis
31).
Version 3.1, juin 2008
Page 152
Annexe B: Les format des nombres
Informtique 3
Annexe B: Les format des nombres
Complément à deux
Le complément à deux permet de représenter les nombres négatifs dans le système binaire. Des symbole
supplémentaire comme + et – ne sont ainsi plus nécessaire.
Dans le complément à deux, les nombres positifs sont représentés avec un premier bit 0 (le bit de poids le plus
fort qui est également appelé le bit de signe). Les valeurs négatives sont représentées avec un premier bit 1. Ces
dernières sont codées de la manières suivante : tous les bits du nombre positif sont d’abord inversés et la valeur 1
est ensuite additionné au résultat.
Exemple :
+4(10) = 00000100
-4(10)
= 11111011 + 1 = 11111100
-1(10)
= 11111111
127(10) = 01111111
-128(10) = 10000000
Le complément est un système de nombres signés, qui ne possède qu’une seule représentation de la valeur nulle.
Les additions et les soustractions peuvent être ainsi être effectuées sans dissociation de cas. Il n’existe qu’une
seule représentation de la valeur nulle, si l’on admet que les bits, résultants des dépassements de capacité, sont
tronqués durant les opérations.
Par exemple, l’opération :
-4 + 3 = -1
sera calculé de la manière suivante :
11111100 + 00000011 = 11111111;
Nombre à virgule flottante
Les nombres réels sont représentés dans les ordinateurs à l’aide de nombres à virgule flottante (Floating Point)
avec le format IEEE. Le nombre à virgule flottante Z est ainsi représenté avec sa mantisse (M) et sont exposant
(P) part rapport à la base 2.
Il existe plusieurs possibilités pour stocker la mantisse et l’exposant dans la mémoire. Par exemple avec la
précision simple (32 bits) ou double (64 bits). Ce chapitre se concentre uniquement sur le format précision
simple. Ce dernier est stocké dans la mémoire de la manière suivante :
31
30
V
1 bit
23 22
E + 127
8 bits
Représentation
V
E
M
0
M
23 bits
Description
Bit de signe
Exposant
Mantisse
Domaine des nombres
0: positif, 1: négatif
-126 bis +127
1,111..111 bis 1,999...999
Tabelle 2: Précision simple de nombres à virgule flottante
Seule la partie fractionnaire de la mantisse est stockée dans la mémoire (hidden bit). Il en résulte la formule
suivante pour la construction des nombres à virgule flottante :
Z = (-1)V M * 2E-127
Version 3.1, juin 2008
Page 153
Informtique 3
Annexe C: La documentation
Annexe C: La documentation
Nom
ARM Architecture Reference Manual,
ARM DDI 0100E
Intel PXA27x Processor Family Developer's Manual
Description détaillée des composants périphériques du chip, 1246 pages
Intel PXA27x Processor Core Developer's Manual
Registres du coprocesseur, cache des instructions et des données, les
spécialités du processeur, 220 pages
Intel PXA270 Electrical, Mechanical and Thermal Specification
Timings, pin out … 128 pages
Intel PXA27x Processor Family Memory Subsystem
Flash, LPSDRAM, 138 pages
Intel XScale Microarchitecture
Technical Summary, 14 pages
Intel PXA27x Processor Family Design Guide
Intel PXA27x Processor Developer's Kit
Edition / Auteur
ARM Limited
Référence
[1]
Intel
[2]
Intel
[3]
Intel
[4]
Intel
[5]
Intel
[6]
Intel
Intel
[7]
[8]
Tableau 52 : Documentation
Titre
ARM System Developmer's Guide
ISBN: 978-1-55860-874-0
ARM System on Chip Architecture
ISBN: 0-201-67519-6
Edition / Auteur
Sloss / Symes / Wright
Morgan Kaufman Verlag
Steve Furber
Addison Wesley
Référence
[10]
[11]
Tableau 53 : La littérature
Nom
GNU Assembler
http://www.gnu.org/software/binutils/manual/gas2.9.1/html_mono/as.html
GNU Compiler
http://gcc.gnu.org/onlinedocs/
Edition / Auteur
GNU
Référence
[20]
GNU
[21]
Tableau 54 : Les liens Internet
Version 3.1, juin 2008
Page 154
Annexe D: Tableau des valeurs ASCII
Informtique 3
Annexe D: Tableau des valeurs ASCII
Caract. Valeur Hex.
Caract. Valeur Hex.
Caract. Valeur Hex.
Caract. Valeur Hex.
NUL
0
0x00
SOH
1
0x01
STX
2
0x02
ETX
3
0x03
EOT
4
0x04
ENQ
5
0x05
ACK
6
0x06
BEL
7
0x07
BS
8
0x08
TAB
9
0x09
LF
10
0x0A
VT
11
0x0B
FF
12
0x0C
CR
13
0x0D
SO
14
0x0E
SI
15
0x0F
DLE
16
0x10
DC1
17
0x11
DC2
18
0x12
DC3
19
0x13
DC4
20
0x14
NAK
21
0x15
SYN
22
0x16
ETB
23
0x17
CAN
24
0x18
EM
25
0x19
SUB
26
0x1A
ESC
27
0x1B
FS
28
0x1C
GS
29
0x1D
RS
30
0x1E
US
31
0x1F
Leerz.
32
0x20
!
33
0x21
"
34
0x22
#
35
0x23
$
36
0x24
%
37
0x25
&
38
0x26
'
39
0x27
(
40
0x28
)
41
0x29
*
42
0x2A
+
43
0x2B
,
44
0x2C
-
45
0x2D
.
46
0x2E
/
47
0x2F
0
48
0x30
1
49
0x31
2
50
0x32
3
51
0x33
4
52
0x34
5
53
0x35
6
54
0x36
7
55
0x37
8
56
0x38
9
57
0x39
:
58
0x3A
;
59
0x3B
<
60
0x3C
=
61
0x3D
>
62
0x3E
?
63
0x3F
@
64
0x40
A
65
0x41
B
66
0x42
C
67
0x43
D
68
0x44
E
69
0x45
F
70
0x46
G
71
0x47
H
72
0x48
I
73
0x49
J
74
0x4A
K
75
0x4B
L
76
0x4C
M
77
0x4D
N
78
0x4E
O
79
0x4F
P
80
0x50
Q
81
0x51
R
82
0x52
S
83
0x53
T
84
0x54
U
85
0x55
V
86
0x56
W
87
0x57
X
88
0x58
Y
89
0x59
Z
90
0x5A
[
91
0x5B
\
92
0x5C
]
93
0x5D
^
94
0x5E
_
95
0x5F
`
96
0x60
a
97
0x61
b
98
0x62
c
99
0x63
d
100
0x64
e
101
0x65
f
102
0x66
g
103
0x67
h
104
0x68
i
105
0x69
j
106
0x6A
k
107
0x6B
l
108
0x6C
m
109
0x6D
n
110
0x6E
o
111
0x6F
p
112
0x70
q
113
0x71
r
114
0x72
s
115
0x73
t
116
0x74
u
117
0x75
v
118
0x76
w
119
0x77
x
120
0x78
y
121
0x79
z
122
0x7A
{
123
0x7B
|
124
0x7C
}
125
0x7D
~
126
0x7E
DEL
127
0x7F
Tableau 55 : Tableau des valeurs ASCII
Version 3.1, juin 2008
Page 155
Index
Informtique 3
Index
.
8
.2byte ............................... 93
.4byte ............................... 93
.align ............................... 90
.arm .................................... 89
.ascii ............................... 92
.asciz ............................... 92
.asm .................................... 57
.balign ............................. 91
.bin .................................... 58
.bss .................................... 95
.byte ................................. 93
.data ................................. 95
.elf .................................... 58
.else ............................... 100
.end .................................... 99
.endif ............................. 100
.endm ............................... 101
.equ .................................... 95
.extern ............................. 90
.global ............................. 90
.hword ............................... 93
.if .................................... 100
.ifndef ........................... 101
.include .......................... 94
.irp .................................. 104
.lis .................................... 57
.macro ............................. 101
.map .................................... 58
.o......................................... 57
.org .................................... 95
.p2align .......................... 92
.rept ............................... 103
.s......................................... 57
.section ............ 95, 96, 153
.section absolue .................. 153
.set .................................... 95
.space ............................... 94
.text ................................. 95
.thumb ............................... 89
.word ................................. 93
8051......................................28
_
__attribute__ ............ 153
_at .................................... 154
_at_ .................................. 154
=
= 95
1
1 of X Decoder....................... 8
6
68HCxx................................ 28
Version 3.1, juin 2008
A
abt.........................................39
Acknowledge bit ..................24
ADC ................................78, 79
ADD ................................78, 79
ADR ....................................102
adressage des registres .......153
adresse de retour.................106
adresse physique...................14
adresse virtuelle....................14
ALU .................................5, 36
amplificateur de sortie ..........18
AND ................................78, 81
anneau de tampons .............140
APCS..........107, 110, 112, 150
architecture.............................3
architecture ARM.................30
architecture de Harvard ..........4
architecture de stockage .......11
architecture de von Neumann.3
architecture RISC .................30
argument.............................113
arithmétique des entiers........78
ARM.....................................30
ARMV5TE...........................60
array ...................................136
ascending............................107
asm ....................................151
ASR ......................................67
assemblage conditionnel.....100
assembleur............................57
assembleur en ligne ............151
assignation des pins..............12
B
B 84
Banked Register ...................41
Barrel Schifter ................36, 67
baud rate ...............................20
BIC ................................78, 81
big endian .............................43
binaire...................................55
bit .......................................155
bit C......................................42
bit d’état ...............................41
bit F ....................................119
bit I .....................................119
bit N......................................42
bit V......................................42
bit Z ......................................42
BKPT ....................................87
BL .................................84, 106
BLX ......................................84
bootloader...........................143
boucle .................................129
boucle d’itération............... 129
boucle do while ............ 134
boucle for ........................ 134
boucle while ................... 133
Branch Target Buffer........... 34
break point........................... 87
BSP.................................... 146
bus d’adresse ................... 6, 46
bus de contrôle....................... 6
bus de données................. 6, 46
BX ........................................ 84
byte .............................. 43, 155
C
call by reference ................ 110
call by value....................... 110
callee.................................. 105
caller .................................. 105
caractérisiques AC............... 12
caractérisiques DC............... 12
carry..................................... 42
case mémoire ....................... 10
cercle de nombre.................. 42
chaîne de caractère ............ 138
champ des étiquettes............ 51
chip select .............................. 8
choix parmi une liste............ 62
CISC .................................... 27
clobber list ......................... 151
CLZ ...................................... 87
CMN ................................ 78, 79
CMP ................................ 78, 79
code d’opération .................. 62
code de condition................. 63
code de démarrage............. 144
code machine ................. 49, 57
code récursif ...................... 106
coeur .................................... 38
cœur d’exécution ................. 35
commentaire ........................ 53
compilateur .......................... 57
complément à deux.............. 55
complément à un.................. 55
compteur de program........... 41
compteur de programme 5, 113
condition.............................. 81
condition d’arrêt .................. 24
condition de démarrage ....... 24
Condition Flags ................... 41
constante........................ 53, 63
contexte ............................. 128
Contitional Execution .......... 42
control bus ............................. 6
contrôleur d’interruption...... 38
contrôleur d’interrutpion.... 124
convertisseur A/D................ 26
convertisseur D/A................ 26
coprocesseur ........................ 65
Coprocessor ......................... 35
Page 156
Index
Informtique 3
Core Memory Bus................ 35
counter ................................. 25
CPSR ............................ 41, 119
CPU........................................ 4
CPU32.................................. 28
Cross Assembleur ................ 57
crt0 .................................. 144
CS........................................... 8
D
Data Abord......................... 116
Data Cache ........................... 34
Debug................................... 35
débuggeur............................. 58
Decode ............................. 5, 37
décodeur d’adresse................. 8
déroulement d’une requête
d’interruption ................. 123
descending.......................... 107
directive de l’assembleur ..... 88
directive de programmation . 50
disabled .............................. 119
dispositif de commande ......... 5
DMA .............................. 17, 39
DMMU................................. 34
do while ........................ 134
documentation...................... 12
DRAM ................................. 10
DSP .................................. 4, 27
E
éditeur .................................. 56
EEPROM ............................... 9
empty ................................. 107
enabled ............................... 119
entrée et sortie digitale ......... 19
environnement de
développement ................. 55
EOR ................................ 78, 81
EPROM.................................. 9
équation logique..................... 8
ET......................................... 81
état du processeur................. 41
évènement .......................... 116
exception ............................ 116
Exception Handler...... 116, 121
Execute............................. 5, 37
exécution conditionnelle ...... 42
Execution Core..................... 35
F
famille de microcontrôleur... 27
famille de processeur ARM . 33
FeRAM ................................ 10
Fetch................................. 5, 37
fichier assembleur ................ 50
fichier de mappage ............... 58
fichier elf.............................. 58
fichier objet .......................... 57
FIQ ............................... 39, 116
FLASH................................. 10
FLOPS ................................. 29
Version 3.1, juin 2008
for ....................................135
FPU ........................................5
frame pointer ..............113, 150
frames...................................15
full ......................................107
G
gestion de projet ...................58
gestionnaire de consommation
..........................................38
GPIO ....................................39
H
halfword .......................43, 155
Header ..................................51
hexadécimal..........................93
hierarchie des composants de
stockage............................13
I
I2C ........................................23
ICLR ..................................118
IDE .......................................55
if .......................................130
IMMU ..................................34
indexation.............................62
initialisation des variables ..145
input operand list................151
instruction.........................1, 51
instruction ARM...................62
Instruction Cache..................34
instruction conditionnelle .....63
instruction d’état...................75
instruction de décalage .........82
instruction de transport entres
registres ............................66
instruction logique................81
instruction non définie........116
instruction pour la pile..........74
instruction pour le
coprocesseur .....................76
Instruction Unit ......................5
interface C/assembleur .......149
interface clavier ....................39
interface du bus ......................5
interface sériel ................20, 39
Interrupt Controller ............124
Interrupt Mask ......................41
Interrupt Service Routine ...116
Interrupt-Controller ..............38
interruption.........116, 118, 147
interruption hardware .........118
interruption software ...86, 116,
118
intructions de transfert de
données.............................66
IRQ...............................39, 116
ISR .............................116, 147
J
jeu d’instruction..............52, 60
jeu d’instruction Thumb .......64
JTAG ................................... 35
jump table .......................... 132
L
langage de programmation
évolué ...................... 49, 149
last in, first out................... 107
LCD Panel ........................... 39
LDC ................................ 66, 76
LDM ................................ 66, 72
LDR ........................... 66, 68
LDR B............................... 69
LDR H............................... 69
LDR SB ............................ 69
LDR SH ............................ 69
Link Register ....................... 41
Linker .................................. 58
Linkmap............................... 99
list file.................................. 57
listing de l’assembleur ......... 57
little endian .......................... 43
localisateur........................... 58
Locator................................. 58
logique ................................. 55
lower byte .......................... 155
LSL ...................................... 67
LSR ...................................... 67
M
macro instruction ............... 101
main ................................. 144
manipulation des bits ........... 81
manuscrit de reliage............. 97
masquage des interruptions 119
MC683xx............................. 28
MCR ................................ 66, 76
mémoire cache..................... 13
mémoire de masse ............... 14
mémoire de travail............... 13
mémoire des données............. 3
mémoire non volatile ............. 9
mémoire programme.............. 3
mémoire volatile.................. 10
Memory Controller .............. 39
memory map.................... 7, 44
memory matrix .................... 10
microcontrôleur ................... 27
microprocesseur................... 27
MIMD.................................... 2
Mini D-Cache ...................... 34
MIPS.................................... 29
MISD ..................................... 2
MISO ................................... 22
MLA ................................ 78, 79
MMU ............................. 14, 34
mnemonics........................... 51
mode d’adressage ................ 70
mode d’utilisation................ 41
mode de fonctionnement ..... 39
mode privilégié.................... 39
modèle de stockage.............. 43
modulo................................. 55
Page 157
Index
Informtique 3
MOSI ................................... 22
mot clé................................ 154
MOV ...................................... 66
MRAM................................. 10
MRC ................................ 66, 76
MRS ................................ 66, 75
MSP430 ............................... 28
MSR ................................ 66, 75
MUL ................................ 78, 79
Multiply-Accumulate ........... 35
MVN ...................................... 66
N
negative................................ 42
nibble ................................. 155
nom de registre..................... 62
Nonnested Interrupt Handler
....................................... 127
NOT ...................................... 81
nul ...................................... 138
O
open drain............................. 19
opérande......................... 36, 52
opérateur .............................. 54
opérateur assembleur.......... 100
opération .............................. 51
opération de décalage..... 63, 67
opération pop ..................... 140
opération push.................... 139
organisation de la mémoire .. 12
ORR ................................ 78, 81
OTP........................................ 9
OU........................................ 81
output operand list.............. 151
Overflow .............................. 42
P
pages .................................... 15
paramètre............................ 111
périphérie ............................. 18
PIC ....................................... 28
pile ............................. 106, 139
pipeline................................. 36
plan de mémoire............... 7, 44
point d’arrêt.......................... 87
pointeur de pile ... 41, 107, 113,
150
pointeur de trame ............... 150
pop ..................................... 107
portable ................................ 49
post indexation ..................... 70
Power-Management ............. 38
pré indexation....................... 70
Prefetch Abord ................... 116
principe des contributions .. 110
priorité des interruptions .... 117
priorité des opérateurs.......... 55
processus de démarrage ..... 143
Program Counter ...... 5, 41, 150
programme principale ........ 146
pseudo code.......................... 49
Version 3.1, juin 2008
pseudo instruction ................88
push ....................................107
PWM ....................................39
Q
QADD ..............................78, 79
QADDD ..................................78
QDADD ..................................79
QDSUB ..................................79
QDSUM ..................................78
QSUB ..............................78, 79
queue de tampons ...............140
R
RAM.....................................10
ramification ........................129
ramification multiple ..........131
ramification simple.............130
Real Time Clock...................39
registre........................5, 13, 40
registre de reliage .41, 106, 113
registre fantôme....................41
registre scratch....................113
relieur ...................................58
reset ............................116, 143
ressource hardware.............148
retour de sous routine .........106
RISC.....................................27
ROM.......................................9
ROM-Processing ................145
ROR ......................................67
rotate.....................................82
RRX ......................................67
RS232...................................20
RSB ................................78, 79
RSC ................................78, 79
RTOS .................................146
S
saut de programme ...............83
saut de programme absolu....83
saut de programme conditionel
..........................................82
saut de programme
inconditionel.....................82
saut de programme relatif.....83
sauvegard des registres.......110
SBC ......................................79
Schifter .................................37
SD Memory Card .................39
SDRAM................................10
séquence d’instructions ......129
set de registre........................40
shift.......................................82
Sign Extend ..........................43
signal PWM..........................25
signé .....................................55
SIMD......................................1
SISD .......................................1
SMLA ..............................78, 79
SMLAL ............................78, 79
SMLAW ............................78, 79
SMUL ............................. 78, 79
SMULL ................................. 79
SMULW ........................... 78, 79
source d’erreurs ................. 114
sous programme................. 105
sous routine........................ 105
SPI ....................................... 21
SRAM.................................. 10
stack........................... 106, 139
stack pointer..........41, 107, 150
startup .......................... 144
startup code........................ 144
STC ................................ 66, 76
STM ................................ 66, 72
STR................................ 66, 68
STRB ................................... 69
STRD ................................... 69
STRH ................................... 69
string.................................. 138
structure ............................. 138
structure de contrôle .......... 129
structure de données .......... 136
structure de répétition ........ 102
SUB ................................ 78, 79
super pipeline....................... 36
svc........................................ 39
SWI...................................... 86
switch............................. 132
SWP ................................ 66, 72
SWPB ................................... 72
symbole ............................... 53
syntaxe................................. 62
syntaxe de l'assembleur ....... 51
sys........................................ 39
système d’exploitation temps
réel ................................. 148
système de bus....................... 6
système faiblement couplé..... 2
système fortement couplé ...... 2
T
table de vérité ...................... 12
Tableau .............................. 136
Tableau de page................... 15
Tableau de saut .................. 132
Tableau des vecteurs
d’exeption ...................... 120
Tableau multidimensionnel 137
taille de la mémoire ............. 12
TDMI................................... 33
tension du bus ........................ 7
TEQ ...................................... 79
Timer ............................. 25, 39
TLB ..................................... 16
totem pole ............................ 19
Trace Buffer......................... 35
traitement d’exception ....... 116
transfert des paramètres ..... 110
transmission des paramètres
............................... 112, 150
tri state ................................. 19
TST ...................................... 79
Page 158
Index
Informtique 3
U
V
UMLAL ................................. 79
UMLULL ............................... 78
UMULL ................................. 79
und ....................................... 39
unité de calcul ........................ 5
unité de contrôle..................... 5
upper byte........................... 155
usr......................................... 39
v5TE.....................................32
variable globale ..................150
variable locale ....................113
variable registre ..................113
vecteur d’exception ............120
vue d’ensemble des
instructions .......................65
W
while ................................133
Version 3.1, juin 2008
word............................. 43, 155
Write Back........................... 37
Write Buffer......................... 34
X
XOR ...................................... 81
XScale ................................. 33
Z
Zero ..................................... 42
zone mémoire ........................ 3
Page 159