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.