La 2ème partie du cours de MACGYVER

====================================

L'adressage étendu (ou absolu):

 

Il permet de travailler sur la mémoire avec des valeurs absolues.(le(s) code(s) d'opération seront/sera suivi(s)

de 2 octets qui représentent l'adresse réelle de la donnée (on parle d'adresse effective):

                                      

  Ex: LDA $CDEF Chargement de A avec l'octet situé en      $CDEF

Ces quelques modes d'adressages ne sont pas les seuls, mais il sont pour l'instant suffisants pour comprendre le fonctionnement du langage machine.

 

Quelques instructions du 6809 E:

                                      

Maintenant que nous avons vu quelques modes d'adressage, voyons quelques instructions (je sais, j'avais dit que je ne les aborderais pas, mais ne restons   pas dans le théorique:

un peu de pratique sera plus amusant!!).

                                      

On remarquera que le nom des instructions reprennent généralement le nom de  leur fonction. Il suffit alors d'un peu d'imagination et de quelques connaissances en anglais pour déduire la fonction d'une instruction à partir  de son nom.

.LD (=LoaD en anglais, charger)

ex: LDA #65 Charge A avec 65 décimal LDX #$ABCD   "    X   "  ABCD hexa

(adressage immédiat) LDY $CDEF   "    Y   " les deux octets

situés en $CDEF/$CDF0. (adressage absolu)

.INC (=INCrease, augmenter)

 INCA  Augmente A de 1

 (adressage inhérent)

 INC  $BCDE    "     le contenu de $BCDE de 1 (adressage absolu)

(même chose avec DEC (DECrease, décrémenter, pour diminuer de 1)

.CMP (CoMPare) CMPA #$45 Compare A à $45,et positionne

 

 le registre d'état suivant le résultat (supérieur, inférieur, négatif, overflow,...)

 (adressage immédiat)

  CMPB  $B456 Même chose avec le contenu de $B456

   (adressage absolu)

                                      

.ST (STock, déposer un octet en mémoire)

 STA  $DCBA Dépose le contenu de A en

 $DCBA (adressage absolu)

 (inexistante en adressage immédiat)

                                       

.JSR (Jump to SubRoutine, saut à un sous-programme)

 JSR SUIT Saut au label SUIT (adressage

absolu).

Le sous-programme doit se terminer par un RTS (ReTurn of Subroutine) qui permet

 

de continuer l'exécution du programme après le JSR. JSR  est l'homologue de GOSUB en BASIC.

                                      

                                      

                                      

                                      

Structure d'un programme machine:

                                       

Un programme machine se présente (grossièrement sous la même forme qu'un programme BASIC, avec des sauts, des sous-programmes. La principale différence réside dans le fait que nous ne manipulerons pas des instructions comme celles du BASIC (une pour afficher un point, une autre un caractère,...) mais presque les instructions (machine) qui composent les instructions BASIC. De ce point de vue, on comprend que le BASIC est considéré comme un langage facile, car ses instructions seront désormais vues comme des 'macros'. Le langage machine est le royaume des tests:

En effet, pour réaliser la même chose que l'instruction 'INSTR' sous BASIC,il faut effectuer de nombreux tests (fin de chaîne, caractère reconnu, ...).Du coup, l'instruction de test 'IF.. THEN . ELSE' du BASIC prendra alors des allures plus compliquées (Plusieurs tests possibles, plusieurs conséquences possibles,...). Bref, ce n'est pas parce que c'est de

l'assembleur qu'il faut dramatiser:rappelez-vous vos premiers pas dans le BASIC. Dans quelques temps vous serez (presque) aussi à l'aise avec le langage machine.

 

Etude d'une routine: PUTC ($E803):

                                      

PUTC permet l'affichage de tous les caractères, mais aussi les mêmes fonctions que les instructions  BASIC: COLOR,

 

SCREEN, CONSOLE, PRINT, LOCATE.

                                      

Un petit exemple de programme simple utilisant les connaissances que nous avons jusqu'à présent:

 On veut faire exécuter à l'ordinateur une série de 'bip'. On sait qu'on obtient un beep en faisant (sous BASIC) PRINT CHR$(7). Dans l'ordinateur, la routine équivalente de PRINT est PUTC. Le code du caractère à afficher doit se trouver dans l'accu B. On appellera la routine PUTC comme un sous-programme , avec JSR.

                                      

On écrira donc:

                                      

  LDB  #7

  JSR  PUTC                           

 

Si vous tapez directement ces deux instructions sous EDIT, l'assembleur vous affichera plusieurs erreurs à l'assemblage: On n'a en effet pas précisé:

-l'origine de l'assemblage

-à quelle adresse PUTC faisait référence (l'assembleur ne connaît pas 'PUTC')

-la fin du programme à assembler.

                                      

Pour l'origine: on utilise la directive ORG (à placer dans la colonne des opérations(2°)), suivie de l'adresse voulue de l'assemblage (dans la colonne des opérandes (3°))). Cela donnera:

   ORG  $A000, par exemple            

 

On accède à la routine PUTC en faisant un appel de sous-programme en $E803 (par JSR).On pourrait taper directement:

   JSR  $E803

à la place de: JSR PUTC, mais pour une question de lisibilité du programme source, il faut mieux lier les adresses de sous programmes à leur nom en toutes lettres. On réalise cette opération grâce à la directive 'EQU': ainsi, on

placera en début de programme:

 

===================================

 

Notre programme final sera donc:

                                      

  ORG  $A000

 PUTC  EQU $E803

 

.  LDB  #7

  JSR PUTC

  SWI

A la fin du programme, un SWI  est nécessaire lorsqu'on veut revenir sous MONITOR, en cas d'exécution du programme, si vous lancez le programme sous BASIC, remplacez ce SWI par un RTS.

Après assemblage, passez sous MONITOR par la commande X et lancez l'exécution par GA000 si vous avez assemblé votre programme à partir de $A000. (Si vous utilisez un TO9, lancez le programme

sous BASIC par EXEC &HA000).

On entend un bip!!

APPROFONDISSEMENT: faire faire plusieurs bip à l'ordinateur.

                                      

                                       

On devra utiliser un compteur, qui recensera le nombre de bip émis. On implantera en $B000 le nombre de bip que l'on désire.

Pour éviter de réécrire plusieurs fois "JSR  PUTC" et que l'on puisse faire  exécuter au micro un nombre variable de bip avec le même programme, on va utiliser une boucle, munie d'un test.

Le compteur sera l'accu A (on ne peut pas utiliser B qui est déjà pris par PUTC). A sera initialisé à 0 au début du programme, et augmenté de 1 après chaque 'bip'.Ensuite, on compare A et la valeur déposée en $B000. Si différent, on

recommence, si égal, on sort:

                                      

       ORG    $A000

PUTC  EQU    $E803

CPT    EQU    $B000

 

       CLRA   Initialisation de A

       (passage à 0)

BOUC   LDB    #7  on charge B avec la

valeur 7

       JSR    PUTC  Appel de  PUTC

       INCA   On incrémente A de 1

       CMPA   CPT  On compare A au

       contenu de CPT ($B000)

    (adressage étendu/absolu)

       BNE    BOUC  Si différent, on

       boucle sur BOUC, si égal, on sort.

       SWI   Retour sous MONITOR.

       END

                                      

Tapez ce programme et assemblez-le.

                                      

Passez ensuite sous MONITOR. On initialisera le registre $B000 avec le nombre de bip désiré: Tapez (après le dièse): B000/. A cet instant, MONITOR affiche le contenu de $B000.

Entrez une nouvelle valeur et lancez le programme par 'GA000'. On notera que si l'on remplace dans le programme la valeur chargée dans B par le code d'un caractère affichable (ex: 65 pour A), on obtiendra autant de 'A'. Bidouillez, amusez-vous (par exemple en enchaînant un bip, un A,...), mais assurez-vous que vous n'avez pas de fichier important sur le disque 4, car en cas de plantage,...

                                      

                                      

Notre but est donc de forcer à zéro certains octets de cette zone. Le tout est de savoir lesquels...

 

Si, sur l'écran, un rectangle est représenté par une zone homogène, son image en RAM A/B ne sera pas représentée par une

succession continue d'octets mais plutôt par des "tirets" dont la longueur et l'espacement varient avec la largeur du rectangle (de gauche à droite). Pour se représenter cela, il faut imaginer que

la zone $4000-$5F3F est un segment  divisé en 8000 intervalles.

Chaque intervalle représentant un octet la première ligne (de l'épaisseur d'un d'un pixel) de l'écran sera représentée par les 40 premiers octets de la zone de de mémoire graphique (soit de $4000 à $4028). Les 40 octets suivants représenteront la seconde ligne (à partir de $4029), etc.

Expression du début de la première ligne

Soit:

XMIN: abscisse coin supérieur gauche

     YMIN: ordonnée   "      "        "

     XMAX: abscisse   "  inférieur droit

     YMAX: ordonnée   "      "        "

                                      

Le problème est de convertir les coordonnées caractère en adresses. Nous savons q'une ligne 'caractère' est une superposition de huit lignes 'pixels' ou de huit lignes de GPL. On veut un début de zone en haut du caractère supérieur gauche de la fenêtre. On aura donc, en raisonnant pour un mode 40 colonnes, les colonnes et les lignes étant numérotées à partir de 0:

Pour les lignes:

                                      

D=  40 *   8 *    YMIN  largeur 8 lignes de la 'pixel' coordonnée fenêtre en supposées en ligne en ligne mode caractère.

                                      

Il faudra ajouter à ceci le décalage en colonnes (XMIN) et l'adresse du début de la fenêtre: $4000

D'où la formule finale:

DEBUT=320*YMIN+XMIN+$4000

On vérifie pour YMIN=0, Xmin=1: Debut=$4 001, second octet de la fenêtre (puisqu' on veut commencer à partir de la deuxième colonne (numérotée 1)).

                                      

Expression de la fin de la dernière ligne:

                                      

On procède de la même manière que pour DEBUT, mais comme on veut que FIN soit l'adresse du GPL situé en bas du dernier caractère de la fenêtre, il faudra ajouter 8*40 soit 320 octets.

                                       

D'où: FIN=320*YMAX+XMAX+320+$4000

                                      

                                      

                                      

Voici le début du programme: calcul des adresses extrêmes:

 

       TITLE  Effaceur de portions

* d'écran

*--------------------------------------

* en coordonnées caractère:

*   XMIN: abscisse coin supérieur gauche

*   YMIN: ordonnée   "      "        "

*   XMAX: abscisse   "  inférieur droit

 

*   YMAX: ordonnée   "      "        "

*--------------------------------------

                                      

       ORG    $A000

                                      

FRMCLR EQU    $E7C3

XMIN   EQU    $A100

YMIN   EQU    $A102

XMAX   EQU    $A103

YMAX   EQU    $A105

DEBUT  EQU    $A106  ADRESSE DE FIN

FIN    EQU    $A108  ADRESE DE DEBUT

LARG   EQU    $A10A LARGEUR DE FENETRE

LIGCRS EQU    $A10B ADRESSE DU DEBUT

                   *DE

                   *LA LIGNE COURANTE

                                      

* CALCUL DE L'ADRESSE DE DEBUT

                                      

       LDB    YMIN

       LDA    #10

       MUL

                                      

       LDA    #32     DEBUT=320*YMIN

       MUL              +XMIN+$4000

                                      

                                       

       ADDD   XMIN

       ADDD   #$4000

       STD    DEBUT   ON DEPOSE LA

              *VALEUR DANS DEBUT

                                      

* CALCUL DE L'ADRESSE DE FIN

                                      

       LDB    YMAX

       LDA    #10

       MUL

                                      

       LDA    #32     FIN=320*YMAX+320

       MUL              +XMAX+$4000

                                      

       ADDD   #320

       ADDD   XMAX

       ADDD   #$4000

       STD    FIN     ON DEPOSE DANS

              *FIN

                                      

    Il faut maintenant détecter la fin de la ligne que l'on aura remis à zéro.

Connaissant Xmax, abscisse maximale et XMIN, abscisse minimale, il est aisé de connaître la largeur de la zone, soit:

LONG=XMAX-XMIN.

A cela, il faudra ajouter

1 pour avoir le nombre total de colonnes à mettre à 0. On aura donc LARG = XMA

X - XMIN + 1

                                      

Suite du programme précédent:

                                       

* IMPLANTATION DANS LARG DE LA

* LARGEUR DE LA

* PORTION D'ECRAN A EFFACER

                                      

       LDD    XMAX

       SUBD   XMIN  XMAX-XMIN: LARGEUR

              * DE LA ZONE EN CAR

              *       ACTERES

              * <256, DONC EST DANS B

       INCB * ADDITIONNE 1 A B

       STB    LARG    largeur de la

              *       fenetre

                                      

Ensuite, il faut vérifier si après avoir mis à 0 l'octet courant, on a atteint la fin de la ligne. Cette fonction d'auto-incrémentation et de test de fin de ligne à effacer est réalisée par la boucle EFAC (et EFAC2 pour la memoire forme).

Si on a atteint la fin de la ligne, il faut recommencer à partir du début de la ligne suivante. LIGCRS pointant sur le début de l'ancienne ligne, il suffit d'y ajouter 40 en décimal(largeur de l'écran pour obtenir le début de la ligne suivante. Après chaque ligne, il faut aussi  vérifier si on a dépassé FIN, l'adresse de fin de la zone à effacer. Ceci est testé par la boucle AUTLIG et AUTLI2 réspectivement pour les mémoires couleur et forme.

                                      

***************************************

*  EFFACAGE EN MEMOIRE COULEUR

* DE LA ZONE CALCULEE

***************************************

                                      

       LDX    DEBUT

       STX    LIGCRS

                                       .

       LDB    FRMCLR*PASSAGE EN

       * MEMOIRE

       ANDB   #$FE

       STB    FRMCLR   COULEUR

                                       .

AUTLIG CLRA

       CLRB

EFAC   STB    ,X+*On incrémente X de 1

       INCA *on incrémente le compteur

       CMPA   LARG* = largeur fenetre?

       BNE    EFAC *NON: on recommence

       LDD    LIGCRS* Oui:

       ADDD   #$28  ON INCREMENTE

              *  D'UNE LIGNE (40 CAR.)

       TFR    D,X

       STD    LIGCRS

       CMPX   FIN    A-T-ON DEPASSE LA

              *       FIN DE LA ZONE?

       BLO    AUTLIG*NON:ON RECOMMENCE

       LDX    DEBUT *OUI:ON INITIALISE

       STX    LIGCRS  LE DEBUT DE LA

              * LIGNE POUR RECOMMENCER

            *LA MEME CHOSE EN M. FORME

                                      

*************************************

*  EFFACAGE EN MEMOIRE FORME

* DE LA ZONE CALCULEE

************************************

                                      

       LDB    FRMCLR  PASSAGE EN M.

       ORB    #$01

       STB    FRMCLR  FORME

                                      

AUTLI2 CLRA

       CLRB

EFAC2  STB    ,X+

       INCA

       CMPA   LARG

       BNE    EFAC2

       LDD    LIGCRS

       ADDD   #$28

       TFR    D,X

       STD    LIGCRS

       CMPX   FIN

       BLO    AUTLI2

                                      

       SWI            ON TERMINE

       END

                                      

Pourquoi a-t-on réalisé deux boucles identiques au lieu d'une seule? Regardons d'un peu plus près: l'une agit en mémoire couleur et l'autre en mémoire forme. Si on avait réuni les deux actions dans la même boucle, il aurait fallu, pour une même adresse, commuter le bit 0 de $E7C3 une fois à 1, mettre l'octet à  zéro puis passer ce même bit à 0 pour recommencer la même opération en mémoire forme.

Cela aurait pris donc beaucoup plus de temps au microprocesseur

 

(à peu près 15 microsecondes pour chaque octet), alors

que dans le programme proposé, on ne commute le bit 0 de $E7C3 dans un état qu'une seule fois pour toute la fenêtre.

Au lieu d'écrire deux fois le même programme, on aurait pu aussi créer un sous-programme chargé d'inverser le bit un autre d'effacer la fenêtre dans la mémoire correspondante et un petit

programme principal chargé de régir le tout. Un petit problème cependant: en mettant les octets des deux RAM (A et B) à 0, on n'obtient pas un écran noir, mais gris. Quelqu'un saurait-il pourquoi ? (Ceci n'est pas une énigme: je ne sais réellement pas ce qui se passe).

Bon courage !

                                      

                                      

                                      

                                      

Sauts, comparaisons et branchements:

___________________

 

Jusqu'à présent, nous avons utilisé plusieurs instructions de ce genre, mais nous n'avons pas vu comment elles fonctionnaient. Les instructions que nous allons voir utilisent un registre particulier du 6809 E : le registre codes-conditions (CCR). Ce registre 8 bits définit à chaque instant l'état du processeur. La signification de ses différents bits est la suivante:

 

    E   F   H   I   N   Z   V   C

bit 7                          bit 0

 

C: indicateur de retenue.

V: indicateur de débordement

(résultat >127 ou <-128)

Z: indicateur de zéro (résultat nul)

N: résultat négatif

Les bits I à E concernent seulement les traitements d'interruptions et non

les tests.

 

Soit M un registre de la mémoire. Soit C une condition portant sur M. On voudra par exemple programmer: si C remplie, alors réaliser l'action A, sinon réaliser A'.

Connaissant le contenu de M et les actions A et A' à réaliser, il nous faudra faire le lien entre les deux grâce à C. Ce lien se fera en deux étapes:

 

- Positionnement des bits de poids faible du CCR (voir plus haut) selon le contenu de M.

 

- Comparaison de C et de M grâce aux bits du CCR (qui représentent l'état  de M).

 

Parfois, il nous faudra réaliser un test sur une opération arithmétique (retenue, débordement). On se passera alors de la première étape : puisque c'est le microprocesseur qui réalise

ces opérations et que le CCR représente l'état du processeur, on aura alors les informations désirées sur ce qui s'est passé pendant le déroulement de l'opération (retenue,...).

 

On peut donc distinguer deux types d'instructions: les instructions de test (qui positionnent les bits du CCR selon l'état de l'opérande fournie) et les instructions de branchement (qui branchent l'exécution du programme à un autre endroit si une condition est réalisée. Cette condition varie avec l'instruction de branchement utilisée).

 

Mais auparavant, il faut bien comprendre comment le microprocesseur travaille avec les nombres.

 

 

I°/ Entiers négatifs et positifs :

     quelle différence?

------------------------------------

 

Le 6809 E est un microprocesseur 8 bits (on peut cependant, dans des cas particuliers, le considérer comme fonctionnant sur 16 bits). Cela signifie qu'il ne peut traiter des nombres que sur 8 bits:

 

S    X    X    X    X    X    X    X

 

Chaque bit pouvant prendre deux valeurs, on obtient ainsi 256 (2^8) valeurs différentes pour un octet. Pour qu'il y ait à la fois des nombres positifs et négatifs, il faut séparer ces valeurs: les positifs s'étendront de 0 à 127 et les négatifs de -1 à - 128 (en base 10).

 

Les 7 premiers bits permettent de coder les 2^7 soit 128 premières valeurs. Par convention, les nombres n'utilisant que ces 7 bits seront considérés comme positifs. Pour obtenir les 128 autres, il faut utiliser le bit 7 ("S" sur le schéma). Ces 128

autres valeurs seront donc considérées comme négatives. La différence entre nombres positifs et négatifs ne réside que dans un seul bit, toujours le bit de poids fort quelque soit la

longueur du nombre, et appelé donc bit de signe.

En hexadécimal, sur 8 bits, les positifs sont donc compris entre 00 et $7F inclus et les négatifs entre $80 et

$FF

La "symétrie" entre positifs et négatifs se faisant toujours par rapport à zéro, on aura par exemple:

-1 décimal sera codé en $FF

 +5 " "     $5

-15 " "     $F1

 

 

II°/ Tests:

 

Ces instructions se contentent de positionner les bits du CCR suivant  l'état du registre testé  ou le résultat d'une opération inhérente à l'instruction concernée.

 

 

        1) L'instruction TST:

 

Très simple, elle permet, comme son nom l'indique (d'une manière peut littéraire il est vrai) de tester un accumulateur (A ou B) ou un registre mémoire.

 

Ses conséquences:

 

Cette instruction modifie les bits N et Z du CCR ( indicateurs de négatif et de zéro) en fonction de l'état du registre testé. Ce registre sera toujours un registre 8 bits. Ex: Si on veut tester le contenu de l'accu A, on écrira:

 

TSTA

Il s'agit donc ici de l'adressage  inhérent. Ce mode d'adressage pour cette instruction fonctionne  également pour l'accu B(TSTB).

 

Si on veut tester le contenu d'un registre mémoire, par exemple $ABBA, on écrira alors:

 

TST  $ABBA   = adressage étendu

 

Ex: Si le registre $DCBA contient la valeur $95: si on la convertit en binaire, on s'aperçoit que le bit 7 est à 1

 

C'est donc un nombre négatif.

Vérifions-le par:

 

       TST     $DCBA

 

A la sortie, on peut vérifier (commande 'R' du MONITOR) que le bit 3 (N) du CCR est à 1. Ceci implique évidemment une petite conversion hexabinaire.

 

Le programme: très simple.

 

TST REG On teste

SWI     On termine

END

Cette instruction supporte également les modes d'adressage direct (par

pages de 256 octets) et indexé (pour la gestion de tableaux).

 

2) L'instruction BIT:

 

Cette instruction existe sous deux formes (BITA et BITB).L'une et l'autre peuvent être utilisée en adressage immédiat (l'instruction est suivie de l'opérande explicite), indexé (pour la gestion des tableaux), direct (adressage par "page" de 256 octets) ou étendu (comme l'adressage direct mais l'adresse est "entière" (sur 16 bits)). Cette instruction effectue un ET entre

l'accu concerné (A ou B) et l'opérande. Ex: On veut appliquer l'instruction BIT entre le registre B et l'octet situé en $A123, sachant que X  contient $A000. En utilisant le registre X, on pourra se servir de l'adressage indexé

 

On prendra par exemple les valeurs suivantes:

B contient:           10011111 (en

binaire évidemment, $9F en hexa)

 

L'octet d'adresse

$A123 contient:   10100001, $A1 en hexa.

 

Si on applique un masque 'ET' entre ces deux valeurs, on obtient comme résultat:

          10000001

 

Le bit 7 (le premier "en partant de la gauche", c'est-à-dire le bit de poids le plus fort) étant à un, le résultat du masquage est donc un nombre négatif. BIT positionnant CCR en fonction du

résultat, on devrait, à l'issue de l'exécution de l'instruction, avoir le bit N à 1.

 

Le programme:

 

       ORG    $B000

 

REGIST EQU    $A123

XCONT  EQU    $A000

BCONT  EQU    $9F

A123C  EQU    $A1

 

       LDB    #BCONT

 

 

 

 

 

 

 

 

 

On initialise B avec $9F

       LDA    #A123C On met $A1 dans

                   l'accu A

       STA    REGIST L'octet situé

                    en $A000 avec $81

       LDX    #XCONT X avec $A000

       BITB   $123,X On applique ici

                  l'instruction BIT

                  entre B et l'octet

                d'adresse $123+contenu

               de X  , soit $A123.

       SWI On termine l'exécution

       END

(Programme à exécuter sous MONITOR et à lancer en $B000 par 'GB000')

 

On vérifiera que le bit 3 DU CCR est à un par la commande 'R' du MONITOR qui affiche à l'écran le contenu des registres du 6809E. Etant affichés en hexa , on pourra s'aider éventuellement d'une calculatrice pour faire apparaître le résultat en binaire.

 

 

3) L'instruction CMP:

 

Cette instruction effectue en fait une soustraction entre le registre spécifié et l'opérande. Les bits de CCR sont modifiés selon le résultat (Z=1 si registre et opérande sont identiques, C=1 si le registre est inférieur à l'opérande (sur des valeurs non signées),...). Généralement, cette instruction est suivie d'un branchement conditionnel.

III°/ Les branchements

       (in)conditionnels:

------------------------------------

 

1) Branchements inconditionnels:

 

a) Sauts à un sous-programme:

 

Ces instruction sont l'équivalent du 'GOSUB' en BASIC.

Nous avons déjà rencontré une instruction permettant le saut à un sou-programme: JSR

Il en existe une autre: BSR

Le retour au programme principal à partir du sous-programme du s'effectue dans un cas comme dans l'autre grâce

à un RTS. Mais l'instruction BSR ne fonctionne qu'en adressage relatif (le code  d'opération est suivi de la valeur à ajouter au compteur programme (registre PC) pour atteindre l'adresse

du sous-programme) alors que JSR est suivie de l'adresse effective. L'instruction BSR permet donc de réaliser

des programmes "relogeables", c'est à dire des programmes qui pourront être chargés et exécutés qu'elle que soit leur adresse d'implantation en mémoire On observe le même phénomène entre

BRA et JMP.

 

 

b) Sauts inconditionnels:

 

Ces instructions sont l'équivalent du 'GOTO' en BASIC.

Le résultat de l'exécution de BRA et JMP sera le même, mais BRA ne fonctionne en relatif et JMP avec des adresses effectives. BRA permet donc de faire des programmes relogeables (voir précédemment).

 

 

2) Branchements conditionnels:

 

 

branchement si inférieur:

   BLT     Cette instruction opère avec des valeurs signées. ex: si A=$F0 , un CMPA  #$40 suivi d'un BLT  BIP entraînera le branchement du sous-programme en BIP (en valeurs signées,

$F0<$40).

 

.branchement si inférieur ou égal:

   BLE   pour des valeurs signées

   BLS   pour des valeurs non signées.

ex: LDA  #$80

    CMPA #$40

    BLE  BRANCH  branchement car

         $80< $40 (bit 7 à un).

 

En revanche si à la place du BLE BRANCH  on avait  BLS BRANCH, on

n'observerait aucun branchement.

 

branchement si égal:

On utilisera l'instruction BEQ, qui branche si Z=0 (CMP effectuant une soustraction, si les registres mémoire et processeur sont égaux, on aura bien une différence nulle).

 

 

branchement si supérieur:

BGT  (signé)

BHI  (non signé)

Le fonctionnement en valeurs signées ou non signées est identique aux instructions BLE et BLS.

 

branchement si supérieur ou égal:

BGE  (signé)

 

Autres branchements:

 

BCC ou BHS: branchement si pas de

                       retenue

BCS ou BLO:    "   "   retenue

 

BNE:   "   "   différent de zéro

BMI:   "   "   négatif

                    (signé evidemment)

BPL:   "   "   positif (signé

                    évidemment)

BVC:   "   "  si pas de

                   débordement

BVS:   "   "  si débordement

 

Il faut préciser que toutes les opérations de branchement commençant par B.. sont valables pour des déplacements de +127 ou -128 octets (on travaille en relatif). Pour dépasser

ces valeurs limites, il convient de rajouter un 'L' devant l'instruction qui commencera alors par: LB.. Autrement, une erreur ' Branch out of range' sera générée à l'assemblage.

Désolé pour l'énoncé un peu sec de ces différentes instructions de branchements conditionnels, mais elles sont si identiques (dans leur fonctionnement) qu'il n'est pas utile de développer

plus chaque cas.

===============================

 

Les PILES:

 

On entend par "pile" un emplacement en mémoire où le microprocesseur peut stocker temporairement les données

contenues dans ses registres afin de les sauvegarder pendant l'éxécution d'une autre tâche, par exemple un saut

à un sous-programme:

-

          ...

JSR SUBROUT   On saute à 'SUBROUT'

          ...

SUBROUT   ...

          RTS          

On revient au programme principal.

-

Analysons en détail l'instruction JSR:

-

Le registre PC (Compteur Programme) indique en permanence au processeur l'adresse de l'instruction à éxécuter. Comme JSR est en fait un déplacement de l'éxécution du programme, on peut

supposer que JSR agira sur PC, et c'est exact!

Mais afin de pouvoir continuer l'exécution du programme principal à la sortie de sous-programme, il est nécessaire d'inscrire quelque part l'adresse suivant l'instruction JSR. Cette inscription est réalisée par JSR elle-même dans la pile système.

Rappel: Sur 6809E, il existe deux piles, système et utilisateur. Dans le microprocesseur, ces piles sont pointées par deux registres "pointeurs de pile": S pour système et U pour la pile user. Ces registres indiquent l'adresse de l'octet du sommet de la pile correspondante.

 

Si l'adresse du sommet de la pile est $F000, après l'éxécution de JSR, qui stocke une adresse (16 bits), S aura pour contenu: $F000  2 soit $EFFE.

Notons que S pointe toujours sur le dernier octet entré dans la pile et que S est décrémenté avant l'inscription d'un octet dans la pile. L'utilisateur peut également stocker des données dans les piles:

Ceci est réalisé par l'instruction PSH ,qui sera toujours utilisée en adressage inhérent. PSHS empile des données sur S et PSHU sur U.

Leur syntaxe est la suivante:

PSHS(ou U)    A,B,X

empile les registres A, B, et X dans S

(ou U).

Pour les registres 16 bits, l'octet de poids faible est stocké avant l'octet de  poids fort.

 

A la fin du sous-programme, l'instruction RTS permet de revenir au programme principal à l'instruction suivant le JSR en dépilant le compteur programme empilé par JSR. L'opération est effectuée est l'inverse de PSH: l'octet de poids fort ayant été empilé

en dernier, il sera dépilé en premier.

 

Pour dépiler un/plusieurs registres, on utilise l'instruction PUL à laquelle on applique la même syntaxe qu'à PSH. Notez que l'éxécution de PUL entraîne le dépilement et le stockage immédiat des registres dans eux-mêmes.

 

Note:

Personnellement, je n'arrive à me servir correctement que de la pile Système, et encore faut-il ne pas la reloger (en modifiant le registre S).

Je ne parvient pas à stocker des données dans la pile utilisateur.

 

Quelqu'un sait-il pourquoi?

A Suivre !!!!!!

 

Si quelqu'un veut bien remplacer

MACGYVER faire offre.

-

Merci d'avance