application particulière : adressage relatif-PC pour une donnée en ROM
Dans le cas d'un code relogeable, ni l'adresse associée à un label ni celle de l'instruction courante ne sont connues au moment de l'assemblage,
mais la différence l'est, l'assembleur peut donc calculer un déplacement à additionner au contenu du registre PC pour accéder à la donnée :
labul dcd 0x0561559513
...
LDR r0, labul ; copie dans r0 la variable labul stockée en ROM
Le code produit sera équivalent à :
LDR r0, [PC, #(labul-.-K)] ; . = adresse instr. courante, K = constante (2 ou 4)
La valeur de K dépend de l'alignement.
Cette technique est utilisée pour le litteral pool (macro LDR avec sign '=', voir ci-dessus)
Load/Store Multiples (par dérogation au style RISC)
Attention : la syntaxe de ces instructions n'est pas cohérente avec le reste du jeu d'instructions.
LDM r7, {r0, r1, r2, r4} ; charger les registres de la liste avec les valeurs lues en mémoire,
à partir de l'adresse de base donnée par r7
LDM r7!, {r0, r1, r2, r4} ; idem, puis mettre a jour r7
STM r7, {r0, r1, r2, r4} ; stocker le contenu des registres de la liste en mémoire,
à partir de l'adresse de base donnée par r7
STM r7!, {r0, r1, r2, r4} ; idem, puis mettre a jour r7
Ces instructions acceptent les suffixes DB (Decrement Before) et IA (Increment After), qui est le choix par défaut.
La liste de registres entres accolades '{' et '}' peut contenir 1 à 15 registres (tous sauf SP).
Attention : l'ordre des registres stockés ou lus en mémoire par une instruction multiple est toujours tel que les adresses mémoire croissent dans
le sens des indices des registres (c'est indépendant de l'ordre des éléments de la liste, qui est ignoré).
Push et Pop
L'empilage (Push) et le dépilage (Pop) sont des applications de Store Multiple et Load Multiple avec SP et '!'
PUSH {r1, r2} ; empiler r1 et r2 (r2 en premier, c'est a dire à l'adresse max)
STMDB SP!, {r1, r2} ; idem, DB choisi pour "full descending stack"
POP {r1, r2} ; dépiler r1 et r2 (r2 en dernier, c'est a dire de l'adresse max)
LDM SP!, {r1, r2} ; idem, IA choisi pour "full descending stack"
Le dépilage de PC est équivalent à un saut indirect utilisant une valeur prise dans la pile, ce qui peut tenir lieu de retour de sous-programme à
condition d'avoir empilé LR en début de sous-programme. On peut en profiter pour empiler quelques registres :
PUSH {r4, r5, r6, LR} ; au début du sous-programme
...
...
POP {r4, r5, r6, PC} ; retour du sous-programme
2.7 Instruction de saut : "Branch"
B unlabel ; un saut direct (codé en relatif)
Bcc unlabel ; saut conditionnel, cc est une condition parmi les 14 possibles (voir suffixes ci-dessus)
BL unlabel ; appel de sous programme (adresse retour copiée dans LR)
BX r3 ; saut indirect par registre (par exemple r3)
BX LR ; retour de sous programme simple
BLX r3 ; appel de sous programme indirect par registre (adr retour dans LR)
Notes :
Historiquement, le X est pour "exchange" car BX et BLX permettent de changer de jeu d'instruction. En Thumb-2 il n'est pas question de cela,
on peut considérer que le X signifie simplement indirect par registre.
Contrairement à la majorité des autres architectures, l'ARM n'a pas d'intruction de retour de sous programme, le retour se fait avec BX LR si
l'adresse de retour est dans LR, ou POP {PC] si elle est dans le pile.
Contrairement à la majorité des autres architectures, l'ARM n'a pas d'intruction de retour d'interruption, le retour d'interruption se fait comme un
retour de sous-programme ordinaire, c'est dans l'adresse de retour qu'il y a un code spécifique pour appliquer le traitement approprié aux
interruptions.