Stm8 Adressage, Sous-programme et Entrée-sortie
Pile
18/09/2019
Les modes d'adressage
La puissance d'un processeur est liée à sa capacité de traitement ( largeur du bus de données, vitesse d'horloge, taille de la mémoire, entrées-sorties, ...), mais aussi aux instructions qu'il met en œuvre et à la facilité d’accès à tous les éléments de la mémoire par chaque instruction.
Cette facilité d’accès est caractérisée par les modes d'adressage à un élément en mémoire, ou comment une instruction peut accéder à une information en mémoire.
On rappelle qu'une instruction effectue une opération sur des données et valorise des données; Une instruction attend en entrée zéro, une ou deux opérandes.
- L'opération fictive Nop n'a pas d'opérande en entrée, ni en sortie
- L'incrémentation d'un registre a un opérande d'entrée (le registre) et un opérande de sortie (ce même registre)
- Une addition aura deux opérandes d'entrée ( A et B ) et une opérande en sortie ( C )
Pour simplifier l'architecture d'un processeur, on peut prendre des conventions particulières.
Pour le Stm8 la convention est que (sauf exception) un des opérandes d'entrée et l'opérande de sortie sont l'accumulateur. Le mode d'adressage qui est explicité dans l'instruction et le code d'instruction ne concerne (sauf exception) que le deuxième opérande d'entrée, il exprime la manière avec laquelle le processeur va acquérir cette information à partir des ressources dont il dispose.
On définit classiquement les modes d'adressage suivant:
| Mode | Exemple | Description |
|---|---|---|
| Immédiat | LD A,#$08 | La donnée suit le code instruction, l’accès se fait donc à partir du compteur ordinal |
| Direct | Add A,$09 | L'adresse de la donnée suit le code instruction, l’accès se fait directement dans la mémoire |
| Indirect | Add A,[$01F8] | L'adresse de la donnée est dans la mémoire à une adresse passée en paramètre derrière le code d'instruction |
| Indexé | Add A,(X) | L'adresse de la donnée est dans un registre d'index (X), l’accès se fait à partir d'un registre |
| Implicite | RTN | L'instruction n'a pas besoin de préciser d'opérande |
Ces modes d'adressage peuvent être adaptés à différentes parties de la mémoire afin d'accélérer les traitements. Le Stm8 définit trois plages d'adressage différentes en fonction de la taille de l'adresse.
| Plage d'adressage | Taille de l'adresse en octet | Espace d'adressage |
|---|---|---|
| Court (Short) | 1 | $0 - $ff |
| Long | 2 | $0 - $ffff |
| Étendu (Extended) | 3 | $0 - $ffffff |
Donc on pourra avoir un LD A,$08, un LD A,$01F8 et LDF A,$123456.
Ces modes d'assemblage peuvent être améliorés afin de faciliter la programmation, toutes les combinaisons ne sont pas disponibles, seules celles ayant un réel intérêt sont disponibles dans le jeu d'instruction d'un processeur donné.
- Absolu ou relatif: l'adressage absolu indique que l'adresse est basé sur une adresse absolue dans la mémoire (par exemple le saut lointain (JMPF)), l'adressage relatif va préciser un déplacement relatif par rapport à quelque-chose ( saut conditionnel proche (JRNE label) attend un déplacement par rapport au CO ( entre -127 et + 127)).
- Base plus index: l'adresse passée en paramètre est augmentée de la valeur contenue dans l'index avant de charger le bus d'adresse (cf.R.A.M).
- Incrémenté: on peut profiter de l'exécution d'une instruction pour faire en parallèle une opération très courante en temps masqué; un adressage indexé avec incrémentation va incrémenter le registre d'index précisé pendant l'instruction. Les instructions disponibles et leurs modes d'adressage sont décrites dans les notes techniques des constructeurs (cf. PM0044 de chez STMicroelectronics). =Les sous-programmes= Dés l'origine, on a constaté que certains traitements étaient toujours les mêmes avec des paramètres différents. On a donc intérêt à les écrire une fois et à les réutiliser à partir de plusieurs endroits. C'est une partie du programme, c'est ce que l'on appelle un sous-programme et là où on l'utilise c'est l'appel d'un sous-programme. Tous les processeurs implémente la possibilité d'exécuter des sous-programmes et de revenir au programme appelant après l'exécution de celui-ci.
Le principe est de ranger quelque-part "ce qui caractérise l'exécution d'un programme à un instant T", de placer le CO sur l'adresse de début du sous-programme et à la fin de l’exécution du sous-programme de rétablir "ce qui caractérise l'exécution d'un programme" avant qu'il ait appelé le sous-programme.
Le "ce qui caractérise l'exécution d'un programme à un instant T" est appelé le contexte d'exécution. Ce contexte est rangé dans une partie de la mémoire dédiée à cet effet, et comme un sous-programmes peut appeler lui-même un sous-programme et que l'on ne doit pas écraser ces contextes on les empile les uns au dessus des autres à l'appel du sous-programme et on les dépile au retour des sous-programmes. Cette partie de la mémoire est la pile d'exécution.
On a pris l'habitude de ranger les données du programme en adresse basse de la mémoire vive et la pile d'exécution en haut de la mémoire parce que au cours de l'exécution d'un programme on peut réclamer de la place pour de nouvelles données ( on consomme en montant) et en choisissant de faire croître la pile vers le bas, on garde la réserve de mémoire disponible (le tas)utilisable par l'un ou par l'autre.
Sur les Stm8 le contexte d'exécution se limite au seul compteur ordinal. Ce compteur ordinal est poussé sur la pile lors de l'appel du sous-programme (instruction CALL) et retirer de la pile lors du retour du sous-programme (instruction RTN).
Exemple de code
Adresse Assembleur Code machine 8000 LD A,$04 B6 04 8002 CALLF $008106 8D 00 81 06 Appel du sous-programme 8006 LD $05,A B7 05 ... 8106 LD A,$08 B6 08 Début du sous-programme 8108 INC A 4C 8109 LD $08,A B7 08 810B RETF 87 Retour du sous programme
Séquence d'exécution
CO A SP Pile de 7F8 à 7FF Mémoire de 00 à 08 8000 .. 7FF .. .. .. .. .. .. .. [..] .. .. .. .. 30 .. .. .. 40 8002 30 7FF .. .. .. .. .. .. .. [..] .. .. .. .. 30 .. .. .. 40 8106 30 7FC .. .. .. .. [..] 00 80 06 .. .. .. .. 30 .. .. .. 40 8108 40 7FC .. .. .. .. [..] 00 80 06 .. .. .. .. 30 .. .. .. 40 8109 41 7FC .. .. .. .. [..] 00 80 06 .. .. .. .. 30 .. .. .. 40 810B 41 7FC .. .. .. .. [..] 00 80 06 .. .. .. .. 30 .. .. .. 41 8006 41 7FF .. .. .. .. .. 00 80 [06] .. .. .. .. 30 .. .. .. 41 8008 41 7FF .. .. .. .. .. 00 80 [06] .. .. .. .. 30 41 .. .. 41
La case mémoire pointée par le pointeur de pile (SP) est marquée par des crochets droits
On se rend compte que lors de l'appel du sous-programme $8106 la valeur de l'accumulateur a été modifié et donc peut influencer l'exécution du programme appelant; cela s’appelle un effet de bord; les effets de bord sont une source permanente de bugs.
Pour corriger ce problème on a deux possibilités:
- on sauvegarde l'accumulateur (et tout ce que l'on utilisera après l'appel du sous-programme) avant l'appel et on le restaure après le retour dans le programme appelant
- on sauvegarde l'accumulateur (et tout ce que l'on modifiera pendant l'exécution du sous-programme) au début du sous-programme et on le restaure avant de retourner du sous-programme
Les deux stratégies sont appliquées couramment dans les compilateurs.
Dans le cas de la sauvegarde dans le sous-programme on peut tirer partie de l'adressage indexé sur le pointeur de pile pour y sauvegarder la valeur de l'accumulateur.
====Exemple de sous-programme avec sauvegarde de l'accumulateur====
Adresse Assembleur Code instruction 8000 LD A,$04 B6 04 8002 CALLF $008106 8D 00 81 06 Appel du sous-programme 8006 LD $05,A B7 05 ... 8106 LD ($0,SP),A 6B 00 Début du sous-programme, sauvegarde 8108 LD A,$08 B6 08 810A INC A 4C 810B LD $08,A B7 08 810D LD A,($0,SP) 7B 00 On recharge l'accumulateur avec la valeur sauvegardée 810F RETF 87 Retour du sous programme
====Séquence d'exécution avec sauvegarde de l'accumulateur====CO A SP Pile de 7F8 à 7FF Mémoire de 00 à 08 8000 ... 7FF .. .. .. .. .. .. .. [..] .. .. .. .. 30 .. .. .. 40 8002 30 7FF .. .. .. .. .. .. .. [..] .. .. .. .. 30 .. .. .. 40 8106 30 7FC .. .. .. .. [..] 00 80 06 .. .. .. .. 30 .. .. .. 40 8108 30 7FC .. .. .. .. [30] 00 80 06 .. .. .. .. 30 .. .. .. 40 810A 40 7FC .. .. .. .. [30] 00 80 06 .. .. .. .. 30 .. .. .. 40 810B 41 7FC .. .. .. .. [30] 00 80 06 .. .. .. .. 30 .. .. .. 40 810D 41 7FC .. .. .. .. [30] 00 80 06 .. .. .. .. 30 .. .. .. 41 810F 30 7FC .. .. .. .. [30] 00 80 06 .. .. .. .. 30 .. .. .. 41 8006 30 7FF .. .. .. .. 30 00 80 [06] .. .. .. .. 30 .. .. .. 41 8008 30 7FF .. .. .. .. 30 00 80 [06] .. .. .. .. 30 30 .. .. 41
On remarque que la valeurs stockée à l'adresse $05 est bien $30 et non $41 comme dans la séquence précédente. =Les interruptions= Une interruption est un mécanisme qui permet lors de la survenue d'un événement de faire exécuter immédiatement un traitement particulier. L'événement est généralement provoqué par un signal extérieur (détection de choc, temporisation dépassée, ...); quand il se produit le processeur suspend l'exécution du programme en cours, exécute d'une routine d'interruption (une sorte de sous-programme), et à la fin de l'exécution de celle-ci reprend l'exécution du programme à l'instruction où il avait été interrompu.
Lorsque l'interruption est déclenchée le processeur sauvegarde sur la pile:
- le compteur ordinal ( PCL, PCH, PCE)
- les index ( Y , X)
- l'accumulateur (A)
- et le registre de contrôle (CC)
A la fin de l'exécution de l'interruption (instruction IRET), ces registres sont dépilés et l'exécution peut reprendre là où elle avait été interrompu.
Les entrées-sorties
Tout processeur doit échanger avec le monde extérieur, un ordinateur aura au moins un clavier et un écran. Un micro-contrôleur aura par exemple les entrées-sorties suivantes:
| Types d'entrées-sorties | Exemples d'application |
|---|---|
| Liaison série | pour communiquer avec un terminal |
| Convertisseur analogique-digitale | pour mesurer des grandeurs physiques comme la température |
| Des entrées logiques | pour détecter le passage d'un élément devant un capteur |
| Des sorties logiques | pour commander la mise en marche d'un moteur |
| Des sorties analogiques | pour commander en proportion l'ouverture d'un volet |
| Des sorties modulées par largeur d'impulsion | pour commander un servo-moteur en PWM |
| Liaisons numériques entre composants | pour acquérir une température avec un bus I2C |
et aussi d'un composant capable de mesurer le temps, le temporisateur.
Ces entrées-sorties sont des circuits électroniques spécialisés implantés directement sur le circuit intégré du micro-contrôleur ou dans un composant relié par un bus au micro-contrôleur.
Vue du processeur, ces entrées-sorties sont des registres qui sont valorisés pour paramétrer le fonctionnement du circuit électronique, des registres qui sont utilisés pour obtenir l'information attendue ( La valeur associée à la tension lue en entrée) et enfin un ou plusieurs signaux susceptibles de déclencher une interruption du processeur.
Les entrées-sorties projetées en mémoire
Pour accéder à ces registres on a plusieurs possibilités:
- on peut utiliser des instructions spécifiques du processeur semblables aux instructions portant sur les registres du cœur ( INC X),
- on peut réserver un certain nombre d'adresses de l'espace mémoire pour accéder à ces registres. La seconde solution est beaucoup plus flexible, puisqu'elle permet de s'adapter en nombre et en type sans avoir à modifier le cœur du processeur; c'est ce que l'on appelle des entrées-sorties projetées en mémoire, les registres sont accédés avec les instructions d’accès mémoire sur l'adresse qui leurs est réservé. Par exemple sur le STM8S105 le registre de contrôle du Timer 1 est à l'adresse 0x00 5250