PILE Fonction Introduction
Fonction Exercice résolu 1
Fonction Exercice résolu 2
Fonction Exercice résolu 3
Fonction Exercice résolu 4
Fonction Exercice résolu 5

Page précédente



 

Monter Descendre Retour Introduction
puce Cette partie explique comment utiliser la pile, un espace mémoire où l'on peut sauvegarder des valeurs. Celles-ci peuvent être entre autre des paramètres destinées à des fonctions de bibliothèques, des registres de façon à les retrouver intactes après plusieurs instructions, une adresse (pointeur) lors d'un saut à un sous-programme pour revenir au programme principal...

puce Les modes d'adressages utilisés sont -(An) et (An)+, dans le cas de la pile il faudra écrire par la suite -(A7) et (A7)+ ou encore -(SP) et (SP)+.

puce Pour comprendre le fonctionnement de la pile, prenons un exemple facile :
Nous avons dix assiettes numérotées de 1 à 10, nous les empilons dans l'ordre croissant : 1,2,3,4,5,6,7,8,9 et 10.
Maintenant nous constatons que c'est l'assiette déposée en dernière qui doit être reprise en première (méthode LIFO : Last In, First Out) et ainsi de suite : 10,9,8,7,6,5,4,3,2 et 1.

puce C'est exactement la même chose pour la pile sauf que au lieu d'empiler les valeurs vers le haut, nous les empilerons vers le bas (simplement pour avoir des adresses croissantes pour pouvoir retirer des double mots de la pile). Par conséquent pour déposer une valeur sur la pile nous décrémenterons celle-ci avec le mode d'adressage -(An), puis pour sortir cette valeur nous incrémenterons la pile avec le mode d'adressage (An)+.

puce Pour accéder aux données déposées sur la pile il faut un pointeur (adresse) qui pointe sur la dernière valeur déposée, sachez aussi que lorsque la pile est vide ce pointeur pointe juste avant la pile.
puce Dans l'absolu, nous pourrions utiliser n'importe quel registre d'adresse (An) comme pile mais le pointeur de pile utilisé par les fonctions en ROM est A7 (appelé aussi SP) et il serait catastrophique de vouloir en changer.
puce Tous les exemples seront écrits avec A7 et non SP, ensuite faites comme bon vous semble car cela n'a pas d'importance.

puce Voici un bref exemple avec une pile de 100 octets (ce qui est faux dans la réalité), supposons que celle-ci est vide :
A7100
98vide
96vide
94vide
92vide
90vide
...vide
0vide

puce Puis supposons que nous déposons un double mot puis un mot sur la pile. Le pointeur de pile A7 pointe sur la dernière valeur car pour désempiler une valeur on utilise la post-incrémentation (la valeur est sortie puis le pointeur de pile A7 est incrémenté) :
100
98Première valeur déposée (double mot)
96
A794Deuxième valeur déposée (mot)
92vide
90vide
...vide
0vide

puce Enfin, supposons que nous désempilons la dernière valeur déposée. Le pointeur de pile A7 pointe toujours sur la dernière valeur et vous remarquez que la valeur désempilée n'a pas été initialisée (ce qui est inutile car celle-ci sera écrasée lorsque nous déposerons à nouveau des valeurs) :
100
98Première valeur déposée (double mot)
A796
94Deuxième valeur déposée (mot)
92vide
90vide
...vide
0vide

puce Lors de la création de vos programmes, je vous conseille de vous faire un tableau de ce type en notant précisemment quelles valeurs sont actuellement dans la pile, c'est à dire les votres et celles par certaines instructions :
100
98Registre PC déposé automatiquement par l'instruction BSR (double mot)
96
A794Registre D3 (premier mot)
92vide
90vide
...vide
0vide

puce Attention, l'adresse de la pile (donc du registre A7 ou SP) sera toujours paire, par conséquent si vous déposez sur la pile un octet, celle-ci sera décrémentée d'un mot (2 octets).
Ceci est particulier au registre de pile, évidemment si vous avez décidé d'outre passer ce standard il vous faudra faire face a cette éventualité par vous même...
La raison est simple : l'adresse d'un mot ou d'un double mot doit être toujours paire, au cas où vous déposeriez un octet puis un mot (ou un double mot), le résultat serait un plantage (ADDRESS ERROR).

puce Enfin, je vous déconseille de modifier les valeurs contenues dans la pile si vous n'êtes pas sûr de ce qu'elles contiennent, en effet si vous modifiez une adresse importante vous risquez tout simplement de provoquer un plantage (ADDRESS ERROR si l'adresse est impaire ou ILLEGAL INSTRUCTION si l'adresse est bonne mais le code lut est erroné...).





 

Monter Descendre Retour Exercice résolu 1
puce On utilise les registres D0, D1, D2 et A0 dont les valeurs nous intéresse, mais une bibliothèque que nous appelons modifie ces registres à des fins personnelles.
puce Nous allons donc perdre ces valeurs.

SOLUTION :
puce Déposer les registres sur la pile (les sauvegarder), utiliser la bibliothèque, puis sortir les valeurs la pile qui sont restées inchangées.

PROGRAMMATION :
MOVE.w D0,-(A7) ; on dépose D0 dans la pile
MOVE.w D1,-(A7) ; on dépose D1 dans la pile
MOVE.w D2,-(A7) ; on dépose D2 dans la pile
MOVE.l A0,-(A7) ; on dépose A0 dans la pile
JSR xlib::xfonction ; on appel une bibliothèque (D0, D1, D2 et A0 changent)
MOVE.l (A7)+,A0 ; on sort la valeur de A0
MOVE.w (A7)+,D2 ; on sort la valeur de D2
MOVE.w (A7)+,D1 ; on sort la valeur de D1
MOVE.w (A7)+,D0 ; on sort la valeur de D0

AVANTAGES / UTILISATION :
puce On n'utilise pas de variables temporaires pour sauvegarder les valeurs de D0 et D2, ce qui augmente un peu sa vitesse et réduit un peu la taille du programme.





 

Monter Descendre Retour Exercice résolu 2
puce Il est long de déposer les registres un par un sur la pile.
puce Ici nous n'en avons que quatre mais imaginez un peu le cas avec une dizaine ou plus !

SOLUTION :
puce On utilise l'instruction MOVEM (une variante de MOVE) qui est très intéressante car elle permet, en une ligne de code, de déposer autant de registre que l'on souhaite.
puce Reprenons notre programme ci-dessus et raccourcissons le un peu.

PROGRAMMATION :
MOVEM D0-D2/A0,-(A7) ; on dépose D0, D1, D2 et A0 sur la pile
JSR xlib::xfonction ; on appel une bibliothèque (D0, D2 et A0 changent)
MOVEM D0-D2/A0,-(A7) ; on sort D0, D1, D2 et A0





 

Monter Descendre Retour Exercice résolu 3
puce Une fonction d'une bibliothèque utilise un registre de donnée (par exemple D1) comme paramètre, nous allons nous intéresser ici à la fonction SetFontSys de la bibliothèque TIOS qui est très simple d'utilisation.
puce La valeur de D1 ne nous étant pas nécessaire, nous décidons de ne pas la reprendre. Le problème c'est qu'avant le saut vers la fonction, l'adresse de la prochaine instruction à exécuter (registre PC) est déposée sur la pile pour revenir à notre programme et si nous ne reprenons pas la valeur de D1 elle sera considéré comme l'adresse précédemment déposée... à moins d'un miracle votre calculatrice plante !

SOLUTION :
puce Il faut donc simuler par nous même la sortie des valeurs déposé (ici D1) en incrémentant l'adresse de la pile de la taille de la somme des valeurs que nous avons déposées.

PROGRAMMATION :
MOVE.w #0,-(A7) ; paramètre de la hauteur de police (petite)
JSR tios::FontSetSys ; lance la fonction
ADD #2,A7 ; on restaure la pile de 2 (mot)

AVANTAGES / UTILISATION :
puce On incrémente le pointeur de la pile de 2 (mot) car nous avons déposé un mot sur la pile. Maintenant l'adresse de la prochaine instruction a exécuter est la valeur qui sera sorti la prochaine fois.
puce Vous pouvez tout à fait utiliser l'instruction LEA pour incrémenter le pointeur de la pile, le résultat est le même, voilà ce que ça donne pour notre exemple :
lea 2(A7),A7 ; on restaure la pile de 2 (mot)
puce Si vous ne connaissez pas encore cette instruction, sachez qu'elle charge une adresse dans un registre d'adresse, ici nous utilisons le mode d'adressage x(An), nous chargeons l'adresse de A7+2 dans A7 donc nous avons bien incrémenté A7 de 2.





 

Monter Descendre Retour Exercice résolu 4
puce On veut utiliser une chaîne de caractère et il nous faut déposer l'adresse du premier octet (caractère) sur la pile.
puce On prend ici comme exemple la variable bonjour dc.b "bonjour monde",0

SOLUTION :
puce Nous allons utiliser l'instruction PEA qui effectue exactement le même travaille que l'instruction LEA mais au lieu de charger l'adresse dans un registre d'adresse elle le dépose sur la pile.
puce Il faudra là aussi restaurer la pile pour éviter le plantage, le petit piège c'est que l'adresse (pointeur) de la chaîne de caractère déposée sur la pile est un double mot (4 octets) car un pointeur est toujours définie sur 32 bits.

PROGRAMMATION :
MOVE.w #4,-(A7) ; on dépose la couleur
PEA bonjour(PC) ; on dépose le pointeur de la variable bonjour
MOVE.w #0,-(A7) ; on dépose l'ordonnée
MOVE.w #0,-(A7) ; on dépose l'abscisse
JSR tios::DrawStrXY ; on lance la fonction
LEA 10(A7),A7 ; on restaure la pile de 2+4+2+2=10

AVANTAGES / UTILISATION :
puce Nous avons pu expliquer les pièges de l'instruction PEA qui dépose sur la pile un pointeur et doit être utilisé avec le registre PC (Program Counter).
puce Notez que l'instruction
PEA bonjour(PC)
est équivalente, par exemple, aux instructions
LEA bonjour(PC),A0
MOVE.l A0,-(A7)





 

Monter Retour Exercice résolu 5
puce Nous voulons un sous-programme qui puissent agir avec des paramètres passés par la pile, malheureusement le pointeur vers la prochaine instruction est déposé sur la pile lors du saut. Nous ne pouvons pas utiliser nos paramètres car c'est ce pointeur qui va être sorti en premier.
puce Nous somme là dans un cas où le risque de plantage est élevé.

SOLUTION :
puce Il nous faut a tout prix garder la valeur du pointeur intacte pour retourner au programme, il y a plusieurs façons d'opérer, je propose de le sortir dans un registre d'adresse puis de le déposer à nouveau sur la pile à la fin, ainsi l'instruction RTS sortira bel et bien le pointeur voulu.

PROGRAMMATION :
; le code suivant est à mettre dans le programme
MOVE.w #4,-(A7) ; on dépose un paramètre
MOVE.l #4,-(A7) ; on dépose un autre paramètre
JSR SousProg ; on saute au sous-programme

; le code suivant est le sous-programme
SousProg : ; label du départ du sous-programme
MOVE.l (A7)+,A0 ; on sort le pointeur de retour dans A0
; les paramètres sont accessibles
MOVE.l (A7)+,D0 ; on sort le dernier paramètre dans le registre D0
MOVE.w (A7)+,D1 ; on sort le premier paramètre dans le registre D1
; les paramètres sont accessibles
MULU D1,D0 ; on peut par exemple effectuer une multiplication
; les paramètres sont accessibles
LEA 6(A7),A7 ; on restaure la pile de 4+2=6
MOVE.l A0,-(A7) ; on dépose à nouveau le pointeur de retour
RTS ; on revient au programme

AVANTAGES / UTILISATION :
puce Nous pouvons donc simuler une macro avec des paramètres, c'est un peu plus lent et surtout plus compliqué mais on peut économiser beaucoup de mémoire ainsi.





 

 

Lisez la section sur les droits d'auteur et la license d'utilisation avant de distribuer Zguide.

Zguide © 1998, Florian DREVET. Tous droits réservés à l'échelle mondiale