Professional Documents
Culture Documents
Le cours ASM propose un aperu de deux langages d'assemblage: x86 et ARM, avec
un accent particulier sur ce dernier. En effet, plus rcent que l'assembleur x86,
l'assembleur ARM joue un rle prpondrant puisqu'il est largement rpandu non
seulement dans les systmes embarqus (comme les smartphones ou tablettes PC),
mais tend aussi se rpandre dans les desktops et serveurs.
Ce chapitre introduit les spcificits des processeurs implmentant les jeux
d'instructions compatibles avec ces deux langages d'assemblage, et donne
galement une brve introduction au langage assembleur.
Les familles des processeurs de type x86 ont une architecture CISC avec des
instructions de taille variable pouvant aller de 1 17 bytes. Elles sont bties sur des
microarchitectures de type x86 avec un souci permanent de prserver une
compatibilit ascendante: ainsi, les gnrations successives de processeurs
admettent plusieurs modes de fonctionnement, qui diffrent en particulier du point
de vue de l'accs la mmoire.
L'architecture fortement pipeline des processeurs x86 (pouvant aller jusqu' plus de
30 tages de pipeline) permet plusieurs instructions d'tre excutes en parallle;
ce type d'architecture est galement nomme superscalaire. Bien entendu,
aujourd'hui, tous les processeurs de type x86 (32/64 bits) sont multicoeurs.
Une particularit intressante au niveau des instructions est la technologie SIMD
(Simple Instruction Multiple Data). C'est une technique largement utilis dans les
processeurs & microcontrleurs permettant d'appliquer des oprations
(arithmtiques) sur un vecteur de donnes, et cela durant le mme cycle d'excution
de l'instruction (donc en parallle).
L'unit matrielle de gestion mmoire (Memory Management Unit) sur x86 est trs
complexe: elle permet de faire de la segmentation (premires gnrations de
processeur x86) et de la pagination. Pour assurer la compatibilit, la traduction
d'une adresse virtuelle sur x86 passe obligatoirement par une traduction de
l'adresse virtuelle vers une adresse linaire (via les segments), puis de l'adresse
linaire vers l'adresse physique.
Au dbut des annes 2000, Intel a volu fortement sur le plan marketing en
renommant les familles de processeurs (Athlon, Opteron, Intel Core 2, etc.), ainsi que
les noms de leurs microarchitectures (non montrs dans ce tableau). Des exemples
de microarchitectures sont Pentium Pro, P6, Nehalem, Sandy Bridge, Haswell,
Skylake, Larrabee, Itanium, etc.).
L'volution de ces technologies s'est accompagn d'une concurrence froce,
notamment avec la prsence de la firme AMD, principal rival d'Intel. AMD a
dvelopp ses propres familles de microprocesseurs (rputes nettement moins
cher qu'Intel), tout en implmentant des microarchitectures x86. Les autres
concurrents sont le coren Samsung, l'amricain Texas Instruments, le japonais
Toshiba et la socit francoitalienne STMicroelectronics.
Les processeurs de type ARM sont principalement utiliss dans le contexte des
systmes embarqus au sens large. Le processeur, de type RISC, est beaucoup plus
"simple" qu'un processeur CISC. En revanche, il existe une multitude de contrleurs
intgr au sein mme du composant lectronique (chipset). Les instructions sont en
principe de taille fixe (soit 16 ou 32 bits). La plupart des instructions s'excutent en
un seul cycle d'horloge.
Il est frquent aujourd'hui d'avoir plusieurs coprocesseurs arithmtiques offrant des
instructions de type SIMD, ainsi qu'un DSP (Digital Signal Processing) afin d'offrir une
puissance de calcul leve tout en maintenant une consommation relativement
basse.
Il n'y a pas de segmentation mmoire comme avec un processeur x86. Seule la
pagination est supporte par la MMU. En revanche, il est possible de mapper des
zones mmoires de tailles diffrentes.
La gestion des interruptions sur un processeur ARM est assez diffrente que sur un
processeur x86. Il n'y a en fait que deux lignes physiques qui sont relies du
contrleur d'interruption vers le cur de processeur, savoir les lignes IRQ et FIQ
(pour Fast IRQ, celleci tant par ailleurs peu utilise). Il n'y a donc que deux vecteurs
d'interruption associs aux interruptions matrielles (avec bien entendu d'autres
vecteurs pour les interruptions logicielles/exceptions).
Au niveau de la gestion des IRQs, une architecture multicoeur base sur ARM est
relativement similaire une architecture x86: un contrleur primaire (appel aussi
distributeur) est responsable de dispatcher les interruptions aux contrleurs locaux
chaque cur.
Les familles Cortex constituent une des familles de processeur ARM les plus en
vogue aujourd'hui. Elles se dclinent en fonction des types d'application (tempsrel,
multimdia, scurit, etc.).
Les dernires versions de Cortex (CortexA15 notamment) sont multicoeurs (jusqu'
4 curs) et supportent la virtualisation, du point de vue de l'architecture matrielle
et du jeu d'instructions. Les performances de ces processeurs (> 2 Hz) se
rapprochent de plus en plus des processeurs x86 tout en consommant moins
d'nergie et en ayant une architecture volutive moins lourde qu'un x86. Ils
constituent donc une concurrence srieuse Intel, pour les serveurs notamment.
10
Les processeurs x86 offrent 3 modes de base: real mode, protected mode et vm86
mode.
Le mode rel (premier mode) n'offre aucune protection et tait utilis dans les
premires gnrations de processeur, alors que la mmoire ne pouvait dpasser 1
Mo, du fait que seule 20 lignes d'adresse taient prsentes (220 = 1 Mo). Les
registres de segment, comme nous le verrons plus tard, tant implments sur 16
bits, une adresse mmoire tait compose d'un numro de segment, puis d'un
offset cod dans un autre registre de 16 bits. Le numro de segment correspond
alors aux bits de poids fort de l'adresse, et le dplacement ne pouvait tre cod que
sur 4 bits (on remarque la possibilit d'avoir un chevauchement (overlap) des
segments).
Le mode protg change considrablement la manire d'utiliser les registres de
segment: ils ne contiennent plus les bits de poids forts, mais un index dans une table
de segment qui donne une adresse physique contenant le dbut du segment. Le
dplacement cette foisci peut tre cod sur 16 bits si les registres sont de 16 bits,
ou 32 bits avec des registres 32 bits. Avec le mode protg, il est possible d'utiliser
la pagination. Aujourd'hui, seule la pagination est utilise et les segments se
rduisent au nombre d'un seul pour chaque type, avec un offset de 232 (ce qui
permet bien de grer un espace linaire de 4 Go).
Nous nous tendrons pas davantage sur les autres modes.
11
Lorsqu'un processeur x86 dmarre, il est dans le mode "real mode". Trs
rapidement, le code logiciel (en principe du bootloader, voire de l'OS, va implanter
une table de segment avec un minimum d'information afin de passer en mode
protg, et de disposer ainsi d'un adressage adhoc. L'OS pourra par la suite
configurer les tables de page afin d'activer la pagination.
Dans le mode protg, il faut encore pouvoir distinguer entre le mode utilisateur
(user mode) et le mode noyau (kernel mode), afin que tout OS moderne puisse grer
correctement la scurit entre l'espace utilisateur et l'espace noyau.
C'est la notion d'anneau de protection ou ring qui permettra de faire la
diffrence. Gnralement, dans un environnement non virtualis, seul deux rings
sont utiliss: le ring 0 pour le code noyau et le ring 3 pour l'espace utilisateur.
Le bootloader reste en principe dans le ring 0. C'est le systme d'exploitation, lors du
bootstrap, qui commutera en mode utilisateur lorsque toute l'initialisation au niveau
noyau sera termine.
12
13
Dans le cours ASM, nous ne considrerons que les architectures x86 32 bits (et non
64 bits).
Le processeur x86 dispose de 8 registres gnraux dont 4 peuvent tre facilement
accessibles en 8, 16 ou 32 bits, selon le modle de la figure cidessus.
Les registres eax, ebx, ecx, edx sont utiliss librement pour stocker n'importe quelle
valeur et peuvent tre utiliss comme oprandes d'une instruction.
Les registres esi et edi sont plutt utiliss dans le contexte d'adressage par
indexation (index d'une table, d'une zone mmoire, etc.), mais du point de vue du
processeur, ils n'ont pas de signification particulire. C'est le cas aussi pour le
registre bp, qui est gnralement utilis pour prserver une rfrence dans la pile.
En revanche, le registre sp est rserv pour stocker le pointeur de pile et peut tre
altr de manire intrinsque avec certaines instructions, comme nous le verrons
plus tard. De plus les registres bp et sp sont associs au segment utilis pour la pile
(registre SS).
Le registre eip contient l'adresse de la prochaine instruction excuter (ce registre
correspond au Program Counter (PC) d'autres processeurs/microcontrleurs). Il ne
peut tre altr directement, mais est mis jour lors d'instructions de saut.
14
15
16
17
Le registre cpsr correspond au registre eflags du x86. Il contient l'tat des bits lis
l'ALU et comporte des bits systme indiquant le mode d'excution du processeur,
l'tat d'activation des interruptions (IRQ/FIQ), et d'autres bits spcifiques au modle
de processeur et lis au jeu d'instructions; par exemple, le mode Thumb est
dtermin par un bit de ce registre.
Certains registres ARM sont rpliqus physiquement dans les diffrents modes
d'excution. Par exemple, les registres r13 (sp) et r14 (lr) sont physiquement
diffrents d'un mode l'autre. En revanche, il n'existe pas au niveau du langage des
noms diffrents pour les diffrencier. Cela complique quelque peu la
programmation, car lorsque l'on utilise ces registres, il est important de connatre le
mode d'excution du processeur.
La rplication de registres dans les diffrents modes permet de prserver les valeurs
de registre d'un mode l'autre et diminue ainsi l'utilisation de la pile.
Lorsque l'on passe d'un mode l'autre, le programmeur manipule donc des fentres
de registres diffrentes, chaque fentre tant propre au mode d'excution.
Les diffrentes fentres de registres sont examines en dtail dans les pages
suivantes.
19
20
Le mode FIQ est utilis lors d'une interruption matrielle de haute priorit. Le cur
ARM dispose en effet de deux lignes d'interruption matrielle, l'une tant rserve
pour le type d'interruption FIQ (l'utilisation des deux lignes est sous la gestion du
contrleur d'interruption).
Comme le traitement doit tre trs rapide, ce mode dispose de registres r8r14
diffrents. Ces registres (notamment de r8 r12) peuvent donc tre utiliss
directement dans la routine de service lie cette interruption, sans avoir besoin de
prserver les valeurs courantes sur la pile. On vite ainsi des transferts mmoire.
21
Alors que le mode FIQ peut grer des interruptions hautement prioritaire, le mode
IRQ est le mode le plus souvent utilis pour grer des interruptions matrielles; les
temps de latence et de traitement sont suffisamment faibles et conviennent pour la
plupart des applications. Dans ce mode, seuls les registres sp, lr et spsr sont
rpliqus.
A l'instar du mode FIQ, le mode IRQ est utilis dans un contexte d'interruption
matrielle et dispose de sa propre routine de service (un vecteur d'interruption IRQ
ddi). Comme toute routine de service, celleci devra rester aussi petite que
possible afin de ne pas dsactiver les interruptions durant une trop longue priode.
C'est pourquoi, en principe, on cherchera quitter ce mode aussi vite que possible
afin d'viter les problmes de rentrance. C'est le mode SVC qui servira de "mode
principal" pour l'excution de code noyau. Le mode SVC est prsent sur la page
suivante.
22
Le mode SVC est le mode "prfr" pour l'excution de code en mode privilgi
(mode superviseur). Le code peut manipuler toutes les instructions sensibles et
dispose de tous les privilges au niveau de l'espace d'adressage.
23
LemodeUndef estutilislorsd'uneinterruptionlogiciellecorrespondantunchec
l'excutiond'uneinstruction(instructionnonvalide).
24
Le mode Abort est utilis lorsqu'un accs mmoire est invalide. Typiquement, cela
se produit lorsque l'accs une adresse mmoire n'est pas permis, ou qu'il n'existe
aucun mappage entre l'adresse virtuelle et l'adresse physique (faute de page). Ces
aspects sont traits au cours de systme d'exploitation dans le chapitre consacr la
gestion mmoire.
25
26
27
28
29
30
31
32
33
Les deux directives cidessus sont lies au prprocesseur : elles auront pour effet
une transformation du code source (en tant que texte) vers le code intermdiaire qui
sera "prsent" au compilateur.
La directive .include permet d'inclure un fichier l'intrieur du fichier en cours de
compilation.
La directive .equiv permet la redfinition de termes l'intrieur du fichier; c'est le
cas par exemple de constantes; chaque occurrence d'une constante sera
systmatiquement remplace par sa valeur correspondante, un niveau textuel.
Dans ce sens, la notion de constante n'a pas de signification particulire du point de
vue du compilateur.
34
La directive .space est trs utile pour la rservation explicite de zone mmoire dans
le code objet, autrement dit dans l'espace d'adressage du code compil. Cette
directive peut tre utilise pour rserver une zone mmoire ddie la pile, par
exemple, ou tout autre type de zone mmoire dans lequel des donnes pourront
prendre place.
Il est intressant de se rendre compte que les adresses croissent en parcourant le
fichier du haut vers le bas. C'est la raison pour laquelle la rfrence stack_high de
l'exemple cidessus indique le sommet de la pile (et non le bas).
35
36
La section bss est gnralement utilise par le compilateur pour dfinir l'ensemble
des variables et donc des zones mmoire correspondantes non initialises. De ce
fait, le code objet stock dans le fichier est rduit car il n'est pas ncessaire de
stocker un ensemble de bytes non initialiss. De plus, la section BSS pourra tre
initialise 0 lors du chargement, aprs avoir allou la mmoire ncessaire.
37
La directive .org informe le compilateur que ce qui suit est placer un certain
offset par rapport au dbut de la section. L'exemple cidessus montre que
l'instruction suivant la directive .org sera place l'adresse 0x18, puisque dans cet
exemple, la section courante (.text) est suppose l'adresse 0x0.
Cette directive peut tre utilise n'importe o dans le fichier, mais ne peut
provoquer une discontinuit de l'espace d'adressage, i.e. il n'est pas possible de
donner un offset qui aboutirait une adresse infrieure la position courante.
Le linker dterminera l'adresse des sections. Un rajustage d'adresse aura lieu
durant l'dition des liens.
38
Les directives .global et .extern sont utilises par le compilateur et le linker. Lorsque
le compilateur traite une rfrence (label) suivant la directive .global, il donne la
possibilit au linker de l'utiliser comme rfrence externe, cd qu'un autre code
objet pourra y rfrer.
Respectivement, lorsqu'une instruction fait rfrence un label qui a t dclar
.extern, le compilateur produira une rfrence symbolique correspondant au nom du
label, rfrence qui sera par la suite rsolue par le linker.
39
40
La directive .align permet l'alignement de l'adresse qui suit sur un multiple d'un
certain nombre de bytes. Par exemple, un alignement sur un mot de 32 bits conduira
ce que l'adresse soit un multiple de 4 octets, et en d'autres termes, cela signifie
que les 2 derniers bits soient nuls (en effet, on le voit aisment en incrmentant
l'adresse de 4 depuis la valeur 0).
Sur ARM, un tel alignement sur 4 octets est toujours requis au niveau des
instructions; par exemple. le registre pc (r15) est toujours incrment de 4 octets et,
partant de ce constat, les instructions de saut peuvent encoder une adresse sur un
nombre de bits rduit comme nous le verrons plus tard.
Malheureusement, pour des raisons historiques, l'argument de la directive .align n'a
pas la mme signification sur x86 que sur ARM : sur cette dernire, c'est le nombre
de bits 0 que doit comporter la prochaine adresse, alors que sur x86, il s'agit du
nombre d'octets dont l'adresse doit tre un multiple. L'effet est cependant le mme.
41
42