You are on page 1of 118
BOOT Sirvon Table des matiéres 1 Introduction 1.1 LANGAGE d’ASSEMBLAGE vs ASSEMBLEUR, 1.2 Le monde ARM . 1.2.1 Le Cortex M3 12.2 Le eceur Cortex M3 dans le STM32 2 Le Coeurtex M3 17 2.1 Introduction . . . . : cece eee eeee WT 2.2 Modes, priviléges et états Le we .. 17 2.3 Les registres . . . be Le .. 18 2.8.1 Les registres RO A R12 boas eevee 19 2.3.2. Le registre R13 aliasSP ce 20 2.3.3 Le registre R14 alias LR... 0 oe eee es 20 2.3.4 Le registre R15 alias PC... . ‘ se. QL 23.5 Leregistre PSR... ..- +... + cee ees BB 3 Du bon usage des directives 25 3.1 Introduction a. 25 3.1.1 Conventions typographiques et utilisation de symboles 26 3.2 Structure d’un programme .. 0.0.2... 0 cae ve 26 3.2.1 Les sections AREA 3.3 La section de code Be ee eee . awee 3.1 Les étiquettes ... . . Le +2. 3.3.2. Mnémonique 29 3.3.3. Les opérandes 6 31 3.3.4 Commentairesssss . .. . bv BD 3.3.5 Procédure ... . eee sone 88 3.4 La section de données. . . . snes eee eee 33, 3.4.1 Réservation simple .........- ee 33 2 Réservation avec initialisation . . . 34 3:43 _Initialisation des données : le diable est dans les détails... . . 36 3.5 Et c'est tout? heme cee. 86 3.5.1 Directives de gestion de la mémoire feces BT 3.5.2 Directives de gestion projet... saua@---- 88 3.5.3 Directives diverses et variées . . . Wake Ret R ee 40 3 a Parlons d’opérandes AL 42 43 Constante et renommage Opérandes pour instructions courantes. . Rake 4.2.1 Utilisation de registres . 0.0.0... 02. 4.2.2 Opérande immédiat . Opérande pour les aco’s mémoire : modes dadressage 4.3.1 De la notion de pointeur 4.3.2 Les modes d’adressage ‘Tu parles d’un jeu. 58 Guide de lecture 2 5.1.1 _ Liste des suffixes "condition' possibles Les instructions arithmétiques .. . . . ee Les instructions logique et de manipulation de bits Les instructions de transfert interne ee Les instructions de test eee Les instructions de saut . oe Les instructions de load/store . 0... ee 5.7.1 Les transferts simples 5.7.2 Les transferts multiples 5.7.3 Accés a la pile systeme Les instructions "systéme’ et autres Structures algorithmiques et structures de données 6.1 62 63 65 Organigramme versus Algorithme ...........- Structures alternatives . 6.2.1 Alternative simple (ow raceourcie) 6.22 Alternative complate . : 623 Cas particulier d’alternative . . . 624 Choix multiple * Structures itératives . see 6.3.1 La boucle Répéter... jusqu’é 63.2 La boucle Tant que... faire . . 6.3.3 La boucle Pour... . Conditions composées 6.4.1 Alternative avec ET 6.4.2 Itération avec ET . . 64.3 Alternative avec OU 6.4.4 Itération avec OU Structure de données 6.5.1 Tableau a une dimension 6.5.2. Tableau & plusieurs dimensions 6.5.3 Enregistrement . 6.5.4 Tableau non dimensionné, chaine de caractéres 6.5.5 File d’attente, ou queue 41 41 43 43 45 49 50 51 5B 55 56 57 63 64 65 67 67 68 70 70 73 73 cy ey 16 8 79 82 82 6.5.6 Pile cece oes cement: . oo 95 7 Modularité interne 97 7.1 Approfondissement de la notion de procédure . . « - vie 97 T1.1 Appelsimple .. 0-0-0020 e eters . 97 7.12 Appels imbriqués - - dose eeebg ev mea ae oem OF 7.1.3 Exemple "fil rouge’ =... - Scenes 98 72 . 100 Utilité des arguments... 0-0-2 e eee » . 100 7.2.2 Arguments par valeur, arguments par référence. - - 100 7.23 Passage des arguments par les registres généraux pees 101 724 Passage des arguments par une pile... +2. e eee ee = 108 7.2.5 Passage des arguments par la pile systéme . . cee es = 108 726 SurVart du mélange... - 2-0 eee +. 10 73 Données locales - Dees eee MO 7.3.1 Simple réservation des données locales. « - 2 ui. 732 Utilisation d'une liste chainée 0-0 MS 74 Récursivité - we eR BE. Eamew ngeeace.. IT Chapitre 1 Introduction Ua programme d’ordinateur est généralement défini comme étant une séquence d’ins- tructions qui agit sur des données et doit fournir un résultat attendu. Dans un langage de haut niveau, cette séquence et ces données sont décrites sous forme symbolique, abs- traite. Il faut faire usage d’un compilateur pour les traduire en instructions du langage machine, seules comprises par le processeur. Le langage d’assemblage dérive directement du langage machine, si bien que programmer en langage d’assemblage oblige & toujours considérer les choses du point de vue du processeur 1.1 LANGAGE d’ASSEMBLAGE vs ASSEMBLEUR Lorsqu’il exéeute un programme, un processeur informatique obéit donc & une sé quence d’ordres numériques - les instructions - qu'il lit en mémoire : ces instructions y sont codées sous forme binaire. L’ensemble des instructions en mémoire constitue le coce du programme en cours dexécution. D’autres zones de la mémoire sont égale- ment utilisées par le processeur durant exécution du code, essentiellement. une zone contenant les diounées (variables, constantes) et une zone contenant ia pile systen - utilisge par le processeur pour conserver par exemple les adresses de retour lors @’appel de sous-programmes. Code, données et pile systéme sont les trois éléments fondamei taux de tout programme lors de son exécution. On peut programmer directement en langage machine, c’est & dire écrire les séquences de bits des instructions telles quelles. Mais ceci est épouvantablement malcommode, méme si l’on adopte une écriture plus condensée grace A la notation hexadécimale (numération en base 16) des instructions. 11 est bien préférable d’utiliser un sancaye & plage, qui permet une représentation du code dans laquelle des noms symboliques adaptés & la compréhension humaine correspondront aux instructions du langage machine. Le lan- gage d'assemblage permet également de réserver la place nécessaire & la pile systéme et, aux zones de données, en leur donnant, si besoin, une valeur initiale. Pronons l’exemple d’une instruction copiant dans le registre général n°1 du processeur la. valeur 170 (soit AA codé en héxadécimal). Voici comme on Pécrit, en utilisant la syntaxe du langage d’assemblage étudiée ici : mov Rl, #0xAA ; recopie (move) la valeur 170 (AA en héxa) L 3 dans le registre RI Exemple 1 : Une simple ligne de code alors que la méme instruction, représentée en langage machine (base héxamdécimale), sécrit : ESAQ10AA. Le nom symbolique mov porte le nom de - RI et #0x.AA sont ici les ts de l'instruction. Le point-virgule dénote le début dun commentaire qui s'achéve avec la ligne courante. L'agsenttewr est un programme chargé d’effectuer la traduction, en langage ma- chine, du programme écrit, en langage d’assemblage. Il regoit en entrée un fichier source, it en langage d’assemblage, et fournit deux fichiers, le fichier objet contenant le lan- gage machine (et des informations nécessaires a la suite de la fabrication d’un programme exécutable), et le fichier listing d’assemblage faisant le compte-rendu détaillé du travail effectué par l’assembleur'. Le présent polycopié traite du langage d’assemblage en gé- néral mais s’appuie sur les processeurs & base de Cortex M3 proposé par ARM. Cette structure est ensuite intégré par différents fondeurs (Freescale, STmicro,NXP,... ) dans des jicontréleurs contenant, en plus de ce processeur, une mémoire, et des multiples périphériques. Une partie de la documentation de ce cceur de processeur est disponible, au format PDF sur le site ARM 1.2 Le monde ARM ARM (pour Advanced RISC Machines) ne vend pas & proprement AARMM ‘parler des ycontréleurs mais des licences de coeur de microprocesseurs a architecture RISC 32 bits. Cette société basée & Cambridge vise essentiellement les systémes dits embarqués. Pour donner une idée de la position de ce concepteur sur le marché, 95% des téléphones mobiles en 2008 ont été fabriqués avec des processeurs & base d’ARM (I’Iphone d’Apple en fait partie). Depuis 1985 et sa premiere architecture (nommée ARM1), les architectures ARM ont bien stir évoluées. L'architecture sur laquelle est basée le Cortex M3 est larchitecture dénommée ARMV7-M. Voffre d’ARM s’articule autour de 4 grandes familles de produits, et pour lesquelles il a déposé beaucoup de licences © La famille ARM 7 (171 licences?) La famille ARM 9 ( 253 licences) # La famille ARM 10 (72 licences) ® La famille Cortex (69 licences) 1. Signalons un abus de langage fréquent : "programmer en assembleu langage d’assemblage" 2. Chiffres en 2009 au lieu de "programmer en Pm” prundeloud con |elame.de. caphand: NVICL se. CM3Core er ie} | | t » FPB | Privsteeronera! tus | i FicuRE 1.1 ~ Diagramme fonctionnel du Cortex M3 1.2.1 Le Cortex M3 Le Cortex M3 cible particulirement les petits systémes em- Cortex barqués qui requiérent d’importantes ressources (32 bits) mais pour lesquels les cofits (produit, développement, consomma- tion) doivent rester réduits La premiére vision d’ensemble (fig.1.1, p.9) du Cortex MB, telle que l'on peut la trouver dans la documentation technique de ce produit, est un diagramme fonction- nel, simple dans sa représentation mais dont chaque bloc peut laisser bien perplexe le néophyte. lg Pros by AM Sans en connaitre tous les détails et toutes les subtilités, il est utile d’avoir une idée des grandes fonctions assurées par les différents blocs de cette architecture, Les unités exécutives * CMSCORE : Il s’agit bien évidement du coeur en lui-méme. Dans cette unité on trouvera les différents registres, tous les mécanisme de lecture/écriture des instruc- tions et des données ainsi que l’unité arithmétique et logique (UAL) pour Pexécu- tion & proprement dite des différentes instructions. Une explication détaillée sur fonctionnement de ce bloc est objet du prochain chepitre et la compréhension de son mécanisme est nécessaire a l’écriture de programme en langage d’assemblage. * Nested Vectored Interrupt Controller (NVIC) : Le Cortex est prévu pour @tre immergé dans un microcontréleur qui va inclure des unités périphériques per- mettant P'interfacage avec le monde extérieur. Ces unités peuvent étre vues comme 9 des micro-machines indépendantes. Les échanges entre ces unités et le Cortex M3 deivent. alors étre rythmés et organisés de telle sorte que l'ordonnancement des t€ches & accomplir réponde a des régles (notion de priorités) et a un déterminisme imposés a l'avance par le programmeur. Le NVIC joue ce réle de "chef d’orchestre’. Ila pour charge de réceptionner, de trier et de diffuser les différentes interruptions engendrées par l'ensemble des unités du microcontréleur. Il gere également les évé- nements qui mettent en péril le bon déroulement de la séquenee de code en cours d'exécution (reset, probléme de bus mémoire, division par 0,..etc.) * Memory Protection Unit (MPU) : Ce bloc est optionnel, c'est a dire que le fondeur qui va utiliser le Cortex M3 pour concevoir son 1C, peut choisir de ne pas implémenter cette fonctionnalité. Ce bloc permet d’attribuer & des zones spéci- ficues de la mémoire, des droits d’accts en lecture et /ou éeriture spécifiques. Ainsi dans le cas oi différentes taches logicielles indépendantes s’exécutent en paralléle (ou plus précisément en se partageant la resource commune qu’est le processeur), il est possible d’attribuer, A chacune d’entre elles, une zone mémoire inaccessible pour les autres taches. Ce mécanisme permet done de sécuriser les accés mémoite Il va de pair généralement avec l'utilisation d’un systéme d’exploitation (temas réel ou non) pour la couche logicielle. * Le Bus Matrix : Cette unité est une sorte de gigantesque multiplexeur intelligert. TL permet les connections sur les bus externes Le bus ICode : Bus (32 bits de type d’AHB-Lite? ) qui véhicule les adressages des espace mémoire allouées au code ainsi que les instructions. +» Le bus DCode : Bus (également 32 bits de type d’AHB-Lite) en charge de la gestion des lectures/écritures en zones mémoire données. » Le bus System (toujours 32 bits de type d’AHB-Lite) concerne tous les accés & Vespace systéme. » Le bus PPB pour Private Peripheral Bus. Tous les périphériques contenus dans le micro-contréleur viennent s’ajouter & Parchitecture du Cortex. ARM a prévu un bus spécifique pour permettre les échanges avec les périphériques. Ce ‘us est 32 bits mais est, cette fois, de type APB (Advanced Peripheral Bus) ce qui correspond un autre protocole de bus (dont on peut juste retenir qu'il est moins performant qu’un type AHB mais que cela suflit amplement pour 'acc’s aux unités périphériques) Test & noter que le bus matrix joue un réle non négligeable pour transmettre les informations utiles aux unités de mise au point présentées dans la section suivante. Les unités de mise au point La mis au point des programmes est une étape importante et particulitrement chronophage dans le cycle de développement d’une application embarquée. En outre, s'il existe des impératifs de certification pour le projet, il est nécessaire d’avoir a sa dis- position des outils (logiciels et/ou matériels) qui permettent de surveiller le maximum d’événements occurrents dans un cycle dhorloge. Pour le Cortex M3, les différentes 3. Advanced Microcontroller Bus (AHB) est. un protocole de bus déposé par ARM. 10 unités qui sont présentées briévement ci-dessous correspondent A ces fonctions de sur- veillance. Elles sont directement implantées dans le silicium du circuit ce qui permet de disposer de ces outils de mise au point par un accés strictement matériel. Une couche logicielle extérieure sera. cependant nécessaire pour récupérer et traiter les informations issues de ces unités. L’idée générique qui sous-tend introduction de telles solutions ma- térielles est d/offrir au programmeur la possibilité de tester, fiabiliser (voire certifier) son code sans jamais introduire la moindre modification dans celui-ci. I est en effet commode (ct usuel) d’insérer au milieu d’une structure logicielle queleonque une printf("Coucou je suis passé par la ') pour étre stir que V'exécution passe dans cette structure. Ce fai- sant, on introduit une modification de code, qui pent modifier le comportement global du programme. Ceci est particulidrement vrai lorsque la gestion de temps est critique pour le systéme, ce qui, pour les systémes embarqués contrdlés par microcontréleur, est presque toujours le cas. © Flash Patch and Breakpoint (FPB) : Le FPB est la fonction la plus basique pour cela, Elle est liée A la notion de point d’arrét (breakpoint) qui impose & stopper sur une ligne de code (cad une instruction dans le cas du langage d’assem- blage) préalablement repérée. Cette unité permet de marquer des instructions de telle sorte que lorsqu’elles arrivent & exécution, le processeur se mettent dans un mode de fonctionnement particulier : le mode debug. Le logiciel de développement, (ct celui qui le pilote...) a alors la possibilité d’observer l'état du processeur et éventuellement d’influer directement sur le déroulement du programme en cours. « Data Watchpoint and Trace (DWT) : La notion de "point d’observation" est le pendant de la notion de point d’arrét pour les données. Il s’agit en effet de stopper le déroulement non pas sur une instruction repérées mais lorsque que le programme agit sur la donnée marquée. Cette action peut étre en lecture, en écriture, sur dépassement de valeurs.....cte. L’unité permet également denvoyer des requétes pour les unités ITM et ETM. © Embedded Trace Macrocell (ETM) : La notion de trace recouvre la ca- pacité pour le matériel A enregistrer une suite d’événement lors de Vexécution du programme. La récupération de ces enregistrements permet d’analyser le bon (ou moins bon..) déroulement de V'exécution. Dans le cas de ETM, seules des infor- mations sur les instructions sont stockées dans une structure de type FIFO. Cette unité, a instar de lunité MPU, est optionnelle. + Instrumentation Trace Macrocell (ITM) : Cette unité permet également dengendrer des informations de type trace sur des requétes (logicielles, matérielles ou temporelles). Les informations sont plus limitées que pour l’unité ETM mais peuvent cependant @tre grandement utile pour loger un bug viscieur. Cela est d’autant plus vrai si 'unité optionnelle ETM n’est pas présente. * Advanced High-performance Bus Access Port (AHB -AP) : Il s’agit ici @un port (Entrée/Sortie) & Vintérieur du Cortex-M3 & visée de debug. I permet Pacc’s & tous les registres et A Yensemble de espace adressable de la mémoii Il est prioritaire dans les politiques d’arbitrage du bus matrix. Cette unité est connectée en amont par le port Serial Wire JIAG (SW / JTAG) qui est I'inter- face (avec ses couches physiques) réalisant la connexion avec le monde extérieur u a at rE se’ "2 8S FIGURE 1.2 ~ Famille des produits STM32 (équipée de son coté d’une sonde JTAG. Le protocole JTAG est un protocole standardisé utilisé par la quasi totalité des fabriquants de semi-conducteur. * Trace Port Interface Unit (TPUI) : Le TPUI joue le méme rdle pour les fonction Trace que le SW / JTAG pour les fonction debug. Son existence est. prin- cipelement lié au fait qu’il faille bien sortir les enregistrements de 'TTM vers le monde extérieur. Il a cependant une difficulté supplémentaire lorsqu’un unité ETM existe puisqu’il doit également gérer les informations qui y sont stockées. Son se- cond réle est done de fusionner et de formater ce double flux de données afin de les sransmettre sur le port. Coté monde extérieur, il sera nécessaire d’utiliser un Trace Port Analyzer (TPA) pour récupérer ces données. 1.2.2 Le coeur Cortex M3 dans le STM32 ‘Vous disposerez en Travaux Pratiques de cartes d’étude équi- oLy pées du contréleur STM32 de la société STMicro. Pour étre a vraiment précis il s'agit du STM32F103RB En effet, le microcontrdleur STM32, comme toute bonne famille de uC, se dé sous un grand nombre de version (fig.1.2, p.12). line Fonctionnalités Le choix de la bonne version du microcontréleur peut étre une étape décisive dans la phase de conception d’un projet : en fonction des besoins (en terme de fonctions, 12 du nombre d’B/S,...), mais aussi des contraintes propres (colt, consommation, dimen- sion,...) chacune des versions du processeur sera plus ou moins bien adaptées. LA encore, le but du présent document n'est pas de rentrer dans les détails du fonctionnement des aspects périphérique du micro controleur. Il est cependant utile d’avoir un vision d’en- semble du circuit que vous allez programmer pour ne pas étre surpris par des choses aussi basiques que l'adressage mémoire D’un point de vue fonctionnel, la figure (fig.1.3, p.14) visualise comment STmicro a "habillé" le Cortex pour fabriquer son STM32F103RB. Un premiére remarque impor- tante est que la totalité des fonctionnalités proposées par ce microcontrdleur ne sont pas forcément simultanément disponibles. Les broches de sortie sont généralement par- tagées par plusieurs unités. Ainsi, selon la configuration que le programmeur aura impo- sée, certaines fonctions deviendront de facto indisponibles pour l’application. Seule une connaissance approfondie d’une version donnée du processeur peut permettre de savoir si, a priori, la version choisie peut suffire aux besoins de l'application & développer. Le question du choix de la bonne version est done loin d’étre triviale. Le processeur sur Iequel vous allez travailler posséde : © Un étage d’alimentation airsi que des circuits d’horloge (en violet). On y devine la possibilité de mise en mode 'sornmeil’ du processeur ainsi que l'accés a différentes fréquences (ce qui s'avére intéressant pour le gestion de timer notamment) © L’ajout de mémoire de type Flash et de type RAM (en orange). La quantité de mémoire présent dans le boitier est une des variables qui fluctue le plus selon la version du microcontréleur que l'on choisit. Dans notre cas, pour fixer une ordre de grandeur, 128KB de code vont représenter environ 65000 lignes de code (une instruction codée sur 16 bits)... © Des gestionnaires évolués du temps systéme (en bleu foncé), Avec notamment un timer 24 bits "proche da coeur’ et une unité de réveil automatique lorsque. le processeur est tombé en mode 'sommeil". Ces unités ont une portée importante lors de Vutilisation de noyau temps réel. © Des périphériques de gestion du temps et/ou de comptage (en rose). © Des périphériques de gestion de signaux analogiques (en marron). Il s’agit ici soit de convertisseurs analogiques/numériques pour Pacquisition de grandeurs analo- giques, soit de gestionnaire PWM pour l’envoie de signaux assimilables & des gran- deurs analogiques. De périphériques de signaux tout ou rien (en bleu clair). Ces 51 GPIO (General Purpose Input Output ) sont des ports d’entrée/sortie TTL et les 16 autres si- gnaux concernent des entrées tout ou rien pour déclencher des interruptions. Des périphériques de communications. Les différents protocoles actuels sont pré- sents dans ce boitier. Que ce soit pour des communications série (USART, USB) ou des bus industriels (I2C, CAN, SPI). Espace mémoire La gestion de l'espace mémoire est certainement l’aspect le plus compliqué que doit gérer celui qui développe un programme en langage d’assemblage. Fort heureusement, un certain nombre de divaciives d’ assemblage assoc aun ¢ puissant vont 13 Ficure 1.3 ~ Description fonctionnelle du STM32F103RB rendre quasi transparente cette gestion. Il n'est: cependant pas inutile d’avoir une idée claire des répartitions mémoire afin de travailler en toute connaissance de cause lors de la mise au point du programme. En effet, les registres du processeur contiennent réguligrement des quantités qui correspondent & des adresses. Lorsque le programme n’a. pas le comportement souhaité (un méchant bug, en clair!), il s’avére judicieux de savoir si ces quantités sont bien celles que l’on pouvait espérer. Le Cortex posséde un espace mémoire de 4Go adresses consécutives (bus de 32 bits) Une adresse mémoire correspond A un octet. Il en découle qu’un 1/2 mot (16 bits) oceupe 2 adresses et le mot (32 bits) occupent 4 adresses mémoires. Par convention, le stockage des données se fait selon la norme (GENS) II est A noter qu’ARM laisse le choix eu fondeur d’opter (par le biais d’une entrée spécifique) entre un adressage little endian (par défaut) oa a fa figure (fig.1.4, p.15) montre comment se font les placements mémoire d'un mot et d’un 1/2 mot, a savoir que les poids forts d’une valeur stockée sur plusieurs octets sont rangés sur les adresses les plus hautes. Liarchitecture est de type Harvard, cela induit un découpage séparé de Pacets au code de celui des données. La figure (fig.1.5, p.15) montre comment ce découpage est prévu. Les autres zones (peripheral, external...) imposent le placement sur lespace adressage des différentes unités présentées figure (fig.1.3, p.14) Une particularité est & relever concernant l'accts en mémoire. Ils'agit du oi bacciag, Cette technique existe & la fois dans la zone SRAM (entre les adresses 0X2000 0000 et 0X2000 FFFF pour la bit-band region) et les adresses 0X2200 0000 et OX23FF FFFF 4 Quads nen te an ye re nee aglon . Dogua fao hg ina ze sc] £3] Fo] oa] KS - sts OxACERPHOA Oe 4¢|e3 rarer Bjew 70/28 Fafer —1yzmats 0x70 a vale Ficune 14 SRA Figure 1.5 ~ Mapping mémoire du Cortex M3 pour l’alias) que dans la zone Peripheral (entre les adresses (RAUONUO0DICNONKO00> =: la bit-band region) et: les adresses 0X4200 0000 et OX43FF FFFF pour fias. Ces 4 zones sont schématisées par des hachures dans la figure du mapping mé- moire (fig.1.5, p.15). Cette technique permet d’affecter directement (set ou reset) des bits situés A des adresses des zones bit-banding, Quel est le probléme? Si on veut modifier un bit dans une zone mémoire, sans cette particularité, il faudrait, dans la mesure oi architecture ne peut pas directement agir sur ces bits en mémoire 1. Récupérer le mot en mémoire 2. Modifier le bit (par application masque par exemple) 3. Récrire le mot en mémoire ARM a concu de faire correspondre l’adresse d’un mot (en zone alias) avec un bit (en zone bit-banding). Ainsi lorsque le programmeur écrit une valeur dans la zone, cela revient & affecter le bit bit-banding correspondant avec le bit de poids 0 qu’il vient d’écrire. Il est A noter que cette technique n'est pas consommatrice de mémoire RAM dans le mesure oi les zones alias sont fictives : elles ne correspondent pas physiquement & des emplacements mémoire. Elles sont simplement consommatrices d’adresses mémoire, mais avec 4Go d’adresses possibles, cette perte est fort peu conséquente. pl kel ($1042). 16 Chapitre 2 Le Coeurtex M3 2.1 Introduction Le chapitre précédent a montré, d’un point de vue fonctionnel, comment pouvaient se décomposer les différentes unités présentes dans un microcontréleur comme le STM32 Is’agit maintenant de s’enfoncer un peu plus au coeur du Cortex M3, et de détailler le contenu de la boite CM3CORE de la figure (fig-1.1, p.9) Il serait cependant vain de vouloir faire une redite, incomplete parce que simplifiée, du contenu des différents manuels de référence [3], [2], [1] qui expliquent dans le détail Je fonctionnement du Cortex. Mais il serait encore plus vain de prétendre a faire de la programmation en langage d’assemblage sans avoir une idée assez. précise de la structure de celui-ci. Ce chapitre tente done de présenter les aspects de architecture nécessaire & une programmation raisonnée du microcontréleur. 2.2 Modes, priviléges et états Le Cortex M3 peut étre positionné dans 2 modes opératoires différents : le ‘T's te et Je ‘andier mode, Ces modes se combinent avec le niveau de privilege qui peut tre aceorder A 'exécution d’un programme, © Bn niveau Unpeiviicwc, le eode exécuté n'a pas acc’s & la totalité des instruc- tions (scules quelques instructions particuliéres d’accés & des registres spéciaux sont exclues). Il n'a pas accés de facon général A tout ce qui reléve du systéme (WIC,timer system,...). Ce niveau de protection peut paraitre peu sécurisant dans la mesure ot le programme peut (en changeant un bit dans le registre Control) sortir par lui méme de cette protection. L'intérét est cependant cer- tains : il s’agit simplement ’éviter d’avoir un code qui, par un mauvaise gestion d'un pointeur par exemple, vienne détériorer le comportement global du proces- seur et perturber gravement le déroulement de application. C’est un peu comme le vérouillage/dévérouillage de votre téléphone portable : il faut une combinaison de touche (connue de tous) pour le réaliser. I] n’a done évidement aucun réle pour empécher le vol, mais cette fonction est néanmoins trés utile lorsque le téléphone est au fond de la poche d’un jeans. qv A Vinverse, en mode |riyilegor!, toutes ces imitations tombent. © Le mode Thread est en quelque sorte le mode par défaut dans le mesure ot c'est Je mode dans lequel se trouve le processeur aprés un reset. C'est le mode normal lors de Pexécution de Papplicatif. Pour ce mode, les 2 niveaux de privilége sont possibles. © Le processeur entre en mode Handler suite & une exception. Lorsqu’il a fini dexé- cuter les instructions de traitement de cette exception, la derniére instruction permet de reprendre le cours normal de lexécution et provoque le retour en mode Thread. Dans ce mode le code est toujours Privileged. Un second élément est & prendre en compte pour comprendre de fonctionnement du Cortex M3. I s'agit: de l'état interne du processeur qui peut étre soit en Fest st soit en Stave. Le terme Thumb fait référence au jeu d’instructions du processeur (cf. chapitre 5) L¥état_ associé correspond done au déroulement normal? de lexécution. L’état Debug, résulte d’un passage en mode de mise au point. La cadence d’exécution du programme ne répond plus au mémes régles (point d’arrét, point d’observation,...) il est donc compréhensible que cela se traduise par un état particulier. Comme pour tout événement dans les mécanismes internes d’un processeur, le passage d’un état & un autre se traduit (¢t/ou se provoque) par le basculement de la valeur d’un ou plusieurs bits. Dans ce cas il s'agit de 2 bits (C_DEBUGEN et C_HALT) localisés dans le registre DHCSR (Debug Halting Control and Status Register). Afin de ressuzer le lectewe : la maitrise de ces différentes options de fonction- nement n’est pas un préalable pour Vécriture de ses premiers programmes en langage assemblage. Les maigres explications qui précédent ne sont li que pour faire prendre conscience des capacités du processeur. Il s’agit aussi pour l'utilisateur de comprendre que observation de Vexéeution de son programme en "pas a pas" ne reléve pas de la ma- gie noire mais de Verploitation par le logiciel de développement de ressources spécifiques du processeur. 2.3 Les registres La premigre vue que l’on peut avoir d’un processeur, est de regarder quelles sont les registres qui le compose. Il s’agit sans aucun doute de Vapproche la plus pragmatique dans la mesure o} les architectures modemes, comme celle du Cortex M3, sont dites de type load-store. Cela signifie que les programmes transférent initialement les données de la mémoire vers des registres et effectuent dans un second temps les opérations sur ces registres, Enfin et lorsque cela est nécessaire, il y a transfert du résultat vers mémoire centrale. Définissons tout d’abord ce qu’est un registre. Un registre, dans son acception initiale, 1. A la lecture de ces quelques paragraphes, on doit comprendre que dans sa vie normale de proces- seur, le Cortex M3 devrait en état Thumb, en mode Thread et en niveau Unpriviliged. 18 correspond & 11n emplacement de mémoire interne (au sens de série de bits accessibles en paralléle) & un processeur. Cependant il convient de moduler cette définition pour la simple raison que, dans le cas d’un microcontréleur, il y a toujours de la mémoire interne (20KB de static RAM pour le cas du STM32 et cela est sans considérer la mémoire de type FLASH), l'ensemble de cette mémoire interne ne const:tue pour autant pas autant de registres. Une définition tout aussi inexacte serait de penser qu'un registre est un emplacement mémoire qui ne fait pas partie du mapping mémoire. En effet, ensemble des périphériques se programme par le biais de valeurs que 'on donne & des registres, il n’en posséde pas moins des adresses physiques auquel le processeur accéde comme & tout autre espace mémoire. ‘Liutilisation extensive du terme registre en architecture des ordinateurs peut laisser présager que ce terme englobe de fagon assez vague ensemble des espaces mémoires dont le contenu affecte directement: la fonctionnement du processeur. Nous ne considérerons dans cette partie que les registres du coeur du Cortex M3. Leur grande particularité est qu’ils sont accessibles par le jeu d’instructions sans avoir & engendrer de requéte sur le bus données. L’opecs's (qui correspond au codage de instruction A exécuter) d’une instruction manipulant le contenu d’un registre doit done contenir l'information du registre atteindre. L’exécution dane instruction peut amener la modification @’un ou de plusieurs de ces registres sans récessité non plus d’activité sur le bus de données, Le Cortex M3 posséde 17 registres, tous évidement 32 bits : © AOA #12: 13 registres & usage général R48 SP 79: registre poinvour ©, qui se dénomme également SP, PSP (SP_process) stern ou MSP (SP_main) eis © Rig : registre de lien LR (Link register) © #18: compteur ordinal ou PC (progranm pointer) © uPSR : un registre d’états (Programm Status Register, le x pouvant éire A pour Application, I pour Interrupt ou E pour Exécution) qui étrangement nest jamais appelé R16 (un vieux contentieux avec Renault parait il...) A ces 17 registres il convient d’en adjoindre 3 spéciaux (PRIMASK, FAULTMASK et BASEPRI) qui sont des registres servant a la gestion des exceptions (cf. chapitre 27 Le vingt-et-uniéme que l’on peut ajouter cette liste est le registre CONTROL qui a déjA 6 Evoqué pour son rdle dans le niveau de privilége mais qui agit également au niveau du pointeur de pile R13 2.3.1 Les registres RO & R12 Ces 13 registres servent, comme on le verra lors du passage en revue du jeu d’ins- tructions, de conteneur pour stocker les 996" dune instruction et pour rece- voir les résultats des ces opérations. ARM distingue les 8 premiers registres RO-RT (Low registers) des 4 suivants R&8-R12 (High registers). En effet, les registres R8 A R12 possédent des restrictions d'emploi par rapport A ce-taines instructions. Le pro- grammeur prudent utilisera en priorité les 8 premiers registres pour ne pas A avoir & gérer ces restrictions. 19 88 01 clon: Ces registres dite générauc, contrairement a d'autres architectures, ne sont accessibles que par paquet de 32 bits. Les registres ne sont donc pas scindables en 1/2 mots ou en 4 octets. Si votre application traite, par exemple, des octets (une chaine de caractéres pour étre encore plus précis), les 24 bits de poids fort devront étre a 0 pour que votre opération soit sensée. 2.3.2 Le registre R13 aliasSP R13 est le registre pointeur de pile. Comme son nom Vindique il pointe (cad qu’il contient l'adresse d’n emplacement mémoire) qui correspond & l’emplacement courant, dela pite ay Cette notion de pile sera développé plus tard (paragraphe 6.5.6), on peut juste l’envisager dans un premier temps comme une zone tampon oit le programme en cours d’exécution peut stocker temporairement des données. Dans le cas du Cortex M8 cette zone de stockage est double et par conséquence le registre SP se décline en 2 versions PSP (SP_Process) ou MSP (SP_Main). Attention A un instant: donné seule une des 2 piles est visible par le processeur. Ainsi lors de ’écriture sur la pile comme dans Vexemple suivant push RIé —; Sauvogarde de PO | MSP or PSP??? Exemple 2 : Sauvegarde d’un registre iture se fait sur la zone visible. Pour ce qui est de cette visibilité, on peut rete- nir qu’en mode Handler le pointeur courant est toujours MSP. Pour le mode Thread, méme si cels peut étre modifié logiciellement, le pointeur courant est PSP. Ainsi, sauf manipulation particuliére, les acc’s & la pile systéme se feront via SP_Process lors du déroulement habituel du programme mais lorsque survient une exception la gestion de la pile est assujettie 8 SP_main. Ce découpage induit une plus grande stireté dans le fonctionnement du microcontréleur et plus de rapidité lors d’un changement de contexte (il ne faut pas oublier que les périphériques communiquent avec le Cortex par le biais interrupticns et done qu’en soi une exception n’est pas exceptionnelle...). 2.3.3 Le registre R14 alias LR A travers ce registre, se devine la structuration d’un programme qui sera abordée chapitre 7. Découvrons, & travers le petit exemple suivant, un des mécanismes de base le saut & un sous-programme. Fraurr 2.1 Double pile syst8me | Main PROC Ie BL MaPirst ; Appel &la routine ENDP MaFirst PROG NOP +} No operation BX LR } Retour au programme appelant ENDP Exemple 3 : Utilité du regisire LR Dans cet exemple, le programmeur a écrit 2 procédures (c'est le terme consacré pour la notion de sous programme) : Main et MaFirst. Le procédure Main ne fait rien d’autre qu'un appel & MaFirst qui elle-méme ne fait rion (I'instruction NOP n’a aucun autre effet que utiliser un cycle machine pour s’exéeuter). Lorsque le processeur arrive sur Vinstruction BL (Branch with Link), il stocke dans le registre LR adresse suivante ol il se trouve puis il affecte le pointeur d'instruction avec adresse de la routine. De fagon symétrique, dans la routine MaFirst Pinstruction BX (Branch and Exchange), il va changer le contenu de LR avec la valenr contenue dans le pointeur @’instruction et ainsi retourner dot il vient pour continuer Ie traitement, de la procédure appelante. 2.3.4 Le registro R15 aliasRO} ~ addy ot'ye tiouse prochne execution On Yappelle fe CracraR CEERI’ pointeur d’instructions ou le compteur ordi- nal, mais son role est unique : contenir Vadresse mémoire of se trouve la prochi wie Le bit de poids 0 de ce registre est: toujours & 0 étant ag a ret Moin Main peeps oak ois ltarirst “Avani Pappel “Apres Fappel ‘Avant fo retour ‘Aorés le retour FicuRE 2.2 Appel A un sous programme via le rogistre LR que les instructions sont codées sur 16 bits (Thumb) ou 32 bits (Thumb$_28), elles oc cupent done au moins 2 adresses consécutives. Lors du déroulement d’une séquence de code, le pointeur PC va automatiquement s‘incrémenter (en général de 2 en 2) pour aller pointer la suite du code. Le terme compteur ordinal pourrait laisser penser que son fonctionnement se limite cette incrémentation simple. I] n’en est rien et les choses se compliquent rapidement, notamment lorsque qu'il y @ un rupture de séquence (a l'instar de l'exemple précédent oii l'appel 4 un sous-programme, induit une discontinuité dans la suite des adresses de stockage du code). PC dans ce cas va prendre une valeur qui nest pas une simple incrémentation de sa valeur initiale. La gestion de ce pointeur est intrinséquement liée & la structure (IENUEEIEMRle cette architecture RISC, Cette technique permet d’introduire une forme de perallélisme dans le travail du processeur. A chaque instant, plusieurs instructions sont traitées simulta nément, chacune 4 un niveau différents. ‘Trois étapes successives sont nécessaires pour qwune instruction soit completement effectuée : » La phase Fetch : récupération de l’instruction en mémoire. C'est A cette étape que PG joue tout son réle. La phase Decode : l'instruction est une valeur codée en mémoire (son opcode) qui nécessite un décodage pour préparer I’exécution (récupération de données par exemple). * La phase Execute : exécution de l'instruction décodée et écriture des résultats si nécessaire. A cette 3 étages (classique pour un pipe-Line) se rajoute un premiére unité en amont : Vunité de PreFetch. Cotte unité (qui fait partie des savoir-faire d’ARM) consiste essen- tiellement & prédire ce qui peut se passer lors des ruptures de séquences et 4 préparer Ja récupération d’instruction suivante en 'bufferisant” jusqu’a 6 instructions 4 l’avance. 22 Cette pratique permet d’optimiser la rapidité du processeur. Cette vision simplifiée des étages d’un pipéeiSH6 masque volontairement la com- plexité de la chose. LA aussi, par rapport aux objectifs de ce document, ce niveau de compréhension suffit pour écrire des programmes en langage d’assemblage et le lecteur avide de connaissances pourra aller piocher dans la documentation ARM, toutes les ex- plications nécessaires pour aller plus loin. 2.3.5 Le registre @PSR) (A) Ce registre contient une information de type "SME ou (MFRE"|dusprocessetr. 1 contient des informations importantes, sorte de compte rendu, sur ce qui vient de se passer dans le processeur. Il se décline en trois versions)bien qu’il ne s’agisse que d’un soul registre. La répartition des bits significatifs comme le montre la figure (fig.2.3, p.24) est telle qu'il n'y a pas d’interseetion et done qu'il est possible de le séparer en 3 sous ensemble cohérent, © ASR . avec A pour ppliaation): ce registre contient le fanions du processeur. Ces 5 bits sont essentiels pour l'utilisation d’opérations conditionnées puisque les conditions s'expriment exclusivement comme une combinaison logique de fae fa nions. La mise & jour des ceuxcci est faite parle plupart des instructions, A]@OHet ion Guelarsuitixe S soit précise a miotique de Pinstraetion? représente la retenue lors du calcul sur les grandeurs ). $C = 1, alors il y a eu un débordement de la re- présentation non signée lors de instruction précédente , ce qui signifie que le résultat non signé est particllement faux. La connaissance de ce bit permet de travailler en précision multiple. * aut 1 si le résultat est nul. * recopie le bit de poids fort du résultat. Sila valeur est ie done un résultat négatif. * vaut 1 s'il y a eu débordement de la représentation signée. Le résultat signé est faux. ( Sticky saturation flag) : n'a de sens que pour 2 instrue- tions spécifiques de saturation USAT et SSAT : le bit est positionné & 1 si ces ingtructions ont saturé la variable traitée. - avec I pot dans cette configuration, ce sont les 9 bits de poids faibles qui contiennent I information. Ces 9 bits composent le muméro de l'ex- ception (Interrupt Service Routine) qui vient d’étre déclenchée. Par exemple, Jorsque ISR vaut 2, cela correspond au déclenchement d'une interruption HMI (Non Maskable interrupt), s'il vaut 5 qu'll y a eu une probléme sur les accés mémoire,... TEPSRM avec E pour SSee + ee Tegistre mémorise 3 informations distinctes = Le bil 24 (1) pour indiquer s'il est en Thunb State c'est A dire qu'il utilise le jeu d’instruction appelé Thunb. comme c’est toujours le cas ce bit est toujours & 1 (ca cst de l'info!). « Il utilise les champs de bits [10-15] et [25-26] pour stocker 2 informations qui se superposent (il y a exclusicn mutuelle entre les 2 utilisations) ICL ow IT. 23. * Pour ICT, ils’agit d'une information qui est stockée lorsque qu’une lecture /écriture multiple (le processeur lit/éerit, en rafale et avec une seule instruction plusieurs registre généraux) est interrompue. Au retour de interruption le processeur peut reprendre ses accés multiples la oi il en était, + Pour If, il existe dans le jeu d’instructions une instruction particuliére de type I£/Then?. Les bits IT lors de Vexéeution de cette instructions vont conteniz le nombre d'instructions qui seront incluses dans un bloc If/Then ainsi qu’un codage des conditions de leur exécution. Le registre EPSR a donc une utilité toute relative pour le programmeur. Quand on sait de surcroft qu'il n’est pas modifiable, on peut se permettre d’en oublier existence pour développer son code FIGURE 2.3 ~ Le registre xPSR. Dun point de vue langage d’assemblage, exemple suivant montre qu’il est possible daccéder séparément aux trois entités ou d’aceéder & ensemble. Il est & noter que cette lecture se fait pas le biais de instruction spécifique MRS. | Recup (MSR arse FSi part APSAGans RID | eae Teepeeertey scores : f mmpet PSR dane 35 {J Exemple 4 : Récupération du registre d'état 2, Cette instruction particuliére n'est pas le seul moyen, heureusement, d’éerire us. Si..Sinon..Alors en langage «assemblage. Une approche, plus systématique, par saut conditionné permet de mettre en place toute sorte de structures algorithmiques (cf 6.1) 24 Chapitre 3 Du bon usage des directives 3.1 Introduction ‘Comme pour tout langage, l'aspect. syntaxique d’un listing revét une importance cruciale pour que le compilateur (dans le cas des langages structurés de haut niveati) ou Vassemblour (pour les listing écrit: en langage d’assemblage) comprennent la suite de caractéres qu’ils vont lire et qui compose le programme. Si Yon considare les exemples précédents, un assembleur serait bien en peine de générer le code exécutable correspondant : il lui manquerait toute une foule d'informa- ions. Seules quelques instructions, isolées de tout contexte, ont été transcrites dans ces cexemples. Oi est le point d’entré du le code, ot le programme s'acheve til, od est placé le code en mémoire, comment s’appellent les constantes ou les variables, ....? Cette partie a pour but de définir ce contexte & travers la description des directives a’ assenblage est une! wui apparait textuellement dans le listing et qui sert A assembleur po Cos lignes de programme, Dien que partie intégrante du listing et nécessaire & sa cohérence, ne correspondront, directement & aucune ligne de code. C'est ce qui manguera le plus, au déplombeur de programme qui s’adonnera au plaisir du désassemblage. Cette opération consiste a convertir le code (c'est & dire la suite des mots lus en mémoire) en mnémonique + opérande numérique. Le codage d’une instruction étant biunivoque. il n'y a pas de pro- bléme particulier pour retranserire en langage d’assemblage primitif un code extrait de la mémoire. Ce faisant toute la couche symbolique sera perdue et la compréhension de ce qui est programmé sera bien obscur! A titre d’exemple le désassemblage du code de Fexemple Ex.??, ?? donne les quelques lignes suivantes : Ox080001A0 BL.W x0so001 As x08000144 B ——x080001A4 008000146 08000148 “NOP Qx080001A BX Ir jer Exemple 5 ; Désasemblage 28 3.1.1 Conventions lypographiques et utilisation de symboles Dans ce qui suit les conventions typographiques suivantes ont éé adoptées + « Les italiques maigres dénotent une séquence de caractires que vous devez choi © Les mots écrits en MAJUSCULES sont obligatoires. On les montre ici en majus- cules pour les mettre en évidence, mais ils peuvent aussi étre indifféremment écrits en minuscues! © Les italiques grasses indiquent un champ dont la valeur est & choisir dans une liste imposée. + Les champs qui ne sont pas éerits entre accolades { } sont obligatoires. Les autres ‘champs sont optionnels, mais on n’écrit jamais les accolades. Pour écrire vos programmes, vous allez tre amené & définir des symboles (une constante, une étiquette pour repérer une ligne de code, une variable,...). On peut employer égale- ment le terme didentifieateur pour ces noms définis pas Vutilisateur, Un symbole sera toujours associé & une valeur numérique par Vassembleur et le linker : au méme titre que les directives définies ci-dessus, un symbole ne sera jamais explicitemont inclus dans le code final. La lisibilité, par essence trés faible en langage d’assemblage, de vos pro- grammes est done directement lige & la sémantique de vos symboles. I! convient done de ne pas étre avare en caractéres pour les rendre plus explicites. D’un point de vue syntaxique, un symbole doit, également. répondre aux régles suivantes pour étre admis par l'assembleur » Le nom d’un symbole doit étre unique dans un méme module » Les caractéres peuvent étre des lettres minuscules ou majuscules, des chiffres ou le underscore’. L’assembleur distingue la casse. A priori, il n'y a pas de longucurs maximales. Le premier caractére ne peut pas tre un chiffre. Les mots-clés (mnémoniques, directives,...) du langage sont évidement réservés. S'il savere nécessaire (pour mixer votre code avec un compilateur par exemple) utiliser une palette de caractdres plus importante, il est possible de le faire en encadirant, le symbole avec des | (qui ne feront pas partie du symbole) . Par exexuple |-tect| est un symbole valide et Vassembleur le mémorisera (dans sa table des symboles) comme .text. 3.2 Structure d’un programme Ecrire un programme en langage d’assemblage, sous sa forme la plus simple, implique que Vutilisateur puisse, dans un fichier source (qui est un fichier de texte), ® définir la séquence d’instructions du code, afin que Passembleur puisse les tra- duire en langage machine. Cette séquence, une fois assemblée, ot étant donnée la structure Harvard du Cortex M3, sera stockée en mémoire CODE. déclarer les données qu'il va utiliser, en leur attribuant, si nécessaire, une valeur initiale ou constante, afin que lassembleur puisse donner les ordres pour réserver la place nécessaire en mémoire, en Vinitialisant, le eas échéant, le tout étant prédestiné & remplir la mémoire DATA. 26 Au sujet de la pile systéme : Une troisiéme entité est cependant nécessaire au bon déroulement du programme : la pile systéme. Celle-ci n’est figée ni en taille ni en emplacement mémoire. Cela implique que, quelque part dans le listing, se trouve une réservation pour cet espace spécifique ct a minima une instruction pour Vinitialisation du pointeur (SP) en charge de sa gestion. Dans Vutilisation des outils de développement actuel, cette phase est souvent incluse dans wn fichier (écrit en langage d’assemblage) qui contient un certain nombre d’initialisations. Bn effet, le microcontréleur qui héberye le Corter M3 doit lui aussi subir quelques opérations de configuration juste aprés un reset, Vinitialisation de la pile dans ce fichier la n’est done pas aberrante. Le programmeur aguerri aura cependant & coeur Waller jeter son ail averti dans ce code, ne serait ce que pour vérifier que la taille prédéfinie de la pile systéme n'est ni sous-dimensionnée ni sur-dimensionnée. Mais il rentrera la dans un univers ou nul ne sort completement inderine, Vauteur vous aura prévenu! 3.2.1 Les sections AREA Un programme en langage d’assemblage doit avoir au moins deux parties, appelées ici section ot définies dans le listing par la directive AREA. © Une section de code contient la liste des instructions, « Une section de données oi se trouve la description des données (nom, taille, valeur initiale) Attention aux mélanges!: A inverse d'un langage de haut niveau ott la dé- claration des variables peut étre plus ou moins mélangée avec les actions, le langage Wassemblage exige une séparation nette. Du point de vue de assembleur une section est une zone contigué de la mémoire dont, tous les éléments sont de méme nature logique (instructions, données, pile systéme). Le programmeur dispose de la directive AREA qu’il communique & lassembleur pour lui signifier le début d’une section. Le section se termine naturellement avec Pouverture @une autre section Le corps de la section est constitué des instructions pour Is partie CODE ou de diverses réservations de place (initalisée ou pas) pour Ia section DATA. La syntaxe générale de définition d’une section, telle qu’on doit la construire dans un fichier source : Détaillons done les 3 champs © AREA : c'est Ia directive en elle-méme. * Nom_Section : nom que vous attribuez a la section on suivant les régles requises plus avant. © Une suite facultative d’options. Les principales options sont : 27 * code ou data : indique le type de section que on ouvre. * readonly ou readwrite : indique si la section est accessible en lecture seule (cas par défaut pour les sections CODE) ou en lecture écriture (cas par défaut pour les sections DATA). * noinit - indique, pour une section DATA, qu'elle est non initialisée ou initialisée 4.0. Ce genre de section ne peut contenir que des réservations brutes de mémoire ou des réservations de données initalisées A 0 * align = n avec n une valeur entre 0 et 31. Cette option indique comment: la section devra étre placée en mémoire. La section sera alignée sur une adresse modulo 2",ce qui on d’sutres termes, signifie que les n bits de poids faibles de la premitre adrosse de cotte section seront & 0 11 existe d’autres options qui, si elles ont besoin d’étre positionnées, montrent que vous avez abteint un niveau d’expertise qui dépasse les objectifs de ce document. Dans un programme, une méme section peut tre ouverte et, refermée plusieurs fois On peut également imaginer que Y’on souhaite ouvrir différentes et distinctes sections. ‘An final, toutes les diverses parties seront, combinées automatiquement. C’est le rale de Pédition de liens (linker) qui devra done prendre en compte les différentes contraintes afin d'attribuer les adresses mémoires de chaque section. 3.3 La section de code Une section de code contient des instructions sous forme symbolique. Une instruction est Gerite sur une ligne, selon la syntaxe suivante La syntaxe de tout langage d’assemblage est rigoureuse. On ne peut placer sur une ligne qu’une instruction tout au plus. Sont également. permises les lignes ne contenant qu'une étiquette, qu’un commentaire, ou méme rien du tout (pour aérer le listing, ce qui eat loin d’étre un luxe). Notons enfin qu'une étiquette doit obligatoirement étre placée en premiére colonne de la ligne. 3.3.1 Les étiquettes Une étiquette est un symbole de votre choix, construit toujours selon la méme régle, L'étiquette sert de repére, ¢’identification, & instruction (ou a la donnée). Elle permet, en cours d’exécution, d’aller 4 cotte instruction grace & un saut (ou branchement) Voici un exexple de morceau de programme, dun intérét algorithmique limité, mais, contenant une boucle et par conséquence une étiquette. Ce programme incrémente 4 chaque boucle le registre £2 avec une valeur contenue dans 4. Le nombre de oucles ffectnées est éga.ement caleulé par une incrémentation (unitaire dans ce cas) du registre RO. La boucle est effectuée tant qu'il n’y a pas dépassement de capacité (donc tant que Ie fanion C du registre «PSR resta a 0) 28 MOV R0,#0 —_ ; Initialisation du comptour MOV R3, #4; Valeur initiate MOV R4, #35; Incrément ‘Tournis ADD R0,#1 _; Incrtmentation du comptour de boucle ADDS R3,R4 — ; Incrémentation do la valour BOC Tournis _ ; Saut conditionné If Bink Exemple 6 ; Saut d une étiquette Le symbole # dénote un adressage immédiat, c’est dire qu'il précéde une constante a utiliser telle quelle (dans ce cas pour le chargement de registre). La derniére instruction (BCC) est un saut conditionnel. Le B signifie une demande de Branch et le suffixe CC signifie Clear Carry, et donc que le saut n’est réalisé par le processeur que si Popération précédente (addition avec affectation des fanions) ne provoque pas de dépassement et le basculement 8 1 du fanion C. Le point de rendez vous (Tournis) est Popérande qui suit et correspond & l’étiquette positionnée quelque lignes plus haut. Une version de saut sans condition existe & la derniére ligne de cet exemple. L’ins- truction saute 4 | *tiquette qui repére cette méme instruction...Cela ressemble fort & une boucle infinie.... Lorsque I’on place une étiquette sur une ligne vide, elle sert & repérer la premitre instruction (ou Ja_premiére donnée) suivante. Pour Vassembleur, 18S) étiqiiettes)SOtit) Gee Se valeur numérique d’une étiquette est_la valeur de Vadresse qu'elle représente, Cette étiquetie peut aussi bien étre l'adresse d'une mstTuC- tion que celle Pune donnée. Etiquettes ct constantes : Dans tous les langages d’assemblage, cette notion a été élargie : il est possible d’attribuer une valeur é une étiquette grévce a la directive BQU dont nous reparlerons au chapitre suivant. C'est |équivalent d’un #define en langage ©. L'étiquette prend alors la signification d'une grandeur numérique écrite sous forme symbolique qui n’est pas obligatoirement une adresse. 3.3.2. Mnémonique | Leh chl gain On appelle |) NURMle nom symbolique delVitSFUCERH! Ce nom est imposs et Vensemble des mnémoniques compose le jeu instructions. Dans le monde ARM, il existe dopuis la version d’architecture ARMV4, deux jeux d’ins- tructions distinetes : le jeu ARM (codé sur 32 bits) et le jeu Taunb (codé sur 16 bits). La taille pour codage du jeu Thumb étant moindre, ce jeu offre évidement. moins de possibi- lités que le jeu complet (par exemple seuls les sauts peuvent étre conditionnés alors que dans le jeu ARM la plupart des instructions arithmétiques peuvent V’étre). L'avantage tire de cette compression de code, est une plus grande compacité du code. Pour de nombreux processeurs ARN, il y a possibilité de les faire fonctionner en mode Thumb ot. en mode ARN, selon les besoins et les contraintes propres du projet. 29 Depuis V'architecture ARNV6, ARM a introduit une seconde subtilité qui consiste en introduction d'une version Taumb-2 pour le jeu «instructions, Dans cette seconde ver- sion de l'eppellation Thumb , le jeu If) bits est étendu avec quelques instructions 32 bits permettant d'allier performance et densité comme tendrait a le montrer la figure (fig.3.1, p.30)* FIGURE 3.1 ~ Performance et densité des différents jeux d’instructions Le Cortex M3 utilise exclusivement le je Thunb-2. Il lui est donc impossible de basculer en mode ARM (c'est ce qui explique que le bit T du registre BSPR (paragraphe 2.3.5) soit toujours positionné & 1 Le jeu Thumb-2 comprend) 114 tinémoniges diff@elme|(en excluant les instructions de communication avec un éventuel coprocesseur). Un classement repide permet de distinguer : » 8 pour les instructions de branchement 17 pour les instructior iques (addition, comparaison,...) 9 pour les déealages 9 pour les multiplications et divisions 2 pour les instructions de saturation 4 pour les instructions de changement de format (passage de 8 & 16 bits par exemple) © 10 pour des instructions arithmétiques particuligres © 2 pour la récupération du registre PSR © 24 pour les opérations locture/écriture unitaires en mémoire © 12 pour les opérations locture/écriture multiples en mémoire * 17 pour des instructions diverses (” WAIT, 7 daa) pel ty ~ Tout est simple +: Attention d ne pas se méprendre sur la complenité des opéra- tions. Ce sont toutes des opérations qui ne manipulent que des entiers (signés ow pas). Le néophyte ne devra done pas sétonner de ne pas trouver, avec de tels processeurs, dea capacités pour le traitement des nombres flottants par exemple. De méme pour tout ce qui reléve de la structuration algorithmique ou la gestion de structures de données avan- a 1. Ce schéma est extrait de documents commerciaux ARM, il est done & prendre comme tel 30 cées, il sera nécessaire de s’adapter au langage d’assemblage en décomposant la moindre opération. 3.3.3 Les opérandes | | }: Les instructions agissent sur et/ou avec les opérandes fournis. Une instruction peut, selon le cas, avoir de 0. 4opérandes, séparés par des virgules. Chaque opérande est écrit sous forme d'une expression Expr qu’évalue l’assembleur. Généralement, les instructions arithmétiques et logiques prennent 2 ou 3 opérandes. Le eas de 4 opérandes est relative- ment rare dans ce jeu d’instructions. Dans le eas du jen Thumb-2, hors les instructions de lecture/écriture, les opérandes sont; de deux types : les valeurs immédiates, ou les registres. Pour les instructions de type lecture/écrituro, un des opérandes sera obligatoi- rement une adresse mémoire. Différontes techniques existent pour spécifier ces adresses : les nocies d’adressage qui seront détaillés 4.3. Il faut copendant avoir a l'esprit que, en raison de architecture Load/Store du Cortex, cette adresse sera toujours stockée dans un registre. ‘Tout acc’s en mémoire nécessitera done au préalable la récupération dans un registre Padresse de la cible & atteindre. Amendons le programme précédent, pour que la valeur initisle corresponde au contenu un octet labellisé Octinit. Ajoutons-y, puisque cela est maintenant connu, la déclara- tion des sections. ; Section Donnees AREA MesDonnees, DATA, ALIGN=0 vctinit DOB ox124 |: Section Programme AREA MonCode, CODE, readonly, ALIGN=6 Procédure principale ain PROC EDR R6;=Octinit ; Chargement de Madresse MOV 0,0; Initialisation du compeeur LDRB RS, [R6] _; Chargemont de In valeur initio MOV R4, #35; Incrément Tournis ADD R0,#1 ; Incrémentation du complour de bovele ADDS R3,R4 ——_; Incrémentation do la valeur BCC Tounis Sant conditianaé mf Bint Exemple 7 : Opérande mémoire 3L }0x20000102 0x20000101 | 0x20000100 3 |ax200000FF | 20000209| y (zjecc00028 FIGUKE 3.2 ~ Utilisation d'un registre comme pointeur o£ |exz09000FE Sur cet exemple (voir également (fig.3.2, p.32)) , on voit que pour affecter RI avec la, valeur stockée a la case mémoire appelée octnit, il est nécessaire de passer par un registre supplémentaire (R6). Celui-ci récupére dans un premier temps (©) Padresse de cette variable (LDR R6,=Octinit, ) puis (®) selon un accés dit indirect, charge R9 avec la valeur mémorisée (LDRB R3, [R6]).Le regsitre 26, une fois initialis6, agit comme un. pointeur sur la zone mémoire & lire. On peut également remarquer au passage, que seul Yoctet de poids faible est recopié puisque instruction LDRB réalise le transfert d'un octet. Par contre c’est l'ensemble du registre R¥ qui est concerné par Vinstruction, les 24 bits de poids fort de ce registre sont done mis 0. Le contenu final du registre 32 dits 3 est bien équivalent au nombre non signé stocké sur un octt 2 octinit, Attention! : Il est important de noter que V’étiquette octinit n’est pas la donnée elle-méme. Elle n’est qu’un repére de la donnée - son adresse. 3.3.4 Commentairesssss, Un commentaire commence obligatoirement par; (SiiEViRENIG), inéme s'il est seul sur la ligne. I termine toujours avec la ligne. Si l'on veut écrire un commentaire tenant sur plusieurs lignes, chaque ligne doit commencer par; (point-virgule). Les caractéres accentués sont autorisés. Les commentaires peuvent étre placés n'importe of dans le programme, Pourvu qu iiteeSiiaiMOGHORMMMY 1 n'est pas vain do rappeler qu’un listing est plus souvent lu qu’écrit....méme par celui qui l’écrit! Le commentaire ost done salvateur lorsque vous avez & reprendre du code développé quelques semaines (mois, années,...) auparavant, n’en soyez donc pas avares! !! 32 3.3.5 Procédure Dans le langage d’assemblage présenté ici, toutes les instructions doivent obligatoire- ment étre écrites & l'intérieur d’une procédure. TI est done normal que la premiére ligne qui suit Pouverture d’ure section resemble & une ligne oti le mnémonique est remplacé par PROC comme dans Vexemple suivant : | AREA Nouvelie_Section, CODE, readonly, ALIGN-6 MaFonct PROC Corps de laprocédue (instructions) NDP l Exemple 8 : La déclaration de procédure On appelle procédure une séquence @’instructions. On pourra la distinguer d’un sous-programme (ou subroutine) lorsque la derniére instruction permet de retourner vers un programme appelant. Nous reviendrons (7.1)en détails sur la fagon d’écrire et @utiliser les procédure, regardons-en pour Vinstant que la partie émergée : I'appel & une procédure, La forme la plus générique pour l'sppel sera un branchement avec lien (BL Ma- fonction) et le retour correspondra & une ré-affectation du pointcur d’instruction par Vinstruetion BX LR comme présenté dans exemple 2.3.3. Comme en langage C, il existe done une "procédure principale’, la premitre a étre lancée aprés un séquenc> d’initialisation du micro-contréleur qui s’appellera main. Mais cela n’est pas un standard comme cele est le cas pour le langage C. Test en effet possible de modifier dans le fichier d’initialisation la saut en mettant, l’tiquette qui correspond A votre point d’entrée mais Vintérét de la. manipulation n’est. pas évident, Procédure ou Fonction : II est possible de remplacer le couple PROC/ENDP par FUNCTION/ENDFUNC, en sachant que le langage ne fait aucune distinction entre Procédure et Fonction, contrairement d certains langages de haut niveau 3.4 La section de données Un ensemble de directives permet, Rete de ee Test également possible de leur attribuer, le eas échéant, une valeur initiale. Cette manipulation semble Simple mais obo 3.4.1 Réservation simple Tl svagit juste de réserver un espace mémoire et de tui attribuer facultativement «in nom. 33 capr est la quantité (exprimé en nombre d’oetets) de mémoire que I’on désire allouer. Elle sera initialisée par défaut A 0. Les expressions numériques sont des grandeurs que l'on fournit directement 8 l’as- sembleur. Dans le ces considéré ici ¢’est le nombre d’octets pour la réservation mais dans Ja suite cela pourra correspondre 4 une valeur initiale, & une valeur immédiate & donner am registre,...cte. Cette grandeur peut étre exprimée dans différentes bases : * Base décimale : base par défaut pour lequel aucun préfixe ni suffixe n'est nécessaire » Base hexadécimale : comme pour le langage C, cette base est sélectionnée lorsque Ja quantité est préfixée avec Ox (Exemple pour la valeur 255 : OX00FF), Un alte native est utiliser le & + Base quelconque (entre 2 et 9) : la syntaxe ext: hasn_digits, o& base est la base choisie et digits sont les caractéres (en 0 et base — 1) représentant le nombre. (Exemple en base 5 : 5_ 1213 représente la valeur 183 = 1x 5°-+2x 5?+1x5!+ 3 x 5°). Cette possibilité s’avére principalement intéressante pour la base binaire dans laquelle le programmeur peut aisément exprimer une valeur (de registre par exemple) pour laquelle il connait les bits & positioner. Par exemple pour mettre les bits de poids 3 et 5 d’un octet a 1, il faudra spécifier : 200101000 = 2_101000 = 40) * ‘Base’ ASCII : inutile d’apprendre par coeur la base ASCII! En entourant un ca ractére unicue par une simple quote (’), l'assembleur comprendra.qu’il doit prendre Ja valeur ASCII de ce caractére comme valeur de 'expression. Il est aussi possible de construire une chaine de caractéres (pour la création d’un message par exemple) en entourant celle-ci par une double quote ("). 1 faut également noter que cette expression pourra étre un calcul littéral simple. Par exemple TasDeMots SPACE 12*4-+9 réservera 51 octets. Le caleul sera évidement fait par l'assembleur (ct done le processeur du PC de développement) lors de la génération du code (et non 8 un quelconque moment par le Cortex). Les principaux opérateurs arith- métiques (+,-,",/, >> (décalage a droite), << (décalage A gauche), & (et), | (ou)...., ete. permettent de construire ces expressions littérales. L’utilisateur avaneé trouvera dans la documentation technique, une liste exhaustive et détaillée des opérateurs existants ainsi que leur niveau de préséance (priorité relative) en aachant que les parenthéses sont autorisées. 3.4.2 Réservation avec initialisation Différentes directives existent pour créer des zones mémoires contenant des valeurs particuliéres (variables initialisées), En voici la liste avec les arguments possibles : La réservation par FILL est le pendant de la directive SPACE mais avec initialisation. On spécifie que l’on veut réserver expr octets initialisés avec la valeur valeur qui sera codée sur valeurtaille octets. Une différence de taille : (Toute valeur non signée peut étre stockée sur un format plus grand que celui juste nécessaire sa valeur; il suffi d’ajouter des 0 devant. Lassembleur ne peut pos savoir a priori sur quelle taille il doit coder W’information. [Vait Fri 400°%,1 ;Reseracion Vali dos 4 cette: PB FR FB FD | | vere int YoxrD.2 Reservation Val? des 4 det mots OOF ODE | | tee fuerns ‘nares wrscee omnes oer emaarsamanen | Exemple 9 : Bremple de réseruation avec FILL Les 4 autres ine spécifient dans la directive la taille de la variable a Q =a Tes données sont, par défaut see un donnée de type W commencera sur une adresse paire (bit, de poids le plus faible & 0) et les données de type D et Q seront sur des adresses modulo 4 (les 2 bits de poids le plus faible & 0) L’option U permet de préciser que l'alignement west pas nécessaire, Attention cela peut étre excessivement dangereux!! Le nombre de réservations correspond done au nombre de valeurs initiales fournies. La premiere initialisation est obligatoire, les suivantes sont facultatives. L’exemple suivant utilise ces différentes directives avec différentes bases et plusieurs formes d’expressions littérales. La figure (fig.3.3, p.36) montre le mapping mémoire résultant de cet exemple en prenant, 0x20000000 comme adresse de base. Octinit DOB 0x24,2_ 9111 Chaine DCB "toto',",10,13 Demimot DOW 47, 1248 Mot DoD 3,08F0F * 3 Hoct DOB OxAB>> 2 —_; Doux décalnges & droite Danger DOWU Ox1294 Exemple 10 : Exemple de réservations avec initialisation Sur exemple, 3 octets de bourrage (padding) ont été ajoutés par V’assembleur pour permettre aux données d’étre alignées. Un octet a été placé en 0x20000009 pour que demimot soit placé & ume adresse paire (0x2000000A) et 2 octets ont été ajoutés en 0x2000000B pour que adresse de Mat ait. ses 2 bits de poids faible & 0 (0X20000010). A contrario, le demi mot Danger se retrouve désaligné en 0x20000019, puisque la directive DOWU a été utilisée pour le eréer. 35 0x20000000} 0x2000000E| 3 19605 = oxeFrR's AP? Ficure 3.3 ~ Exemple de réservation avec initialisation 3.4.3 Initialisation des données : le diable est dans les détails Que se passe t “il dans la vie d'une variable initialisée? Dans un cycle de dévelop- pement normal, on peut imaginer que cette variable prenne naissance au chargement du programme en mémoire. Le Leader (programme en charge du transfert: depuis le poste de développement vers la carte & base de Cortex) va écrire & 'alresse mémoire correspondante de cette variable la valeur initiale prévue. Ensuite, si la variable est va- riable, elle va évoluer et ne sera plus égale & sa valeur initiale. Supposons maintenant que Putiliseteur redémarre la ible (RESET). Le programme repart sans passer par la case loader. Qu’est-ce qui garantit que la valeur initiale sora retranscrite? A priori en langage d’assemblage rien. Il s'avére cependant que, dans la majorité des cas (du fait qu'il soit souvent couplé & un compilateur C), Passembleur a prévu cela, Le méca- nisme mis en place repose sur un doublement de zones & initialiser : un premier espace adresse de type RAM pour les variables elle-mémes et un doublon en mémoire de type RON (généralement, juste aprés le code) contenant les valeurs initiales. 11 suffit ensuite avoir A se disposition une routine qui récupére les tables contenant les adresses des différentes zones et. qui opere & la recopie de Pune sur autre. Une légere adaptation de la méthode permet aussi de réinitialiser les variables & 24ro. Ces manceuvres, au demeu- rant fort utiles, n’apparaissent. pas forcément clairement. Ainsi pour le cas de la suite de développement RealView d’ARM, cola passe par l'emploi d’un librairie dynamique dans le code qui se fsit par Pajout d’un sympathique mais néanmoins obscur IMPORT //LibSS Request8Sarmlib|/ dans Pentéte du fichier principal. 3.5 Et c’est tout? fvidement non_...il existe encore certaines directives pour I’assemblour qui ne sont pas explicitées dans ce chapitre. Certaines (ZQU, RN, LTORG) le seront dans le chapitre suivant étant donné qu’elles ont principalement attrait & la manipulation de données (et done & la gestion des opérandes). D’autres concernent le partage (IMPORT,EXPORT) 36 de variables ou de procédures. C’est le propos du chapitre 77. Certaines enfin ne seront pas mentionnées ici car leur intérét eat assez limité (INFO, TTL,..). Celles qui restent, sont listées ci-dessous. Elles sont plus particulidres (dans le sens oi leur emploi n'est. généralement pas nécessaire pour produire un exécutable) mais elles peuvent s’avérer fort utiles. 3.5.1 Directives de gestion de la mémoire oli eapr doit correspondre & une valeur d'une puissance queleonque de 2 (de 2°. 2). $i expr n’est. pas spécifiée la valeur prise est 2. ALIGN permet de positionner les données ‘ou les instructions qui suivent cetie directive, sur une adresse alignée modulo eapr. Cette directive insdre des 0 (en zone DATA) ou des instructions NOP (en zone CODE) pour aligner le code. Son utilité est certaine pour résoudre des problémes de fatals désalignements mémoire. L’emploi d’un ALIGN 1 resemble cependant plus & un sujet de philosophic. ALIGN peut. prendre d’autres arguments optionnels pour insérer un offset, supplémentaire & Palignement Cette directive permet de réserver, repéré par lo nom symbol, une zone de mémoire banalisée de la taille size (toujours en octets) et optionnellement alignée (en suivant la méme syntaxe que celle indiquée pour utilisation d?’AREA). Les espaces de mémoire ainsi eréés, seront initialisés & 0 par le Linker et mutualisés. C'est & dire que le Linker ne réservera au final qu'une seule zone commune telle que la plus importante zone COMMON soit inchise & Vintérieure, Un des intéréts de disposer de cette directive est optimiser la gestion de la mémoire dans des projets conséquents, notamment 3 des fins allocation de dynamique de mémoire par un syst2me d’exploitation. Cette directive permet de réserver avec initialisation (expr) , & instar des directives DCB, DCD..., des emplacements mémoire mais non pas en zone DATA mais en zone CODE. On peut, par exemple utiliser cette directive pour créer des tables de saut pour réaliser des acc’s indexés 4 un ensemble de procédures (ef. 6.2.4). oit bool vaut TRUE ou FALSE. L’absence de bool étant équivalent & TRUE. Ces deux directives permettent de préciser & assembleur que on désire obtenir on conserver un alignement modulo & de la pile sys:me. 37 3.5.2. Directives de gestion projet La directive ROUT permet la gestion et la limitation en visibilité d’étiquettes lo- cales. Ceci est pratique pour éviter les interférencos entre deux étiquettes similaires. Un étiquette locale (LOCAL LABEL) est une étiquette de la forme nfnom}, ot n est un nombre (entre 0 et 99) ce qui est normalement interdit car une étiquette doit théorique- ment débuter par une lettre! Par la suite, on référence cette étiquette par Jn {nom}. Comme le nom est facultatif, étiquette peut n’étre qu’un nombre . La directive ROUT sert alors & positioner les frontitres de visibilité de ces étiquettes locales. | Procedures ROUT ‘ROUT ne signife routine! ] =: = amt) pen | eode | Bae ms \ ibe sProceduret —— | sates (ce s se eee | BEQ %3 i cible maintenant 3Autres a wat ig a = ee an smple 11 : Utilisation d’étiquettes locales Permet d’inclure (GET) le fichier filename dans le fichier courant. Dans le cas de INC- BIN le fichier est supposé binaire (donc soit des données brutes soit un ficher exécutable de tyep .obj). indique 4 Vassembleur qu’il doit conserver dans sa table des symboles |’étiquette ainsi référeneée par symbole. En effet, sauf cet avis l'assembleur ne garde pas trace de 38 reperes locaux et ne conserve que des éléments plus significatifs comme les adresses de procédures par exemple Les directives qui suivent permettent de conditioner Vinclusion de parties du listing dans un projet. De quci s’agit il? Supposons que vous développiez du code pour um systéme qui se décline en plusieurs versions. Supposons que 90% du code soit commun & toutes les version et que seuls les 10% restants correspondent aux options. Comment peut-on gérer cela. Soi: vous avez autant de versions de projet que de versions du systéme, soit vous n’avez qu'un seul projet dans lequel certaines parties ne seront incluses que si, lors de la phase d’assemblage, vous indiquez de quelle version il s’agit. Cela pourrait, donner quelque chose comme | GBLS Version —_; Définition d'une cle globale de compilation Version SETS??? j avec??? "Classic" on "Design AREA MonCode, CODE; Ouverture dune section de code main PROC + code commun a Vensemble du projet BL Ponetionl int Bink AREA MonOode, CODE; Ouverture dune section de code “nclusion pour la version cissique IF Version = "Classic" Fonction! PROC + code pour cette ler version du systame NDP. daclusion pour la version high-tech ELSEIF Version = "Design" Fonction! PROC + code pour cxtte 2de version du systéme ENDP ENDIF Exemple 12 : Clé d’assemblage et code conditionné Dans l'exemple ??, la fonction Fonction existe dans une double version. Ii es: clair que si rien n’était ajouté au code, le Linker viendrait & s"émouvoir de trouver deux rélérences identiques une méme fonction ne ne saurait laquelle choisir pour finaliser 39 Vinstruction BL Fonction. Cependant comme l'inclusion de l'une ou l'autre des deux versions est conditionnée par la structure JF..BLSBIF..ENDIF, assembler va eflectuer un test pour savoir quelle partie de code doit &tre incluse au projet. L’autre partie sera tout bonnement ignorée. Attention, ld encore de ne pas confondre : le Cortex ne verra jamais ces structures algorithmiques. De méme, il ne connattra jamais Pexistence de la clé d'assemblage version qui a permis de faire la sélection. Ce n’est que Passembleur qui connaitra eette clé, qu’il convient done de ne pas confondre avec la notion de variable (on pourrait parler de variables d’environnement mais ce terme peut préter & confus°on...). Le programmeur devra, au moment de générer la version de logicielle qu’il veut fournir, renseigner la clé et remplacer les??? par Classic ou Design. Tl existe 3 sortes de clés d’assemblage : les booléennes (L), les arithmétiques (A) et Jes chaines de caractéres (S). Leur création est réalisée par une directive GBLa (avec = L, Aou S) pour une création globale (vraie pour tous les fichiers du projet) ow une directive LCLa pour un création locale (vraie uniquement dans le fichier courant). Une directive SET permet ¢aifecter la valeur A cette elé. Dans le code le conditionuement se fait par la structure suivante : semnblage (un assembleur travaille en plusieurs passages pour effectuer son travail) si Expression_logique est. fausse tend que le programme a accés & des bibliothéques de calcul en flottant et/ou qu'un coprocesseur de type unité arithmétique en flottant, est adjoint A la structure Cortex. définit le point d’entrée du programme. Cette directive est importante si vous concevez entigrement ie code. Si vous utilisez une librairie (initialisation du processeur, elle intégre la gestion du point dentrée. Lutilisation de cette directive est dans ce cas & proscrire. Chapitre 4 Parlons d’opérandes Le chapitre précédent nous a montré comment était constitué an programme écrit en langage @’assemblage. Intéressons-nous maintenant aux iecimiques existantes dans ce langage pour accéder et manipuler des données. Il s'agit donc de détailler ce que sont les opérandes. Insistons tout: d’abord sur le fait que la structure de ce processeur est de type load/store. Il n'est done possible daccéder aux zones mémoire en section Data que par des instructions spécifiques. Pour ces instructions un des opérandes sera nécessairement l'adresse d'un emplacement mémoire ot il faudra lire ou écrire, La fagon de décrire cette adresse correspond au terme mode 4’ advessags et sera détaillé a la fin de ce chapitre. Pour les autres instructions les opérandes seront des valeurs données explicitement (opérande immédiat), des contenus de registres ou des étiquettes dans le cas des ins- tructions de branchement. Le programmeur, pour spécifier avec quels opérandes il veut réaliser son opération, écrit une expression construite avec des nombres et. des symboles. Lorsque l'instruction prend deux ou trois opérandes comme dans l’exemple suivant : iD sre oppo cpérandc AAESAREANEN C'est on effet Ini qui segs le rvultat de Popération ou de Paffectation. Les opérandes op2 et op3 seront appelés opérandes uxce car ils servent d’alimentation a |’instruction. Attention! : pour les instructions de lecture (LDR et consor) et d’écriture (STR et consor), voir § 5.7, le sens destinataire et source des opérandes est inversé. Cela est source d’erreur au moins au niveau de Vassemblage du projet, méme si au niveau de Vinstruction on peut y voir une certaine logique 4.1 Constante et renommage Au chepitre précédent (§ 3.1.1), il a été expliqué les régles pour construire un sym- bole ainsi que celles pour exprimer des grandeurs mumériques (avec ou sans expression littérales) (§ 3.4.1). L’utilisations la plus simple pour combiner ces deux objets reléve de 41 Ja déclaration de constante. Une constante est un symbole auquel on associe une valeur fixe. Ainsi 'assembleur chaque fois qu'il rencontrera ce symbole saura qu'il doit simple- ‘ment le remplacer par la valeur associée. Vous feriez tout aussi bien que lui en utilisant 1a fonction Trouver/Remplacer de votre éditeur préféré. Le recours A une constante dans un listing & deux intéréts majeurs. Le premier est de rendre le listing plus lisible (ce qui n'est jamais un luxe!) et le second permet, lorsque la constante est utilisée plusieurs fois dans le fichier, d’opérer & la modification de la valeur A un seul endroit’ dans Ie listing, La maintenance ou la mise au point du projet est ainsi grandement facilitée. La directive EQU permet de définir cos constantes. En voici quelques exemples + Char_@ EQU’G? Meg -EQU "Benjour' IMPOSSIBLE => Brreur & Passemblage Boucle EQU12 3 Version de base | VRAI EQUOKFF ——_; L’équivalent est exprimé en hexa | | pAUX 2QU 40s Iuenon Yen pour de ts mnt | Redite QU Boucle; Double equivalenee..pourquoi pas! i Debut QU main ——_; Equivalence avec ne stiquette i | | ! Exemple 13 : Utilisation de la directive EQU La déclaration par EQU est sans conséquence localement, du moment que le 3° champ est une expression correspondant & un entier constant 32 bits'. Une chaine de caractéres comme dans la dernigre ligne de exemple est notamment impossible. Par contre il faut @tre vigilant lors de Putilisation de la constante dans la suite du listing, notamment: pour ce qui concerne Paccés & des valeurs immédiates comme nous le traitons Gans la section suivante, En effet une instruction comme MOV RO, VRAI risque de poser de sérieux souci....(& suivre). La directive RN pormot de rendre, elle aussi, le listing plus lisible (quoique ...) : | nest un nombre entre 0 et 15. Il sert & repérer quel registre général on vise avec cette directive. Le directive permet de renommer le registre visé avec le nom proposé. Ainsi Comptcur RN 0 permet Wutiliser le symbole Compteur plutét que le symbole R0 dans le suite du listing. Cela peut avoir un sens méme si au final on ne voit plus vraiment de quoi il s'agit. Vous pouves également: décourager définitivement vos futurs lecteurs en écrivant XV3{_Z RN 1 et R_4 RN 2. Le registre R2 deviendra R_4 et le regis:ze R1 deviendra XV34_Z : coté lisibilité, c'est pas gagné?! 1. une étiquotte comme dans la 5®"* ligne correspond & une adresse donc & une valeur déterminége codée sur 32 bits 2, Tnutile de vouloir étre vicieux, R3 RN 4 est impossible 12 4.2 Opérandes pour instructions courantes Les instructions courantes sont l'ensemble des instructions en dehors de celles de Lecture/écriture. 4.2.1 Utilisation de registres Registres généraux Dans le plupart des instructions, et les exemples présentés ci avant proctdent de cette approche, le programmeur va utiliser essentiellement les registres généraux RO A0RI2 pour stocker les valeurs avec Iesquelles il effectue ses opérations courantes. A ce titre, les registres peuvent. Aire considérés comme des variables locales. Les registres généraux sont donc les opérandes les plus féquents que l'on peut rencontrer dans un programme. Us peuvent contenir des quantités qui expriment des valeurs de nature trés différente (un entier 8 bits pour le code ASCII d'un caractére, un entier 16 bits non signé pour un indice de tableau, un entier signé pour un déplacement relatif dans le programme,.., ete.). Quelque soit le cas de figure, les 13/ECi8UEES seront toujours vus par le processeur comme un quantité codée sur 32 bits. Charge au programmeur de maitriser la totalité du contenu d’un registre lorsque linformation qu'il traite ne tient, que sur une moitié ou un quart de celui-ci. D’un point de vue codage il peut @tre intéressant de regarder A quoi resemble le code qui sera généré. Supposons linstruction addition simple ADD RO,R1 qui somme la valeur contenue dans les deux registres et stocke le résultat dans RO. Cette instruction est a priori de type Taumb, son codage (et done ce qui sera mis en mémoire CODE) tient sur 16 bits et vaut en héxa 4408. Regardons ce que spécifie la documentation ARM pour le codage de cette instruction (fig.4.1, p43) : Figure 4.1 ~ Codage 16 bits de instruction ADD Tes bits de poids 9 A 15 correspondent & Popcode de Vinstruction. Ceux de poids 3. 6 codent le numéro du registre Rm, ce qui doit correspondre pour nous & RJ. On peut done s‘attendre A trouver Rm = 1 (soit 0001 en binaire ). Le bit DN combiné en poids fort avec les 3 bits de poids le plus faible contiennent Ie second registre, soit AO dans notre vas et donc 0000 eu binaire. Ou doit done avoir en recomposant ce codage 01000100|0|0001/000 = 0100010000001000 = 04408, ce qui correspond bien (ouf!!} au code proposé par assembleur. Le codage des instructions est un peu plus compliqué que ce qui vient d’étre présenté. Le prograrmmeur n'a heureusement pas besoin aller disséquer le codage de l'instruction pour programmer correctement. Un référenciel 43 précis des possibilités des différentes instructions suffira amplement & son bonheur. IL nest cependant pas inintéressant de s’apercevoir que le choix des registres peut influer sur la taille du code. Prenons par exemple instruction qui effectue un ou logique avec affectation des fanions : ORRS Rz,Ry. Le codage (fig.4.2, p.44) du numéro des registres dans la version Thumb est sur 3 bits. Aussi l'utilisation des registres RU & R7 pourra correspondre sans probléme & un code sur 16 bits. Par contre, l'utilisation des registres 8 & RAZ ne pourra plus tre codée uniquement sur 3 bits. L’assembleur sera done contraint d’opter pour un code Thumb~2, ct |'instruction sera alors codée sur 32 bits. Dans ce cas, le codage devient plus complexe ORRS R1,R9 deviendra (tout en faisant Ja méme chose) ORRS R1,RI,R9. Les 3 registres utilisés sont codés sur 4 bits (done plus de restrictions) et les champs imm8 et imm2 et type servent A coder, comme nous le verrons a la fin de ce paragraphe, un hypothétique décalage (shift). Passer de 16 & 32 bits pour coder une opération arithmétique ne représente certes que 2 octets de plus & embarquer en mémoire, mais c'est aussi 100% plus imporsant en taille de code! Sion cherche & optimiser occupation mémoire, il peut étre utile de s’en souvenir et d’éviter autant que faire se peut l'emploi des registres R8 A R12. aaa os] arly aes Figure 4.2 ~ Codage 16 et 32 bits de instruction ORRS: L caluibanorert poh’ . Autres registres Les registres R19 et R14, dans le plupart des cas peuvent servir d’opérandes comme les autres registres généraux. Sauf que ces deux-lA sont perticuliers puisqu’ils corres- pondent respectivement au pointeur de pile (SP) et au registre de lien (LR). Tl convient done @étre prudent dans leur maniement méme si cela s’avére quelquefois obligatoire. Pour le registre R15 (le pointeur d’instruction) la plupart des instructions refuseront de travailler avec (trop dangereux!). De toute fagon, la seule utilisation raisounable de ce registre concerne son affectation pour aller exécuter des sous programmes. Or pour cela, le jeu d’instruction posséde toutes les possibilités de saut (B, BL, BX...) pour couvrit les besoins, Tnutile done de jouer avee le feu. Pour le registre PSR, il a été vu (2.3.5) que deux instructions particuliéres permet- taient d’y accéder. La aussi rien ne justifie de vouloir en faire autre chose. Reste le cas de tous les autres registres que ’on peut rencontrer dans un microcon- trdleur (en sortant un peu du casur du Cortex done) et: ceux-ci sont Kégion! Pour Ie Cortex, ils appartiennent au monde extérieur, & tout cet espace mémoire accessible uni= quement par des instructions de load/store. Rendez-vous done quelques paragraphes 44 u Rte phinieg > Rie RHI plus loin pour savoir comment y acoéder. Ii ne seront donc jamais des opérandes pour les instructions courantes. Décalage Dans le jou d’instructions, tout: au moins dans la partie étenduo en 32 bits (Thumb-2), ily a possibilité d’imposer un décalage sur un des opérandes source. Dans l'exemple ct dessous est réalisé un ET logique : RO + Ri & (R2 << 3). A noter que le suffixe $ de instruction indique que les fanions seront positionnés par 'exécution. [anos Rorinaisi gs Exemple 14» Boa wR oe ine Tl et done possible®, d’introduire différents décalages, & droite ou A gauche, sur le demier opérande source. Ce qui peut paraitre comme un subtile astuce est en fait grande- ment utilisé par les compilateurs. Rappelez-vous qu’un décalage a droite (resp. gauche) de n bits est équivalent & une multiplication (resp. division) par 2". Utilisé habilement cela peut faire gagné beaucoup de temps de calcul La syntaxe est alors, dans le cas de 3 opérandes : Dans tous les cas, 4, j,k sont entre 0 et 12 et n est un nombre entre 1 et 31. Le décalage logique introduit des 0 A droits ou & gauche. Le décalage arithmétique réintroduit le bit de poids fort (done le bit de signe) pour ne pas perdre la représentation signée d’un nombre. La rotation recopie le bit[0) sur le bit[3i] A chaque tour. Enfin, RRX fait une rotation unique sur 33 bits, le 33" bit étant le fanion C. Au sujet du nombre d'opérande : L’exemple précédent ne fait apparaitre en réalité que 3 opérandes. En effet on considére que R2, LSL #3 ne constitue d proprement parlé qu'un seul opérande. Ceite remarque n'ayant qu'un mineur intérét sémantique. 4.2.2 Opérande immédiat Cas classique Liinstruction de transfert MOVS R6,#0 x 11 est composée de deux opérandes de nature différente, Elle va affecser le premier opérande (registre R5) avec le second opé rande (la valeur 17=0x11). Ce second opérande est un opérande immédiat, Crest & 3, cette possibilité est limitée & 15 instructions arithmétiques : ADC, ADD, AND, BIC, CMN, CMP, BOR, ORN, ORR, RSB, SBC, SSAT, SUB, TEQ, TST, USAT 45 eR RA, gt clog aed aodidan dire qu’il fait partie intégrante de Vinstruction : opérande immédiat sera inclus dans le code de instruction comme le montze le codage de cette instruction (fig-4-3, p-46). Vassembleur nous donne le code en héxa 2511. Regardons 1A aussi la documentation ARM is FIcuRE 4.3 - Codage 16 bits d'un MOVS avec opérande immédiat Le 5 bits de poids fort codent Vopeode, les bits 6 & 10 code le numéro du registre (le codage sur 16 bits n’est possible que pour les registres RO R7) et la valeur immédiate cat codé sur les 8 bits de poids faible. En prenant 101 pour le code de RS on retrouve bien le code attendu. Cas récalcitrant Que se passe t'l si!a valeur immédiate, que l'on suppose non signée dans cet exemple, dépasse 2557 Dans ua premier temps, comme pour le codage du numéro du registre pour exemple du OU logique (fig-4.2, p.44), !’assembleur va commuter sur un code 32 bits, La consultation de la documentation montre qu’il est alors possible de spécifier un opérande immédia: codé alors sur 16 bits. Soyons fous! Le registre R5 faisant 32 bits, il doit pouvoir étre initialisé avec une valeur immédiate codée sur 32 bits. Essayons par exemple Erreur & assemblage Exemple 15 : Exemple d’opérande immédiat problématique Echee! On’se heurte maintenant & architecture RISC du Cortex. L'assembleur va retourner un aimable message (’insulte précisant que lopérande dépasse les capacités de représentation d’un opérande immédiat. Les instructions sont codées sur 16 ou 32 bits et il n'est pas possible d’y déroger, Il est done parfaitement cohérent qu’un opérande ne puisse pas utiliser toute la place prévue pour l'ensemble du code de instruction. Deux réponses & c> probléme sont apportés par ARM. La promiére, partic], consiste & utiliser les décalages de registres. Par exemple, Paddition RO avec la valeur immédiate OxFF100 est: impossible. Par contre, il est possible de charger Ri avec OxFF10 ct de faire ’addition de RO avec Rl << 4. Le seconde approche est plus systématique. Elle n’est toutefois valable que pour le chargement d’un registre et s’appuie sur Vutilisation de instruction LDR. Comme nous le verrons dans la section suivante, LDR permet de charger un registre avec le contenu 46 @une mémoire dont Padresse ost donnée en argument. Reprenons notre ligne de code précédente et remplagons-la par : LDR R5,=0x1FF400 j=> OK a Passemblage Exemple 16 : Bremple d’opérande immédiat moins problématique Maintenant. pas de probléme coté assembleur...On pense utiliser, avec une syntaxe Kegerement différente, un opérande immédiat, En réalité le vrai code embarqué pour cette instruction est : [ Exemple 17 : Mais ot est passé Vopérande immédiat LDR RS [PC #18] j=> OK & Passemblage [PC.#.18] signifie que le processcur doit aller chercher le contenu de adresse localisée 18 adresses au dessus de l’adresse couratif@idil/pointean Malini tiGMl20)) Laissons de coté pour Vinstant l'adressage indirect (reconnaissable par l'emploi de [ }), admettons-en juste le principe. Schématiquement la situation des contenants et des contenus mis en couvre correspondent. le figure (fig.4.4, p.47) AREA CODE FiGuRE 4.4 - Récupération d'un opérande immédiat: codé sur 32 bits pleat acquit Une instruction comme LDR Rj,~exprou expr est une valeur litrérale exprimée dans une base quelconque, est done une pscudo-instruetion, Selon la valeur que prend expr, Vassemblour va générer un codage différent. 1. Si expr peut étre codé sur 8 bits : L’instruction sera MOV R,,#eapr. 2. Si eapr peut étre codé sur 16 bits : L'instruction sera MOV.W R,,Bezpr. 3. Sinon LDR R;,/PC, #offset], o' offset est un déplacement relatif permettant datteindre la zone ‘litteral pool’ oti cette valeur sera crée. aT Literal pool et directive LTORG De sa propre initiative, 'assembleur va créer, lorsque cela est nécessaire, des zones de mémoires pour stocker les valeurs immédiates qu'il ne peut pas directement inclire dans le code de I'instruction. Ces zones sont appelées . Elles sont crées par défaut & la fin de chaque section de code. Cette relative proximité permet que le déplacement relatif & spécifier au pointeur PC pour atteindre la valeur ne soit, pas trop grand. En effet, cat offset doit inférieur & 4096 (dans le meilleur cas, c'est & dire pour un codage sur 32 bits). Quand la pseudo instruction LDR Rd,=erpr nécessite un placement de la valeur immédiate en Literal Pool, V’assembleur vérifie dans un premier temps, que cette valeur n’a pas été erée préeédemment et le cas échéant qu'elle peut étre stteinte (déplacement relatif inférieur & 4096) pour pouvoir utiliser. Si cette double condition mest pas remplie, il erée cette constante dans le prochain Literal Pool. T reste cependant envisageable que la fin de la section soit trop éloignée pour pouvoir envisager cette manipulation implicite*. Il existe alors la possibilité de forcer la aréation d'une zone de stockage via In directive LTORG. Dans exemple 4.2.2, la directive LTORG est. placée entre la procédure main et la fonction RienFaire. La zone de stockage sera done insérée A ce niveau. On pourra alors constater que Vinstruction LDR R5,=0x1FFFF correspondra en réalité & LDR 5, [PC, #8]. Sans Putilisation de cette directive, l'assembleur aurait été en échec puisque la réservation de 5000 octets & I’étiquette Resa Vide dans la méme section de code im- plique que la Literal Pool suivante est trop distante pour étre atteinte par un offset inférieur & 4096. 4, Si tout le code est de type Thumb-2, donc codé sur 32 bits, Voffset de 4096 est équivalent & 1024 lignes de code en langage d’assemblage ce qui est déja respectable mais pas totalement inimaginable. 48 | | SECTION PROGRAMME AREA MonCode, CODE, readonly, ALIGN=6 Debut du programme } Chargement dan valeur immediate 5 Appel a procéiure int Bint } Boucle infnie | LYORG j Ouverture dune sone de stockage RicnFaire PROC NOP 3 Rion faire. | axe woe BNDP ResaVide space 6000 _ésorvation pour "éloigne" Je fn de section ENDP [/ Exemple 18 : Utilisation de la directive LTORG 4.3 Opérande pour les accés mémoire : modes d’adres- sage Tl est évident que toutes les données d’un programme ne peuvent étre exclusive- ment contenues dans les registres. Tl est done nécessaire dans le déroulement d’un pro- gramme d’aller chercher des opérandes sources en mémoire (lecture) ou d’aller déposer des opérandes destinataires en mémoire (éeriture). Ces opérations sont los opérations de load/store. Plusieurs variations de ces instructions peuvent étre exploitées mais glo- balement elles peuvent se résumer & deux opérations types : {expr} est une expression qui permet de calculer Padresse ot sera ue (LDR) la valeur mettre dans 2, ou stockée (STR) la valeur contenu dans le registre Ry. Quelques remarques importantes au sujet de cette syntaxe : © Cette expression contient toujours au moins un registre général. Il est généralement, appelé »cwastre de base puisqu’il va définir une adresse de base & partir de laquelle Vace’s en mémoire va se faire. 49 La notion et Vordre des opérandes source/destinataire existant pour les instruc- tions courantes, n’a ici plus de sens. Le registro de base peut évoluer (incrémentation ou décrémentation) avec l'exé- cution de linstruction. Les différentes possibilités de ces évolutions correspondent aux modes d’adressage. ® Llutilisation de ces instructions sont obligatoires an cours d’un programme mais ce sont celles aussi qui eréent le plus de soucis, En effet, si le registze de base contient, suite A ume manvaise manipulation, une valeur aberrante, le bug est assuré! © Les différentes variations vont correspondre 4 des mnémoniques différents mais contenant toujours les radicaux LDR ou STR (un peu comme des verbes qui peuvent se conjuguer a différents temps mais qui gardent: leur sens initial). On peut notamment distinguer : = Celles qui autorisent d’alier lire ou écrire un octet (LDRB, STRB), un demi-mot (RDI, STRH) , voire c’eflectuer plusieurs lectures/écritures (LDRD, STRD), + Gelles qui permettent de spécifier qu'une dounée en lecture est signée (LDRBS, LDRSH, ...) » Et enfin celles qui ont un lien avec les privileges ou es protections des acts mémoire (LRDEX, LDRBT, ...) « Il m’existe pas (contrairement au langage d’assemblage comme Intel, Motorola, MicroChip,..) d’ace’s direct A la mémoire. Il est donc toujours nécessaire d’opé ret en deux temps : récupération de l’adresse dans un registre puis acc’s & la mémoire via ce registre. 3.1 De la notion de pointeur {expr} contient au minimum un registre qui lui contient une adresse de base. Il s’agit done bien ici de la notion de pointeur que l'on peut rencontrer dans un langage structuré de haut niveau. En langage d’assemblage, on utilisera plus habituellement le terme d'aiessage indirect. Le principe a déja été illustré & travers linstruction LDRB RI,{RO] présentée figure (fig.3.2, p.32). R6 est un pointeur qui contient done (par Géfinition de la notion de pointeur), une adresse & laquelle le processeur doit aller lire pour affecter 'opérande destinataire, ici 22. L’emploi des crochets ({ et }) entourant le nom du registre permet indiquer A l’assembleur que ce qui nous intéresse n’est pas le contenu du registre en lui-méme mais le contenu de adresse stockée dans le registre Le mnémonique LDRB a été utilisé dans cet exemple; le processeur mira done lire qu'un seul octet qu'il considérera comme non signé (LDRSB aurait permis de prendre en compte le signe). Ainsi les 3 octets de poids fort seront positionnés & 0 pour que la valeur sur 32 bits contenue au final dans RY correspondent a la valeur 8 bits contenue & Tradresse source. On parle dans ce cas de promotion non (en promotion signée, Ie bit de poids fort aurait é8 recopié dans les 24 bits de poids fort du registre pour que les valeurs en 8 bits et en 32 bits correspondent & la méme quantité signée).. Resce un détail régler : comment adresse contenue dans R6 a {-elle été spécifiée? Dit en terme de langage structuré : comment a-t-on initialisé le pointeur? En utilisant tout simplement la syntaxe détaillée dans le section précédente : LDR R,, =imms2. Dans Pexemple précité, R9 a été initialisé par LDR R3,=Octinit. Cette syntaxe, qui de prime 50 abord semble étre une exception & Is forme générale LDR Ri, {expr}, est égelement un adressage indirect mais avec le poirteur PC. En effet, LDR est une pseudo instruction et lorsque la valeur immédiate est codée sur 32 bits (et c'est le cas ici puisque Yon veut assigner A R3 la valeur de Vadresse de la variable initialisée Octinit), Vassembleur stocke cette valeur en literal pool et y accéde par déplacement relatif (donc adressage indirect) de PC. Schématiquement ces deux lignes de code, mettent en jeu un double pointage comme le résume la figure (fig.4.5, p.51). C’est le seul moyen d’aceéder au contenu d’une variable. oxzo000102 ox20000101 oetinit (8 |ox20000100 jox200000FF loxz00000F& oooocoz] “AREA CODE AREA DATA Figure 4.5 ~ Initialisation et utilisation d’un pointeur 4.3.2 Les modes d’adressage Dans l’utilisation de indirection simple /R,J, adresse visée par le transfert est expli- citement contenue dans le registre Rj. Il existe 3 autres modes d’adressage pour lesquels ce lien n’est pas aussi direct. L'explication de ces modes d’adressage est illustrée & tra- vers V'instruction de chargement d’un demi-mot vers un registre LDRH mais ces modes existent également pour Pécriture (STRH) et pour les différentes variations de mnémo- niques LDR et STR. Adressage indirect avec déplacement Dans ce mode d’adressage, il s’agit d’ajouter un déplacement supplémentaire (offset) adresse contenne dans le registre de base. La syntaxe est : Le principe de ce transfert est illustré figure (fig.4.6, p.b2). Il est A noter que la valour d’ofisct est dans plupart des cas limitée A 4096 mais que pour cerlaines formes particuliéres (LDRHT par exemple) la valeur maximale peut élre moindre. Cette gran- deur, comme toute valeur immédiate dans une instruction, peut également influer sur la taille du codage (16 ou 32 bits). Une des utilisations principale de ce mode d’adressage est Vaccts & des structure de données. Seule Padresse de la structure est connue et sera déposé dans le registre de base. Pour aceéder ensuite aux différents champs constitutiff de la structure, il faudra spécifier, avec offset le déplacement relatif & imposer pour atteindre ce champ (voir § 6.5) Adressage indirect avec index Pour ce mode, l’adresse est composée de l’addition de deux registres . Le syntaxe est la suivante » Avec ce mode, il est assez aisé de coder un algorithme utilisant un tableau : il suffit de mettre ledresse du tableau dans le registre Rn et Vindex du tableau dans le registre tm, Une ligne de code en langage C comme Local = Tab[indice] ; peut tout a fait correspondre au code assembleur LDRH R8,/R6,R1] de la figure (fig.4.6, p.52). LDRH R3,{R6 ,#0x03} LDRH R3,[R6,R2} ‘ox20000100 i oxzoooa%o1 | ‘oxz00000FF 4 | ox200000F& | aad axzoo00103 7 9x20000162 3 AREA DATA AREA DATA @ () FIGURE 4.6 ~ Transfert avec offset immédiat (a) ou evec index (b) Adressage indirect avec post modification Dans les deux modes prévédents, le registre de base n’était pas modifié par l'ins- truction. Cette pratique est tout & fait compatible avec la gestion de tableaux ou de structure de données, pour lesquels les adresses sont fixes. Ce mode (et dans celui qui sera préseuté ci aprés), la valeur du registre de base sera modifiée avec instruction, Cette gestion correspond parfaitement & la notion de pointeur que l'on trouve dans les langages de haut niveau : au fur et A mesure de utilisation du pointeur celui-ci peut évoluer. c’est done intrinstquement une quantité variable. Pour ce premier mode, la modification du registre se fait aprés Texécution du trans- fert en utilisant la syntaxe L’exécution a done deux effets successifs : l'affectation du registre Rt avec le contenu de Vadresse stockée en Rn puis Rn + Rn £ imm8 [DRA RS (RE) eOK0a ‘freooor04 | Sizeanre3 oes onan =_ | Senos | | | sor | Avent Pintruction Aprés Fintraction AREA DATA AREA DATA @ o FIGURE 4.7 — Transfert avec post-déplacement (a) ou pré-déplacement (b) Attention : la syntaze est assez proche de celle utilisée pour Vadressage indirecte avee offset. Soule la position du terme immédiat (4 Vintérieur ow a U'eatérieur des cro- chets) change. Cela est source de confusion, surtout en relecture de listing. Dans Vexemple (fig-4.7, p.53) le déplacement est positif (+4). Il est A noter que ce déplacement n'est non seulement pes obligatoirement unitaire mais qu'il peut sire ‘compris entre 127 et +128. 53 Adressage indirect avec pré modification Dans ce cas, la modification du registre intervient avant le transfert, Lexécution se passe done également en deux temps (fig.4.7, p.53). Premier temps : modification du registre de base Rn — Rn -imm8. Second temps : transfert de la quantité nouvellement visée vers le registre Rt Atiention : Id aussi, i west pas inutile davoir une bonne vue (ou plutot une bonne police de caractéres!!1) pour ne pas rater le! qui suit les crochets Chapitre 5 Tu parles d’un jeu... 5.1 Guide de lecture Le lecture dun jeu d’instruction est tout sauf une sinécure. Le lecteur standard lira ce chepitre, dans un premier temps, en diagonale. Mais au final, c’est certainement le chapitre dans lequel il reviendra le plus souvent pour savoir ce que peut faire le processeur_ et surtout comment (c’est & dire avec quels opérandes) il peut le faire. Un certain nombre de conventions, d’omissions ou de régles implicites régissent la ré- dacticn des explications sur le jeu d’instruetions, II convient done de lire ces paragraphes en tenant compte des remarques suivantes : + Certaines instructions ne sont qu’évoquées (en fin de chapitre) et: non explicitées, Elles correspondent & des fonctions avancées du processeur et donc s'adressent & des programmeurs émérites qui ne pourront se satisfaire de eet unique document. ‘* La majorité des instructions existent en version codée sur 16 bits ou sur 32 bits. L’assembleur, selon ces propres régles implicites ct en fonction des limites (taille des opérandes immédiats par exemple) optcra pour l'un ou Pautre. Il est cependant possible de forcer la taille souhaitée pour ce codage en ajoutant extension .W (pour 32 bits) ou .N (pour 16 bits). Ce faisant, cela peut induire une plus grande maftrise du processus de fabrication du code mais au détriment d’échec en cas impossibilité de coder Pinstruction sur la taille imposée. * Pour de nombreuses instructions il est possible d’adjoindre un suffixe qui permet alors de conditioner V'exécution de l'instruction. La possibilité d'ajouter ce suf- fixe apparait dans les tableaux par le symbole . L’ajout de ce suffixe n’est pas sans conséquence sur le code engendré par Fassembleur car cela revient & insérer une instruction [T avant Vinstruction elle-méme. I done nécessaire de s’en souvenir, notamment lors de séquences de mise au point oit cette instruction peut apparaitre alors que le programmeur ne I’a pas explicitement écrite. Il est égale- ment nécessaire de se rappeler que le conditionnement est relatif A l'état, des fanions ni eux mémes sont positionnés généralement par linstruction qui préeéde celle ane l'on conditionne. La liste des suffixes est donnée dans le tableau ci-aprés avec les conditions et la combinaison logique des fanions afférente & chaque condition. Pour plusicurs instructions, il est nécessaire de faire 1a distinction entre te poids 55 faible et le poids fort de Vopérande. Par souci de compacité les abréviations pf (poids faible) et PF (poids fort) ont été utilisées pour faire ces distinctions. © Pour les instructions courantes, le premier opérande est souvent présenté comme optionnel. Cela implique que Pinstruction ne supporte qu'un seul opérande et auiquel cas cet unique opérande sert A la fois de source et de destinataire. Par exemple ADD RO,#2 signifie RO— RO + 2 © Les regisires yénérauax soul dénolés indifféremment Rd, Rn, Rm ou Ra pour les instructions courantes. Il n'est pas nécessaire pour une instruction de vérifier d n#m + a, Ainsi, V'instruction ADDS.W R1,R1,R1 est tout & fait recevable. * Pour les instructions de leetuire/écriture, le registre de base est An et le registre qui recoit /fournit la donnée est appelé Rt. « L'expression Mz,(Rx) signifie le contenu de I'adresse pointée par Rn. * Llopérateur apparait (option) pour imposer un décalage de bits sur le dernier opérande de la liste. La liste des décalages possible est la méme que celle présentée § 4.2.1 5.1.1 Liste des suffixes "condition" possibles Cetve liste correspond l'ensemble des substitutions possibles pour le symbole . Tl est a noter que cela s’applique également au cas des instructions de saut (B, BL, BX .--) qui deviennent alors conditionnés. Dans ce eas l'instruction IT n’est pas inséré avant le saut. Liste des conditions Suffixe Condition. Fanions Hy Fgalité Z=1 (EQual) NE | Non égalité Z=0 (Non Equal) cs Dépassement de capacité (Cany Set) c=1 | HS __| Plus grand ou égal (non signé) (Higher or Same) GOT Pas de dépassement. de eapacité (Carry Clear) c=0 Lo | Plus petit. (non signé) (Lower) [MI Négatif N=I (Minus) PL Positif N=0 (PLus) vs Dépassement (signé) V=1 (oVerflow Set) ve Pas de dépassement. (signé) V=0 (signé)(oVerfiow Clear) AT Plus grand (non signé) C=TETZ=0 (Unsigned Higher) 56 Liste des conditions (suite) uffixe Condition Fanions TS | Plus petit ou égal (non signs) | C=00UZ=1 (Unsigned Lower or Same) GE Plus grand ou égal(signé) N=V (Signed Greater than or Equel) i Plus petit (Signé) NZV (Signed Less Than) GT Plus grand (signé) Z=0ERTN=V (Signed Greater Than) LE Plus petit ou égal(signé) | Z=10UN ZV (Bigned Less than or Equal) Passons maintenant a la longue et fastidieuse liste des instructions. Elles sont classées, par grandes familles afin faciliter la recherche par théme. Mais & tout seigneur tout honneur! Commencons par une premidre instruction inclassable : Pas d’opération ‘Ne sert d rien @auire qu’a user un peu de temps CPU... A noter cet incroyable subtilité : NOP peut étre conditionnée donc elle ne fait pas ‘rien faire" si la condition est fausse 5.2 Les instructions arithmétiques ‘Addition aveo Canty ADC{S} {,} , # Ra < Rn + const + fanion @ ADG(S} {,J , (} [Rd — Ra +shitt(Rm) + fanion C e> [,} # Rd © Ra+consi, ADD{S} {,} ,f- Ra < Ratconst ‘ADD{S} (,} , {,} | Rd @ Ratshifi(Rm) ‘ADD[S} (,} SP, # Rd < SP+const ADD[S} {,} SP, {,} | Rd = SP+shift(Rm! Multiplication et addition MLA , , , | Rd € (Rn * Rm) + Ra Taddition devient une accumulation quand Rd = Ra voir Vinstruction SMLAL pour une accumulation sur 64 bits. |S ‘Multiplication et soustraction MIS , , , [Rd — (Rn * Rm) - Ra voir Vinsiruction SMLAL pour ne application en 32 bils, EEE | wisntuptionte an MUL{S} (,} , Attention le résultat ne contient que les 32 bits de pf L’instruction n’a done de sens que si les opérandes sources sont sur 16 bits al faut utiliser SMUL pour avoir un résultat sur 64 bits re) __—— SSSR Rd = Riv const RSB(S} {,) , # RSB{S} (,} , {, {,} , # | Rd— Rm | + fanion C Rd & Rum - shift(Rim) SBO{S} {,} , {,} + fanion daaanmr | eit SDIV {,} , | Rd © Rn + Rn Division entiére stricte : le reste est perdu udp Multiplication signée et addition 64 hit: SMLAL , , , | [Rdpp nad = Ra* ia [Rdpr | Reps) [Rdpy « Rdys] est un pseudo registre 64 bits composée de deux registres 32 bils ee Multiplication signée - résultats sur 64 bits SMULL , , , | [Rdpr : Rdpy| — Rn * Rim 58 Saturation signée SSAT ,#,{,} | si (Rn <0) Rd — min(—26°"5—D shift(Rn)) si (Rn >0) Rd © max(20™™"5—1) _ | shift(Rn)) Le janion Q est mis dun sill y a eu saturation, sinon Q reste inchangé Le fanion Q doit étre mis 4 0 avant Uopération pour exploiter cette information La saturation est une opération importante en représentation 4 virgule fire Se Soustraction simple SUB{S} (} ,,# Rd + Rn-const SUB{S} {} ., ( {} SP,#é Rd + SP-const SUB{S} {} (SP, {,} Rd + SP-shift(Rm) eo Division non signée | [UDIV (,} , | Rd — Rn = Rn) i Multiplication non signée - résultats sur 64 bits UMUL , , , | [Rdpr : Rdg] — Rn * Rm Multiplication non signée et addition 64 bits UMLAL , , , | [Rdpp : Rape] — Rn * Rm +IRdpr : Raps} [Rape = Rd,y] est wn pseudo registre 64 bits composde de deus registres 32 bits | eae Saturation non signée USAT ,#,{,} | Rd — max(20"5-) — 1 shift(Rn)) Te fanion Qest mis @ un sl y a ou saturation, sinon @ reste inchangé Le fanion Q doit étre mis d 0 avant Vopération pour exploiter cette information La saturation est une opération importante en représentation 4 virgule fize 59 9 “we fay poe segs tea PA * Ravenel tumprans 5.3 Les instructions logique et de manipulation de bits > eee ET logique AND{S} , , # Rd © Rn AND const AND{S} , , {,} | Rn © Rn AND shift(Rm) Décalage arithmétique a droite ASR{S} , , # | Rd — Rm >>inms ASR{S} , , Rd © Rn >> am Te décalage réintroduit le bit de signe d gauche Le dernier bit sortant a dreite affecte le fanion Carry C a, Effacement de champs de bits BFC , #, # | Ral pr+Nbits : pl] — 0 pf = 0...31 et Nbits = 1.32 Cette instruction n'a pas de version modifiant les fanions | Recopie de champs de bits de pf A une position donnée BF l ,, #, # | Ral pit Nbits :pf] <— Rn[Nbits :0] Pf = 0...31 et Nits = 1.32 Cette instruction n’a pas de version modifiant les fanions L’instruction symétrique permettant de recopier un champs de bit donnée dans le poids faible de Rd neriste pas Effacement de bits par ‘aacquedey, BIC{S} [,} , # Td < Rn AND NOT (const) BIO(S} (,} , ( , | Rd < CLZ(Rn) Ra recoit une valeur entre 0 (Rd = OxFFFFFFF) et 32 (Rd = 0) 60 OU Exclusif EOR{S} , , # Rd € Rn XOR const EOR{S} , , {,} | Rd < Rn XOR shift(Rm) x. Décalage logique & gauche LSL{S} feRa>t , # Rd © Rm << imm5 LSL{S} , , Rd © Rn << Rm Le décalage introduit des zéros & droite Le dernier bit sortant @ gauche affecte le fanion Carry C Décalage logique & droite TSR{S} , , # Rd © Rm >> imm5 LSR{S} , , Rd © Rn >> Rm ‘Le décalage introduit des zéros @ gauche Le dernier bit sortant & droite affecte le fanion Carry C as Complément & 1 logique MVN{S} , # Rad © NOT (consi) MVN{S} , {, } Rd < NOT(shift(Rn)) Complément & 2 [NEG {,} [Rd — -Rm NBG est équivalent RSBS OU logique complémenté | ORN{S} {,} , # | Rd= Rm OU NOT(const) ORN(S} (, {, {,} , F [Rd Rm OR const) ORR{S} {,} , {,} | Rd — Rm OR shifi(Rm) OL RBIT , ee Inversion Octets PF et pf REVi6 , | Rd(31 24) — anf? 20] Rd[23 :16] + Rm R15 :8] ~ Rm[23 :16] Ra[7 0] < Rm[31 :24] [ERB [iovcrston Octee PF cep par | REVi6 , mot Rajat :24] — Rmj23 -16) Rad[23 :16] < Rm|[31 :24) Rd{15 :8] + Rm{7 :0] Raz :0| + Rm[L Ue Inversion signée de | mot REVSH , Ra[ai :8] < Promotion signée (Rm|? :0]) Ra(7 :0) + Ramis 8] Rotation étendue vers la droite ROR{S} , , # | Rd < rotation(Rm, imm5 bits) ROR{S} , , Ra € rotation(Rn, Rim bits) Ta rotation réintroduit le bit 0 sur le bit 91 & chaque tour Tl weciste pas de rotation de n bits vers la gauche puisqu’elle équivaut une rotation de 92-n bits vers la droite Rotation étendue vers la droite ROR{S} , , | Rd ¢ rotetion([Ra,C], Rm bits ‘Meme principe que ROR mais avec le fanion C en Saeme bit & droite Pas de forme auec opérande irumédiat pour ¢ ee Promotion signée sur 32 bits d’un champs de bits SBFX , , #, # | Ra[Nbits :0] — Ru| pF-Nbits : pf] R31 :Nbis] « Ra[Nbits} instruction 62 Be Promotion signée sur $2 bits d’un octet SXTB , {, } | Rd + rotation(Ra)[7 :0) Ra{B1 :8] < Ra{7] Ta rotation peut élre ROR #8 ou ROR #16 ou ROR #24 eee Promotion signée sur $2 bits d’un } mot. SXTH , {, } | Rd = rotation(Rn)[io .0) | Ra{31 :8] + Ra{15] rotation peut dire ROR #8 ou ROR #16 ou ROR a4 Promotion non signée sur 32 bits d’un champs de bits UBFX , , #, # | Ra[Nbits :0) — Rnl p+Nbits pf] ] | Ra(31 -Nbis| < 0 zz Promotion non signée sur 32 bits d’un octet, UXTB , {, } | Rd < rotation(Ra){? <0) Ra(3i :8] H 0 rotation peut étre ROR #8 ou ROR #16 ou ROR F2f Promotion non signée sur 32 bits d’un } mot | UXTH , {, } | Rd © rotation(Rin)|15 0) l Rd[31 :8] — 0 Tolation peut étre ROR #8 ou ROR #16 ou ROR #4 5.4 Les instructions de transfert interne La notion de transfert interne correspond & des transferts ne faisant pas appel & des emplacements mémoire. Ce sont done des transferts entro rogistres ou des affectations de registres avec des valeurs immédiates. ie Chargement d’adresse_ ,

You might also like