Suivez-nous sur X
|
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z,
ALL
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z
|
|
A propos d'Obligement
|
|
David Brunet
|
|
|
|
Programmation : Assembleur - les modes d'adressage et les boucles
(Article écrit par Roméo Rapido et extrait d'A-News (Amiga News) - avril 1989)
|
|
Récapitulons les différents modes d'adressage
Afin de simplifier : quand un registre reçoit une valeur, on notera "ri <-". Si c'est une valeur qui est stockée, on écrira
celle-ci. Si c'est le contenu d'un registre, on écrira le registre "ri". Si c'est un adressage indirect et que c'est la valeur
contenue à l'adresse qui est dans le registre "ri", on écrira (ri) (ouf !).
Rappelons qu'il y a huit registres de données (d0 à d7) et huit registres d'adresse (a0 à a7) et que a7 est aussi le pointeur
de pile ou SP (stack pointer), leur taille est de 32 bits, donc acte. Enfin, les instructions s'écrivent INSTRUCTION SOURCE,DESTINATION
ou INSTRUCTION SOURCE. Dans ce dernier cas la source est aussi la destination (exemple : clr.l d0 qui est la remise à 0 du registre
d0) on abrègera quelquefois par D et S. Exemple : move.l d0,d1 on peut écrire la syntaxe de l'instruction "move" qui est "D<-S"
et son effet dans ce cas qui est "dl<-d0".
Il n'en reste plus qu'un, l'adressage relatif au PC. Très utile pour générer des programmes relogeables mais je l'ai volontairement
passé sous silence car l'assembleur de l'Aztec ne le reconnaît pas. Par contre, si vous travaillez avec K-Seka,
vous pouvez l'utiliser (c'est même recommandé - voir article de Charles Vassallo sur le BASIC
et l'assembleur).
Dans ce cas, "move.l DeCadix(PC),d0" se traduit par "D0<- (PC + distance jusqu'au label DeCadix) (arg, j'ai craqué, c'était trop
tentant). Cette distance pouvant être négative ou positive. Votre programme est donc relogeable car où que soit le label,
le déplacement est le même et il n'y a pas d'erreur d'adressage.
Vous savez déjà qu'il y a aussi deux autres registres, le "PC" (program counter) qui pointe sur l'instruction à exécuter, et le
registre "CCR" (code condition register) qui contient les bits "C" (cary ou retenue), "V" (overflow ou dépassement), "Z" (zéro),
"N" (négatif), "X" (extend ou bit d'extension).
Ces bits sont positionnés lors d'une opération ou d'un test du type "cmp.l #$8000,d0" qui effectue l'opération d0-$8000
(destination - source virtuellement, c'est-à-dire que les registres ne sont pas modifiés) dont le seul but est de positionner
les indicateurs. Sachez qu'il existe d'autres bits dans le registre d'état mais que ceux-ci sont réservés au système et
au mode superviseur.
Signification
Z positionné si le résultat est nul.
V dépassement de capacité le résultat ne peut pas tenir dans la taille de l'opérande.
C retenue positionné si une retenue est générée.
X positionné par les opérations sur les opérandes étendus.
Ces différents bits peuvent être testés par les instructions de branchement pour faire des branchements conditionnels. Leur
combinaison permet de faire tous les tests indispensables. La syntaxe est "Bcc adresse ou étiquette".
Ce peut être :
- CC | retenue à zero | c = 0
- CS | retenue à 1 | c = 1
- EQ | égal | z = 1
- NE | différent | z = 0
- GE | supérieur ou égal | n ou v = 0
- GT | supérieur | z et (n ou v)= 0
- HI | supérieur | c et z = 0
- LE | inférieur ou égal | z et (n ou v) = 1
- LS | inférieur ou égal | c et z = 1
- LT | inférieur | n ou y = 1
- MI | négatif | n = 1
- PL | positif | n = 0
- VC | dépassement à 0 | v = 0
- VS | dépassement à 1 | v = 1
- T | vrai | 1
- F | faux | 0
- RA | saut inconditionnel |
Boucles en assembleur
Bon, ceci étant dit, passons à la programmation des boucles en assembleur.
Exemple 1, le for
Pourquoi mettre le test en début de boucle ? Tout simplement pour le cas où on rentrerait dans la boucle avec une valeur
nulle ou négative. Exemple :
for(,bouc<10,bouc++) [...]
|
Ici la variable n'est pas initialisée en début de boucle et elle peut donc contenir n'importe quoi. Il en est de même en
ASM, d'où la nécessité de tester en début de boucle sauf si l'on est certain que l'on doit passer au moins une fois dans la
boucle. Vous pouvez optimiser les algorithmes en utilisant les registres pour contenir les indices de boucles, mais attention
à ne pas utiliser ces registres dans le corps de la boucle (gare aux appels de fonction dans la ROM, entre autres) ou alors
sauvegardez-les sur la pile.
Vous remarquerez que les branchements ont tous le suffixe ".s", ceci afin de travailler en relatif et non pas en absolu.
Explication : "bra étiquette" fait un "jump" à l'adresse 32 bits d'étiquette, alors que "bra.s étiquette" décrémente ou
incrémente le PC de la valeur nécessaire pour que celui-ci contienne la valeur étiquette. La valeur de ce déplacement doit
tenir sur 16 bits en signé. On peut donc se déplacer d'à peu près 32 ko en avant ou en arrière, ce qui est quasiment
toujours suffisant.
Exemple 2, le repeat{...}until(condition)
Exemple 3, le while{condition}{...}
Comme vous avez pu le constater, on a utilisé l'instruction "cmpi", le "i" en plus veut dire immédiat avec une valeur donnée.
Il existe aussi "addi", "subi", etc. (reportez-vous au jeux d'instructions du 68000 dans votre bouquin préféré, moi c'est
"Mise En Oeuvre du 68000" de chez Sybex, un très bon livre sur le 68000 et ses frères ainés, dont le prix est aux alentours
de 240 FF). On aurait pu utiliser "cmp" qui est plus général, de même il existe "cmpa" qui peut être utilisé pour tester les
registres d'adresses.
Enfin, une dernière boucle, le for initialise et décrémente
Cette instruction est très puissante car elle décrémente le registre et se branche à l'étiquette, si la condition est réalisée,
sa syntaxe est donc "dbCC dn,étiquette" (comme bCC). Dans le cas présent, le saut est effectué tant que d0 est >=0
(faites attention au nombre de fois où vous passez dans la boucle, si vous initialisez le registre à "n" vous passerez "n+1"
fois dans la boucle). Remarquez au passage le "moveq" qui est plus rapide qu'un "move.w" mais qui permet seulement de stocker
des opérandes sur 8 bits en signé.
Conclusion
Bon ben voilà, vous connaissez maintenant les bases de la programmation en assembleur. On va pouvoir passer aux choses sérieuses
(ouverture des bibliothèques, des fenêtres, écrans, fichiers et tout le reste).
|