CODING ★ Dr.Watson - Autoformation à l'assembleur par Micro Application ★

Dr.Watson - Autoformation à l'assembleur par Micro Application - Chapitre 07

CHAPITRE 7

LA PILE

La Pile est un bloc de mémoire situé à partir de &C000. Elle est utilisée pour le transfert rapide de données, et remplie à partir de &C000, la position libre suivante étant enregistrée par un registre appelé le 'Pointeur de Pile ' (Stack Pointer) ou SP. L'analogie courante est une pile d'assiettes, dont seule l'assiette supérieure est accessible puisqu'elle est la dernière qui a été posée. Mais la pile est remplie en partant du haut, soit à partir de &C000 jusqu'à zéro, donc les assiettes sont mises ou enlevées par le bas, une manière de faire aux antipodes de la logique ! Cette façon de remplir et de vider la plie est appelée 'Last In, First Out ou LIFO (dernier entré, premier sorti). Donc la Pile est une mémoire LIFO.

L'une des fonctions de la pile est d'enregistrer des adresses pendant les appels de sous-programmes que le Z80 fait automatiquement. Quand le Z80 voit une instruction telle que CALL &BBBA, il lui faut d'abord enregistrer l'endroit où se trouve l'instruction suivante dans la routine d'appel (programme principal), de façon à la retrouver après l'exécution du sous-programme. Puis il place le 'BBBA' dans le PC (compteur de programme). Supposez que le Z80 soit prêt à exécuter l'instruction suivante :

CALL &BBBA

Le Z80 accomplit les choses suivantes :

1. Incrémente PC

2. Appelle l'octet de commande (CALL')

3. Incrémente PC

4. Appelle le premier octet de l'opérande (&BA)

5. Incrémente PC

6. Appelle le second octet de l'opérande (&BB)

7. Stocke l'octet fort de PC sur la pile

8. SP = SP-1

9. Stocke l'octet faible de PC sur la pile

10. SP=SP-1

11. Met &BBBA dans PC

12. Exécute le sous-programme. Jusqu'à RET

13. Incrémente PC

14. Appelle l'octet de commande CRET')

15. Charge l'octet faible de PC à partir de la pile

16. SP=SP+1

17. Charge l'octet fort de PC a partir de la Pile

18. SP=SP+1

19. Incrémente PC

20. Continue avec le programme principal

Dans cet exemple, le sous-programme aurait bien pu rencontrer d'autres sous-programmes, des sous-programmes 'imbriqués', et à chaque exécution de CALL l'adresse de retour aurait été empilée sur la pile. Puis, alors que le programme revenait (RET) de ces sous-programmes, les adresses de retour auraient été enlevées successivement pour ramener le Z80 au point initial de départ. La zone de mémoire utilisée pour la pile est supérieure à 256 octets, donc il y a tout à fait assez de place.

Heureusement, l'opération de l'enregistrement des adresses par la pile, lors de l'exécution des sous-programmes, est entièrement automatique et le programmeur peut donc laisser le Z80 faire ce travail. Néanmoins, lors de l'utilisation de sous-programmes incorporés, la plie ne stocke pas automatiquement le contenu des registres mais elle doit être programmée pour le faire, les instructions à cet effet sont :

PUSH et POP

PUSH qq Placer le registre double qq sur la pile

Ici, qq est AF, BC, DE ou HL. PUSH permet aussi de par sa forme le stockage de IX et IY :

PUSH IX Placer le registre IX sur la pile

PUSH IY Placer le registre IY sur la Pile

Ces instructions recopient sur la pile le contenu des registres spécifiés. Après avoir traité le sous-programme ou autre chose, pour restaurer le contenu précédant des registres, on utilise l'Instruction POP :

POP qq Enlever le contenu de registre de la pile

Là aussi qq est AF, BC, DE ou HL.

POP IX Enlever IX de la pile

POP IY Enlever IY de la pile

Que vous utilisiez PUSH ou POP, ce n'est pas la peine de remettre à Jour le pointeur de pile, cela se fait automatiquement.

Lors de la mémorisation de contenus de registres sur la Pile, il est Important de se rappeler que la Pile est une structure LIFO : vous enlèverez normalement les registres dans l'ordre inverse de leur stockage, Et puis, lors de l'écriture d'un programme avec des PUSH et des POP, chaque PUSH doit être assorti d'un POP, sinon l'ordinateur pourrait "être induit en erreur : il pourrait penser par exemple, qu'un nombre de la Pile est une adresse RETour, alors qu'il s'agit du registre double BC qui n'a pas été enlevé. Evidemment, cela conduirait à un 'plantage' du système. Le programme 7.1 est un exemple de l'utilisation correcte de PUSH et POP pour préserver A et HL. Il utilise deux des routines incorporées de l'ordinateur; l'une est la routine de sortie de texte &BB5A déjà bien connue. L'autre est à l'adresse &BB75 et fixe la position du curseur texte (Voir appendice 4 pour plus de détails). Pour l'utiliser, H doit contenir la position colonne et L la position ligne qui sont requises, Notez que &BB75 altère les registres, c'est donc une excellente idée que de les stocker sur la pile !

PROGRAMME 7.1

LD HL,&0604 ;Charge dans H colonne 4 et dans L ligne 6

LD A,&4D ; Charge dans A ASCII de 'M'

PUSH HL ; Recopie HL sur la plie

PUSH AF ; Recopie A sur la plie

CALL &BB75 ; Fixe le curseur en utilisant HL

POP AF ; Rappelle A

CALL &BB5A ; Ecrit 'M' sur le curseur en utilisant A

LD BC,&0101 ;Fixe décalage du curseur dans BC

ADD HL,BC ;Ajoute décalage à HL

PUSH AF ; Sauvegarde AF sur la pile

CALL &BB75 ; Remet à jour la position du curseur (HL)

POP AF ; Rappelle A

CALL &BB5A ; Ecrit 'M' à la nouvelle position du curseur

RET ; Retour au BASIC

Ceci devrait produire deux 'M' dans des positions diagonales consécutives. Deux points sont a noter dans le programme 7.1. Tout d'abord, bien que les choses soient poussées sur la pile, l'information demeure dans les registres appropriés Jusqu'à qu'ils soient changés, puisque PUSH recopie seulement les registres sur la pile; dans le programme ci-dessus, les contenus des registres sont changés ('altérés') de manière imprévisible par l'utilisation de routines incorporées. Néanmoins, il était tout à fait correct de recourir a PUSH AF puis à CALL qui appelait une routine utilisant le contenu du registre A, puisque celui-ci n'avait pas été changé jusqu'ici. Un autre point a noter: bien que seul A devait être préservé, AF devait être poussé sur la pile, puisque PUSH ne fonctionne qu'avec des registres doubles. Il en va de même pour POP.

EXERCICE 7.1

Ecrivez un petit programme pour :

a) fixer le curseur graphique a (0,0)

b) mettre 100 dans DE et 200 dans HL

c) sauvegarder DE et HL sur la pile

d) tracer une ligne jusqu'à (100,200)

e) remettre le curseur graphique à (0,0)

f) retirer DE et HL mais en mettant l'ancien contenu de DE dans HL et vice-

versa

g) tracer une ligne Jusqu'à (200,100)

Indications : voir appendice 4; &BBCO pour fixer le curseur et &BBF6 pour tracer les lignes. Une réponse possible est donnée dans le chapitre solutions.

Si vous avez fait l'exercice ci-dessus, vous avez peut être remarqué dans la solution une façon intéressante de permuter les contenus de DE et HL :

PUSH DE

PUSH HL

.

.

POP DE

POP HL

Les registres sont retirés dans le 'mauvais'ordre.

Il existe une autre manière de permuter le contenu des registres doubles DE et HL :

EX DE,HL Echange (EXchange) le contenu de DE avec HL

Cette instruction ne marche que si elle est écrite comme ci-dessus; c'est à dire que EX HL,DE ou EX BC,HL etc ne marchera pas.

LE POINTEUR DE PILE (SP)

Pour garder trace des éléments à enlever (POP) ensuite, ou pour garder trace de l'endroit où placer l'élément suivant à placer (PUSH) sur la pile, le Z80 utilise un registre spécial appelé le 'POINTEUR DE PILE' ou SP (STACK POINTER). Celui-ci pointe communément à la dernière position dans la pile - soit le dernier octet dans la Pile.

Il existe diverses instructions qui permettent au programmeur d'accéder au pointeur de pile, et de le changer. Lorsqu'on les utilise, il est possible de créer une 'pile utilisateur'. Après avoir ajusté SP pour qu'il pointe sur une nouvelle adresse mémoire, le Z80 utilisera la nouvelle adresse comme départ d'une nouvelle pile, ignorant totalement l'ancienne. Par conséquent, si une nouvelle pile est créée dans un sous-programme, il est important de préserver toutes les adresses RETour en les plaçant (PUSH) sur la nouvelle pile.

Trois instructions LD peuvent être utilisées pour altérer SP :

LD SP,HL Charge dans SP le contenu de HL LD SP,IX

Charge dans SP le contenu de IX LD SP,IY

Charge dans SP le contenu de IY

Pour trouver la valeur actuelle de SP, on utilise l'instruction suivante:

LD (nn),dd Charge dans la case mémoire nn le contenu du registre double dd

dd est soit BC, DE, HL ou, dans le cas présent, SP.

Simplement pour vous prouver que la création de votre pile fonctionnera, essayez le programme suivant :

PROGRAMME 7.2

LD A,43 ; Met '+' dans A

PUSH AF ; Stocke A dans la pile actuelle

CALL &BB5A ; Met '+' sur l'écran

LD (&714A),SP ; Se rappelle de la valeur actuelle de SP

LD HLS7148 ; Se prépare pour :

LD SP,HL ; Créer la nouvelle pile en 87148

LD A,61 ; Met '=' dans A

PUSH AF ; Stocke A dans la nouvelle plie

CALL &BB5A ; Met '=' sur l'écran

LD HL,(&714A) ; Trouve position initiale de SP

LD SP,HL ; Revient à la pile initiale

POP AF ; Enlève '+'

CALL &BB5A ; Met '+' sur l'écran

RET

Le programme 7.2 mettra '+=+' sur l'écran. Si le pointeur de pile n'avait pas été amené à une nouvelle position/ alors POP AF aurait enlevé '=' a la place, et l'écran aurait affiché '+=='. Pour prouver qu'il y a une nouvelle pile en &7148, essayez ce petit exercice !

EXERCICE 7.2

Prolonger le programme ci-dessus afin qu'il enlève le '=' et l'affiche puis remette SP là ou il était pour enlever et afficher à nouveau un autre '+', l'écran devrait alors afficher '+=+=+'.

Indications : Rappelez-vous que SP doit pointer sur la dernière position dans la pile, par conséquent l'amener à &7148 ne marchera pas. Utilisez 87146.

Une solution est donnée au chapitre solutions.

Pour conclure ce chapitre, il faut mentionner les autres commandes qui agissent sur la Pile. Celles-ci permettent au programmeur avancé et 'prudent' de manipuler le contenu de la pile sans utiliser chaque fois PUSH ou POP pour que le SP pointe a l'élément souhaité dans la pile.

Tout d'abord, il existe trois autres instructions d'échange (EXchange) :

EX (SP),HL Echange le contenu de HL avec le dessus de la plie. EX (SP),IX Echange le contenu de IX avec le dessus de la pile EX (SP),IY Echange le contenu de IY avec le dessus de la plie.

Les autres instructions qui peuvent agir sur SP sont :

INC ss ; INcrémente le registre double ss

DEC ss ; DECrémente le registre double ss

ss est BC, DE, HL ou SP.

ADD IX,pp ;Ajoute le contenu du registre double PP à IX

Ici PP est BC, DE, IX ou SP.

ADD IY,rr Ajoute le contenu du registre double rr à IY

Ici rr est BC, DE, IY, ou SP.

RESUME

Après avoir lu ce chapitre, vous devez connaître ceci :

LIFO EX DE,HL

SP Quelle partie de la pile SP pointe-t-il

PUSH Pile utilisateur

POP LD (nn),dd

EX (SP),HL

★ ANNÉES: 1985
★ AUTEUR: T. Hebertson
★ CONVERTION: CRACKERS VELUS

Page précédente : Dr.Watson - Autoformation à l'assembleur par Micro Application - Chapitre 06
 
Je participe au site:

» Vous avez remarqué une erreur dans ce texte ?
» Aidez-nous à améliorer cette page : en nous contactant via le forum ou par email.

CPCrulez[Content Management System] v8.7-desktop/c
Page créée en 637 millisecondes et consultée 1506 fois

L'Amstrad CPC est une machine 8 bits à base d'un Z80 à 4MHz. Le premier de la gamme fut le CPC 464 en 1984, équipé d'un lecteur de cassettes intégré il se plaçait en concurrent  du Commodore C64 beaucoup plus compliqué à utiliser et plus cher. Ce fut un réel succès et sorti cette même années le CPC 664 équipé d'un lecteur de disquettes trois pouces intégré. Sa vie fut de courte durée puisqu'en 1985 il fut remplacé par le CPC 6128 qui était plus compact, plus soigné et surtout qui avait 128Ko de RAM au lieu de 64Ko.