Envoyer un e-mail à Collection ThomsonCollection Thomson
EditoForum 2002Liens
Nanoreseau
Docs
Logiciels
Matériel
Imprimer le documentLes cours d'assembleur de Prehis-To
Retour à la liste

Initiation à l’assembleur 6809

Cours n°4

L'instruction RTS est une instruction très utilisée. Elle correspond au RETURN du basic.

Nous avons vu dans le cours n°2 que S était le pointeur de pile officiel de l'ordinateur. Il est généralement défini dès l'allumage de l'ordinateur. Il s'agit du pointeur de pile du système. Il peut aussi être défini par l'utilisateur, mais sous de strictes conditions.

Une pile est une zone mémoire dans laquelle la valeur des registres peut être protégée. Selon les nécessités du programmeur, certains registres peuvent être "empilés", c'est-à-dire écrits dans cette zone puis "dépilés", c'est-à-dire récupérés à partir de la même zone. Cette procédure est constamment utilisée lorsque l'on doit protéger un registre utilisé dans une routine et récupérer ce registre au sortir de la routine dans le même état qu'à l'entrée. Les termes d'"empiler" et "dépiler" se justifient lorsque l'on sait que les registres sont écrits "vers l'arrière" dans la pile lors de l'empilement, puis lus "vers l'avant" lors du dépilement. Un empilement et un dépilement peuvent toucher tous les registres sauf, évidemment, celui utilisé comme pointeur de pile.

Imaginons que l'on veuille empiler les registres A, B et U à partir du pointeur de pile officiel S. Sous assembleur, on écrirait alors:

        PSHS   U,B,A

... dont l'exécution, toutes proportions gardées, aurait l'effet suivant:

        STU    ,--S    Ecrit U dans la pile > S=S-1:POKE S,U AND &HFF:
                                                    S=S-1:POKE S,FIX(U/256)
        STB    ,-S     Ecrit B dans la pile > S=S-1:POKE S,B
        STA    ,-S     Ecrit A dans la pile > S=S-1:POKE S,A

Son pendant, pour récupérer les registres empilés serait:

        PULS   A,B,U

... dont l'exécution aurait l'effet suivant:

       LDA    ,S+    Lit A dans la pile  > A=PEEK(S):S=S+1
       LDB    ,S+    Lit B dans la pile  > B=PEEK(S):S=S+1
       LDU    ,S++   Lit U dans la pile  > U=PEEK(S)*256):S=S+1:U=U+PEEK(S):S=S+1

L'ordre d'inscription des registres derrière les instructions PSHS et PULS n'a pas d'importance. Il n'obéit ici qu'à l'ordre d'empilement et de dépilement des registres (coquetterie de programmeur!).

Essayez le programme suivant, pour les TO:

DEBUT  LDA    #$20   Charge A               > A=&H20
       PSHS   A      Empile A               > S=S-1:POKE S,A
       LDA    #$FF   Change la valeur de A  > A=&HFF
       PULS   A      Dépile A               > A=PEEK(S):S=S+1
       SWI           Arrêt du programme     > END
       END           - Fin du programme -

...et pour les MO:

DEBUT  LDA    #$20   Charge A               > A=&H20
       PSHS   A      Empile A               > S=S-1:POKE S,A
       LDA    #$FF   Change la valeur de A  > A=&HFF
       PULS   A      Dépile A               > A=PEEK(S):S=S+1
       STOP          Arrêt du programme     > END
       END           - Fin du programme -

En examinant les registres par la commande "R"+RETURN, vous remarquerez que le registre A a été protégé puisqu’il a toujours la valeur $20 malgré le fait que sa valeur ait été changée par $FF en cours de programme.

Revenons à notre instruction RTS (ReTurn from Subroutine) qui est censée conclure tout sous-programme. Le sous-programme est appelé par un JSR (Jump to SubRoutine), un BSR (Branch to SubRoutine) ou un LBSR (Long Branch to SubRoutine) selon la proximité du sous-programme suivi de l'adresse du sous-programme. Après l'exécution de cette instruction, le registre PC (le doigt pour la lecture [cours n°2]) est empilé puis chargé avec l'adresse du sous-programme, ce qui fait que l'exécution saute au sous-programme. Lors de la rencontre avec le RTS, le registre PC est récupéré dans la pile et donc l'exécution saute juste après le branchement au sous-programme dans le programme principal. On peut dire que l'effet de RTS équivaut à l'effet de "PULS PC". Exécutez le programme suivant:

DEBUT  LDA    #$20    Charge A avec $20      > 10 A=&H20
       BSR    SOUSPG  Va au sous-programme   > 20 GOSUB 50
FIN    SWI            Arrêt du programme     > 30 END
* Remplacer SWI par STOP pour les MO
* Sous-programme                             > 40 REM Sous-programme
SOUSPG LDA    #$FF    Charge A avec $FF      > 50 A=&HFF
       RTS            Retour au programme    > 60 RETURN
       END            - Fin du programme -

Vous remarquerez que le nom du message de break est bien "FIN", ce qui prouve que le programme s'est bien arrêté à cet endroit et est donc revenu du sous-programme puis, en consultant l'état des registres par la commande "R"+RET, que A n'a pas la valeur $20 mais bien la valeur $FF, ce qui prouve que le sous-programme a bien été exécuté.

Si voulez faire un programme binaire tournant sous Basic, il est important de connaître l'instruction RTS: le retour au Basic en dépend. Les registres S et DP devront être conservés dans leur état initial pour éviter le bogue.

Concevons un programme tournant sous Basic et qui sera donc conclu par un RTS. Définissons l'origine (adresse d'implantation) en $9000 (en $5000 pour les MO) pour pouvoir le faire tourner en mémoire non-commutable. La directive FCC nous servira à déclarer un message directement en ASCII et la directive FCB à marquer la fin du message par un 0. Marquer la directive "END" avec l'étiquette "DEBUT" définira l'adresse d'exécution du programme ce qui nous permettra de lancer ce programme par un simple "LOADM<fichier>,,R". Assemblons-le sous éditeur directement sur le disque en tapant dans la barre d'éditeur "A"+<Numéro de lecteur>+":"+<Nom de fichier> (le suffixe par défaut est "BIN"). Puis exécutons ce programme machine assemblé sur disquette par un LOADM,,R sous Basic en n'oubliant pas le « CLEAR,,,&H9000 » préalable (« CLEAR,,,&H5000 » pour les MO):

        ORG    $9000
                                                  10 POKE &H900C,"COUCOU!"
                                                     +CHR$(0)
DEBUT  LDX    #MESSAG    Pointe sur message  > 20 X=&H9000
SUITE  LDB    ,X+        Récupère caractère  > 30 B=PEEK(X):X=X+1
       JSR    $E803      Affiche caractère   > 40 PRINT CHR$(B);
       TSTB              Teste le caractère  > 50 IF B<>0 THEN 30
       BNE    SUITE      Si <> 0, boucle
       RTS               Retour au basic     > 60 RETURN
* Message "COUCOU!"
MESSAG FCC    "COUCOU!"
       FCB    0
       END    DEBUT      - Fin du programme -

Le fichier est chargé, le message "COUCOU!" s'affiche à l'écran puis la main est rendue au Basic (Pour les MO, remplacer « ORG $9000 » par « ORG $5000 » et « JSR $E803 » par « CALL $02 »).

Site
Plus
Forums
Code
Créations

*Site en favoris
*Page en favoris
*Site en démarrage
*Page en démarrage


Haut de page

Collection Thomson 2015 © Ghislain Fournier & François Mouret