Pure Pascal en interne : Conventions d'appel
Les conventions d'appel de Pure Pascal sont quelque peu inhabituelles pour
les compilateurs Pascal. Ils ont été choisis pour rendre le code généré par
le compilateur le plus efficace possible (sur microprocesseur Motorola 68k),
d'une part, et pour permettre une connexion simple de routines écrites en
Pure C ou Pure Assembler, d'autre part.
Quelques règles de base facilitent la compréhension des conventions d'appel:
- Si possible, les paramètres sont transférés dans des registres.
- Étant donné que le processeur 68000 connaît différents types de registres,
des registres appropriés au type de données à transférer sont utilisés,
c'est-à-dire des registres de données pour les types ordinaux, des
registres d'adresses pour les pointeurs et des registres à virgule
flottante pour les types réels.
- Les paramètres qui ne peuvent plus être transférés dans les registres sont
placés sur la pile. Le dernier paramètre est poussé en premier. Puisque la
pile se développe vers des adresses inférieures, le premier paramètre de
pile est donc à l'adresse la plus basse.
- La fonction appelante se charge de supprimer les paramètres passés sur la
pile, c'est-à-dire de réinitialiser le pointeur de pile à la valeur avant
l'appel.
- Les résultats de la fonction, comme les paramètres, sont renvoyés dans un
registre approprié au type de données.
- Les registres sont divisés en ceux qui peuvent être modifiés par les
routines appelées (D0-D2, A0-A1, FP0-FP2) et ceux qui doivent être
conservés (D3-D7, A2-A7, FP3-FP7).
Paramètres variables
Si la routine appelée a déclaré le paramètre avec le mot-clé var, l'adresse
du paramètre courant est toujours transférée, et non la valeur du paramètre
courant lui-même.
Le compilateur réserve les registres d'adresses A0 et A1 pour de tels
paramètres. Si aucun de ces registres n'est libre, l'adresse est poussée
sur la pile.
Paramètres par valeur
- Les types ordinaux (boolean, char, types d'énumération,
types d'entiers) sont transférés dans les registres de données D0, D1 ou D2
si possible. Lorsqu'il n'y a plus de registres libres, la valeur est poussée
sur la pile. Les paramètres qui ne font qu'un octet occupent toujours deux
octets sur la pile. Le paramètre est à l'adresse inférieure du mot, qui est
toujours paire. L'autre octet n'est pas utilisé.
- Les types Pointeur et Procédure sont transférés dans les registres
d'adresses A0 ou A1 si possible, sinon sous forme de mots longs sur
la pile.
- Les types simple, double et réel sont toujours passés sur la pile.
- Le type étendu est transféré dans les registres à virgule flottante FP0,
FP1 ou FP2 s'il y a encore de l'espace, sinon sur la pile.
- Pour tous les autres types (chaîne, ensemble, tableau, enregistrement et
objet) un pointeur vers la valeur est transféré, soit dans un registre
d'adresses, soit sur la pile. La fonction appelée fait alors une copie
de la valeur.
Résultats de la fonction
- Les types ordinaux (booléen, char, types d'énumération,
types entiers) sont retournés dans le registre D0. Si le type occupe moins
de 32 bits, les bits les plus significatifs ne sont pas définis dans D0.
- Les types Pointeurs sont renvoyés dans le registre A0.
- Les types réels sont renvoyés dans le registre FP0.
- Dans le cas des chaînes, la routine appelante réserve de la mémoire pour
le résultat. Le dernier paramètre (invisible) est un pointeur vers
l'espace mémoire réservé. La fonction appelée copie alors le résultat
dans cette mémoire.
conventions registre
Comme déjà mentionné ci-dessus, les fonctions appelées peuvent changer
librement les registres D0-D2, A0-A1 et FP0-FP2 sans les sauvegarder.
Tous les autres registres peuvent également être modifiés, mais dans
ce cas, ils doivent être sauvegardés avant les modifications et restaurés
à la fin de la fonction.
|