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:
à
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)
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
***************************************
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.
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