Stm8 Adressage, Sous-programme et Entrée-sortie

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