Section courante

A propos

Section administrative du site

Écriture des procédures de langage assembleur

Le OS-9 Pascal offre la possibilité d'écrire manuellement des procédures externes (c'est-à-dire des PROCEDURE et FUNCTION du OS-9 Pascal) en langage assembleur. Il peut également vous aider à comprendre le type de code natif produit par PascalT, le convertisseur de code natif. Il suppose que vous comprenez le langage d'assemblage 6809, la programmation en langage de programmation assembleur sous OS-9 et l'utilisation de la mémoire OS-9 Pascal.

Espace de variable : empiler les cadres et empiler les marques

Tout l'entreposage de variables utilisé par un appel de procédure est alloué dans une section de la pile OS-9 Pascal appelée «cadre de pile». Un cadre de pile se compose des trois composantes suivantes : une marque de pile, des variables locales et la pile étendue. Tous les paramètres devant être passés à une procédure font partie de la pile étendue de la procédure appelante. Supposons que la procédure Q soit déclarée comme ceci :

FUNCTION Q(i: real; var j: real; ch: char):integer;

Ensuite, pour appeler Q, la procédure appelante doit effectuer les opérations suivantes dans l'ordre indiqué :

A l'entrée dans la procédure Q, la pile ressemble à la figure suivante et le registre B contient le numéro de la procédure appelée :

La procédure Q termine ensuite la marque de pile de 7 octets et effectue une autre configuration avec le code suivant :

  1. PROCQ LDA PROCN           ; CHARGER AVEC NUMÉRO DE PROCÉDURE D'APPEL
  2.       STB PROCN           ; ENREGISTRER LA PROCÉDURE APPELÉE NUMÉRO
  3.       PSHS A              ; EMPILE LA PROCÉDURE D'APPEL NUMÉRO
  4.       PSHS U              ; ENREGISTRER LA COPIE ACTUELLE DU REGISTRE U
  5.       LEAU ,S             ; NOUVELLE VALEUR DU REGISTRE U
  6.       LEAX -locsize,S     ; REGISTRE DE POINTS X AU BAS DE LA PILE REQUIS
  7.       PSHS X              ; EMPILE PARAM POUR APPEL SUBR
  8.       LDD #extsize       ; CHARGE LE REGISTRE D AVEC UNE TAILLE DE PILE ÉTENDUE
  9.       LDX SUPJTBL         ; OBTENIR LE PAQUET DE SUPPORT D'ADRESSE
  10.       JSR STACKCHK,X      ; PILER VÉRIFIER ET METTRE À JOUR LE POINTEUR DE PILE
  11.       LDD DHOLD           ; OBTENIR LA VALEUR ACTUELLE DE DHOLD
  12.       PSHS D              ; ENREGISTRER LA COPIE SUR LA PILE

Le code illustré précédent est pratiquement identique pour chaque entrée de procédure. Le seul changement d'une procédure à l'autre est l'étiquette de la première ligne, la valeur de «locsize» et la valeur de «extsize». Il y a 3 variables entreposées dans la page zéro (c'est-à-dire dans la page de base) devant être utilisées ou maintenues par chaque procédure. La variable PROCN est le numéro de procédure courante d'un octet. Cette variable doit à tout moment indiquer le numéro de procédure comme indiqué dans le tableau des procédures de la procédure en cours d'exécution. La variable SUPJTBL contient une adresse mémoire absolue d'un point connu dans le paquet de support. Si le registre X du 6809 est chargé avec cette valeur, une instruction 'JSR subr,X', où' subr' est le nom d'un sous-programme de paquet de support tel que défini dans le fichier PASCALDEFS, utilisera l'appel de sous-programme approprié pour tout sous-programme de support. La variable DHOLD contient une valeur de 16 bits devant être sauvegardée localement à chaque entrée de procédure et restaurée à chaque sortie de procédure. La valeur de 'locsize' est, bien sûr, la taille indiquée dans la liste du tableau des procédures pour la taille de la pile locale de la procédure. Après avoir exécuté le code précédent, la marque de pile de 7 octets est terminée. La forme et le contenu d'une marque de pile sont les suivantes :

La figure suivante montre la forme et le contenu de la pile et où les registres U et S pointent après qu'un appel est fait à une procédure et que le code d'entrée de procédure a été exécuté :

Les références à la plupart des données se font via le registre U. Les paramètres passés et la zone de résultat de la fonction sont à un déplacement positif à partir de U, tandis que les variables locales sont à un déplacement négatif à partir de U. Le dernier paramètre passé est entreposé à partir du déplacement «7, U» pour son octet le plus significatif. La première variable locale est entreposée à un déplacement de -1U pour son octet le moins significatif. Pour accéder aux données dans des niveaux de procédures lexiquement plus élevés, c'est-à-dire dans les procédures d'appel, vous devez effectuer une opération «basex». Un basex est fait en gravissant les marques de pile pour trouver l'adresse de la zone de données locale de la procédure appropriée. L'adresse des données locales de la procédure d'appel immédiat se trouve dans les 5ième et 6ième octets de la marque de pile actuelle, comme illustré dans l'avant dernier illustration. Si vous vouliez accéder à une variable de 2 octets qui se trouve à un déplacement de -17 dans la zone de données locale de la procédure appelante, le code suivant serait utilisé :

  1. LDX 5 ,U        ; BASEX MONTE DE 1 NIVEAU
  2. LDD -17,X       ; DEMANDE 2B DE LA REGION D'APPEL PROCEDURE

De même, pour accéder aux données d'une procédure étant lexicalement deux niveaux plus haut (c'est-à-dire la procédure ayant appelé la procédure ayant appelé la procédure courante), deux opérations basex doivent être effectuées.

  1. LDX 5 ,U            ; BASEX MONTE UN 1 NIVEAU
  2. LDX 5,X             ; BASEX MONTE PLUS DE 1 NIVEAU
  3. LDD -displacement,X ; DEMANDE 2B DE DONNEES

Pour accéder aux données dans la zone globale, c'est-à-dire les données déclarées dans le bloc externe, ne nécessite pas d'opérations basex pour atteindre le niveau approprié - le registre Y pointe toujours vers le haut de la zone globale. A un déplacement nul ou positif par rapport à Y se trouve la zone système contenant plusieurs pointeurs, tampons, zones de travail et mémoire de tas. À un déplacement négatif de Y se trouvent les données locales du bloc externe - la zone de données globale. Le tableau suivant montre le contenu du registre et son utilisation pour les procédures s'exécutant dans un environnement OS-9 Pascal :

Registres Utilisation
A Disponible
B Disponible
X Disponible, également utilisé pour les opérations basex et d'indexation générale.
Y Pointe vers le haut de global, également le premier octet de la zone système.
U Pointe vers le haut de local, également le premier octet de la marque de pile actuelle.
S Pointe vers le haut actuel de la pile. Les piles sont construites en descendant dans la mémoire.
DP Pointe vers la zone de données de la page zéro. Cette zone ne doit jamais être utilisée par un programme utilisateur ou une procédure pour ses propres données - le paquet de support OS-9 Pascal gère cette zone.

Les registres Y, U, S et DP ne doivent normalement jamais être utilisés autrement que comme indiqué sur le tableau précédent. S'ils sont modifiés à tout moment, ils doivent être restaurés avant que des appels ne soient effectués au sous-programme ou avant que la procédure ne s'arrête ou n'appelle autre procédure.

Appel d'autres procédures OS-9 Pascal

Pour appeler une autre procédure OS-9 Pascal, les étapes suivantes doivent être effectuées dans l'ordre indiqué :

Enfin, pour quitter une procédure, utilisez le code ci-dessous :

  1. PULS D       ; RESTAURER LA COPIE ENREGISTRÉE DE DHOLD
  2. STD DHOLD   
  3. LEAS , U     ; POINT DU REGISTRE S AU BAS DE LA MARQUE DE PILE
  4. PULS U       ; RESTAURER LE REGISTRE U DE L'APPELANT
  5. PULS A,X     ; DEMANDE LE NUMERO D'APPEL ET RETOURNE L'ADRESSE
  6. STA PROCN    ; RESTAURER LE NUMERO DE PROCÉDURE ACTUELLE
  7. LEAS 2+paramsize,S  ; SUPPRIMER LES 2 DERNIERS OCTETS DU MARQUEUR DE PILE ET TOUT PARAMETRE PASSE DE LA PILE
  8. JMP ,X  ; REVENIR À LA PROCEDURE D'APPEL


Dernière mise à jour : Samedi, le 11 juillet 2020