ZuperIndex
ZINDEX
ZuperIndex
ZDICO
ZuperIndex
ZUPERINDEX
Pile Fonction TI-92 Introduction
Fonction TI-92 Exercice résolu 1
Fonction TI-92 Exercice résolu 2
Fonction TI-92 Exercice résolu 3
Fonction TI-92 Exercice résolu 4
Fonction TI-92 Exercice résolu 5 Barre

Page précédente

Monter Descendre Retour Introduction

puce Cette partie explique comment utiliser la pile, un espace mémoire présent dans les TI, où l'on peut sauvegarder des valeurs.

Il existe deux piles, nous étudierons seulement la pile utilisateur car je ne connais pas la pile de supervision (utilisée par le système d'exploitation) que, de toute façon, nous n'utiliserons pas.
Nous utiliserons le terme générique pile pour désigner la pile utilisateur.

puce La pile, d'une taille de 16 Ko (16384 octets), commence à l'adresse $000120 et fini à l'adresse $004120.

Attention il y a un point crucial à retenir, le départ de la pile est l'adresse $004120 et sa fin l'adresse $000120 !
La pile s'utilise donc à l'envers, nous y reviendrons plus tard avec un exemple concret.

Les valeurs que nous pouvons mettre dans cette pile peuvent être de toutes natures, entre autres des variables locales, paramètres, registres sauvegardés, adresses, structures…), à condition de s'y retrouver et surtout de respecter les valeurs d'autrui !

En effet tout le monde utilise la pile y compris le processeur, ainsi un programme appelant un sous-programme ne souhaite pas voir des valeurs personnelles altérées par ce dernier, sous peine de perdre les pédales voire provoquer un plantage.

puce puce Pour comprendre le fonctionnement de la pile, prenons un exemple facile.

Nous avons devant nous une table symbolisant le départ de la pile et à notre droite dix assiettes numérotées de 1 à 10.

Empilons maintenant ces assiettes dans l'ordre croissant, soit 1,2,3,4,5,6,7,8,9 puis 10.

Si nous voulons les remettre à leur place initiale, nous constatons que c'est l'assiette empilée en dernière qui doit être dépilée en première, c'est donc une structure LIFO (Last In, First Out) et ainsi de suite : 9,8,7,6,5,4,3, 2 puis 1.

puce C'est exactement la même chose pour la pile, sauf qu'au lieu d'empiler les valeurs vers le haut nous les empilerons vers le bas (la pile s'utilise à l'envers comme nous l'avons souligné au départ).

Par conséquent, pour empiler une valeur sur la pile nous décrémenterons son pointeur avec le mode d'adressage -(An), puis pour dépiler cette valeur nous incrémenterons le pointeur avec le mode d'adressage (An)+.

puce Pour accéder aux données empilées sur la pile il faut un pointeur (adresse) pointant la dernière valeur empilée.

Dans l'absolu nous pourrions utiliser n'importe quel registre d'adresse comme pointeur de pile, mais le choix de Texas Instrument s'est porté sur le registre d'adresse A7.
Il serait catastrophique de vouloir en changer car les fonctions en ROM l'utilisent !

Vous pouvez utiliser la désignation SP (Stack Pointer) au lieu d'A7 dans vos codes source, attention SP n'est pas un registre mais une manière équivalente de nommer le registre A7.

Lorsque la pile est vide ce pointeur pointe juste avant celle-ci car le mode d'adressage -(An) décrémente d'abord le registre avant d'enregistrer la valeur.

puce Dernier élément à connaître impérativement, l'adresse du pointeur de pile est toujours paire.
Il est impossible d'empiler un octet, le compilateur vous le fera savoir :o)

Tout ceci pour ne pas empiler ou dépiler un mot ou double mot à une adresse impaire (ce qui est impossible et provoque l'interruption d'anomalie ADRESS ERROR).

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 empilerons à 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


Barre



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 empiler 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.


Barre



Monter Descendre Retour Exercice résolu 2

puce Il est long de empiler 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 empiler 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, D1, D2 et A0 changent)
MOVEM D0-D2/A0,-(A7) ; on sort D0, D1, D2 et A0


Barre



Monter Descendre Retour Exercice résolu 3

puce Une fonction d'une bibliothèque utilise un ou plusieurs paramètre, nous allons nous intéresser ici à la fonction SetFontSys de la bibliothèque TIOS qui est très simple d'utilisation.
puce Le problème c'est que lors du 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 restaurons pas la pile après l'appel à la fonction, celle-ci sera éronnée (les valeurs précédentes ne sont plus valides)... et à moins d'un miracle votre calculatrice plantera !

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.b #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 avec la pile)

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.


Barre



Monter Descendre Retour Exercice résolu 4

puce On veut utiliser une chaîne de caractère et il nous faut empiler l'adresse du premier octet (caractère).
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)


Barre



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 empiler à 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.


Barre



 

 

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

Zguide © 1998 - 1999 par Florian DREVET. Tous droits réservés