COURS205.TXT
Jump to navigation
Jump to search
******************************************************************
* *
* COURS D'ASSEMBLEUR 68000 SUR ATARI ST *
* *
* par Le F‚roce Lapin (from 44E) *
* *
* Seconde s‚rie *
* *
* Cours num‚ro 5 *
******************************************************************
AprŠs ce cours sur les macros, nous allons passer … l'usage des
tableaux en assembleur. J'espŠre qu'aprŠs chaque cours vous
effectuez vous-mˆme des recherches et des exercices, et que vous
ne vous pr‚cipitez pas tout de suite sur le cours suivant. Mˆme
si les cours vous semblent maintenant courts par rapport … ceux
de la premiŠre s‚rie, il n'en soulŠvent pas moins le voile sur de
nombreux sujets. Vous avez maintenant le niveau pour les
approfondir et j'espŠre que vous le faites!
LES TABLEAUX
L'usage des tableaux n'est pas trŠs r‚pandu en assembleur au
niveau des programmeurs d‚butants. En effet le systŠme peut
sembler assez p‚rilleux … manipuler mais s'avŠre par contre trŠs
puissant et trŠs commode!
Tout comme le principe de la pile, celui des tableaux est simple
mais demande beaucoup de logique pour pouvoir fonctionner
convenablement. Prenons tout d'abord un exemple simple: nous
allons appuyer sur les touches de fonctions F1 jusqu'… F10 et …
chaque fois nous allons afficher une lettre. Commen‡ons par un
exemple sans tableau.
Voir le listing num‚ro 2.
Au d‚part INCLUDE de la routine de d‚marrage de programme ‚tudi‚e
au d‚but de la seconde s‚rie. Pr‚sentation avec un petit message,
puis attente d'un appui sur une touche. Comme nous voulons tester
les touches de fonctions et que celles-ci n'ont pas de code
ASCII, nous profitons du fait que la fonction Gemdos 7 retourne
dans le poids faible de D0 le code ASCII mais aussi dans le poids
fort le scan code. Il n'y a d'ailleurs pas que ‡a de retourn‚, car
si vous consultez la bible ST ou simplement la description des
fonctions dans les derniŠres pages de la doc du GFA 3.00, vous y
apprenez que Gemdos 7 renvoi dans les bits 0-7 le code ASCI,
16-23 le code clavier et 24-31 l'‚tat des touches de commutations
du clavier.
Petit rappel sur les codes ASCII et les scan code. Les codes
ASCII (American Standard Code for Information Interchange) sont
des codes sur 7 bits, qui suivent l'ordre alphab‚tique. Ce
standard est aussi appelle Code t‚l‚graphique international
num‚ro 5. Le 8 Šme bit est un bit de parit‚ c'est … dire qu'il ne
sert qu'… la v‚rification de la bonne transmission du code. De
part le fait que ce systŠme est Am‚ricain, le codage ASCII ne
prend pas en compte les accents ni les caractŠres du type c
c‚dille. Cependant notre ordinateur n'ayant pas besoin de ce
huitiŠme bit pour v‚rifier les transmissions, celui-ci est
utilis‚ pour augmenter le nombre de combinaison possible. Retour
au cours 2 de la s‚rie 1, sur les chiffres magiques: avec 7 bits
nous pouvons compter de 0 … 127, un bit de plus nous permet de
compter de 0 … 255. Consulter un tableau des codes ASCII (bible,
livre du d‚veloppeur, doc GFA etc...) et vous vous rendrez compte
que tous les signes 'bizarres' sont cod‚s sur 8bits et ont donc
des codes sup‚rieurs … 127.
Cependant les codes ASCII ne suffisent pas. Imaginez que je tape
sur la touche A de mon clavier. En code ASCII je vais recevoir
65. Mais si un Anglais tape sur la mˆme touche, pour lui ce sera
un Q et il recevra le code ASCII 81. Le code ASCII ne d‚pend donc
pas de la touche, m‚caniquement parlant, mais plut“t de la lettre
de cette touche. Il existe un autre codage qui lui correspond aux
touches d'un point de vue m‚canique. C'est ce que l'on appelle le
scan-code.
Pour le scan-code, une touche possŠde un num‚ro, totalement
ind‚pendant de la lettre qui sera affect‚e … cette touche. Ainsi
la touche A de votre clavier renvoi le scan-code $10, et il en
est de mˆme pour tous les ST du monde, que cette touche soit
marqu‚e "A", ou "Q". C'est l'emplacement sur le clavier qui
compte.
Nous testons donc le scan-code de la touche sur laquelle nous
avons appuy‚. Si c'est Escape, nous sortons du programme.
Autrement, nous allons tester s'il s'agit d'une touche de
fonction. La touche F1 a pour scan-code $3B, F2->$3C, F3->$3D
etc... jusqu'… F10->$44. Les scan-codes se suivant, nous testons
donc notre r‚sultat par rapport au scan-code de F1, si c'est
inf‚rieur ce n'est donc pas valable, de mˆme par rapport au
scan-code de F10: si c'est sup‚rieur ce n'est pas valable non
plus.
Ces tests ‚tant faits, nous sommes donc en pr‚sence d'un scan-code
situ‚ entre $3B et $44, ces 2 nombres compris. $3B, cela fait 59
en d‚cimal. Pour avoir 65 (code ASCII de A) il suffit d'ajouter
6. C'est que nous faisons ensuite. Nous obtenons donc le code
ASCII de A, B, C etc... suivant la touche de fonction qui a ‚t‚
enfonc‚e. Il ne reste plus qu'… afficher cette lettre!
Imaginons maintenant que nous voulions afficher "touche F1"
lorsque nous appuyons sur cette touche, "touche F2", etc....
Plusieurs solutions s'offrent … nous. En voici une premiŠre qui me
vient … l'esprit et que je vais juste vous d‚voiler car elle n'a
pas de rapport avec les tableaux. Pour ne pas compliquer, nous
n'afficherons pas "touche F10", en fait nous ne prendrons en
compte que les touches F1-F9. Souvenez vous d'un des listing de
la s‚rie 1. Celui qui affichait une phrase en faisant apparaŒtre
les lettres comme sur les affichages des gares ou des
a‚roports.Reprenez donc un peu ce listing (c'‚tait le
num‚ro 3) et souvenez-vous de ce qui se passait pour la
phrase situ‚e … l'adresse TXT. Nous affichions cette phrase
mais auparavant elle ‚tait modifi‚e … l'adresse colonne et …
l'adresse lettre.
Dans la cas pr‚sent il suffit de faire … peu prŠs la mˆme chose.
Pr‚parons une phrase ainsi:
TXT DC.B "TOUCHE F"
NUMERO DC.B " ",13,10,0
A chaque appui sur une touche de fonction, nous retirons 10 (en
d‚cimal) au scan-code, et nous mettons le r‚sultat … l'adresse
NUMERO. Ainsi le scan-code de la touche F1 ($3B donc 59 en
d‚cimal) deviendra 49 qui est le code ASCII de la lettre '1'.
Nous verrons donc s'afficher 'TOUCHE F1'.
R‚alisez ce programme avant de passer … la suite, cela vous fera
un excellent exercice!!!!
Passons maintenant au tableau, en modifiant un peu l'affichage.
Un appui sur: affichera:
F1 A
F2 Z
F2 E
F4 R
F5 T
F6 Y
F7 U
F8 I
F9 O
F10 P
PremiŠre constatation: si les scan-code des touches se suivent
toujours, on peut dire que le lien logique entre les lettres
affich‚es est un peu l‚ger...
Prenez le listing num‚ro 3, et commen‡ons … l'‚tudier. Tout le
d‚but, jusqu'au commentaire 'la touche est valable', est
strictement identique au listing pr‚c‚dent. Ensuite nous attaquons
la partie utilisant le tableau. L'adresse de celui-ci est pass‚e
en A0 (Load Effective Adress), ensuite on retire $3B … D0 afin
que celui-ci ait une valeur de 0 … 9. Le tableau que nous
utilisons est compos‚ de Words. Or, un word c'est 2 bytes,
et la m‚moire est compos‚ de bytes. Pour se d‚placer dans un
tableau en word alors que notre unit‚ c'est le byte, il faut donc
se d‚placer de 2 en 2. Il ne faut donc pas que notre 'compteur',
qui est ici D0, prenne une valeur du type 0,1,2,3,4 etc...
mais plut“t une valeur telle que 0,2,4,6,8...
Puisqu'… la suite de nos op‚rations nous avons D0 avec une valeur
du type 0,1,2,3,4... il faut maintenant le multiplier par 2. Cela
se fait par l'op‚ration MULU qui se lit Multiply Unsigned. En
effet c'est une multiplication non-sign‚e, c'est-…-dire qu'elle
ne prend pas en compte le signe de ce qui est multipli‚,
contrairement … l'op‚ration MULS (Multiply signed).
Maintenant, observons bien cette instruction:
MOVE.W 0(A0,D0.W),D0
Il s'agit d'un MOVE donc d'un d‚placement. Il se fait sur un word
puisque nous avons .W Ce MOVE va prendre le D0 iŠme word de A0
pour le mettre dans D1. Ainsi, si nous appuyons sur F3, nous
obtenons $3D. Nous retirons $3B et nous obtenons 2, nous
multiplions par 2, et donc D0 vaut maintenant 4. Nous allons donc
pointer sur le 4Šme byte de A0 et pr‚lever un word … partir de
cet endroit. Le d‚placement est en effet toujours compt‚ avec un
nombre de bytes, que le tableau soit en byte, en word ou en long.
C'est un peu comme si vous vous d‚placiez dans une rue avec des
petites maisons, des moyennes ou des grandes, le d‚placement se
comptera toujours en mŠtres.
Mais que signifie le 0 devant la parenthŠse ? Et bien c'est la
valeur d'un d‚placement fixe … ajouter. Prenons un exemple: Nous
avons un tableau dans lequel on 'tape' suivant un chiffre qui
nous est fourni par un appui sur une touche. Seulement on doit
pr‚lever des choses diff‚rentes si la touche est appuy‚e alors
que SHIFT est enfonc‚e. Il est alors possible de se dire: si
shift n'est pas enfonc‚ alors se sont les premiers ‚l‚ments du
tableau qui seront pris en compte, mais avec shift ce seront les
‚l‚ments de la fin. On pourra alors faire:
MOVE.W 0(A0,D0.W),D1 ou bien si shift est appuy‚,
MOVE.W 18(A0,D0.W),D1. Ceci revient … prendre le D0 iŠme word
de A0, en commen‡ant … compter … 18 bytes du d‚but de A0.
Il faut cependant se m‚fier de plusieurs choses concernant les
tableaux. Tout d'abord bien faire attention au type de donn‚es du
tableau afin de bien modifier le 'compteur' en cons‚quence.
Ensuite bien faire attention au fait que le premier ‚l‚ment c'est
l'‚l‚ment 0 et non pas le 1. Nous avions d‚j… vu dans les tous
premiers cours de la s‚rie 1 les problŠmes pouvant survenir
lorsque l'on compte, en oubliant parfois le 0. Ce problŠme est
d'autant plus gˆnant avec les tableaux que, si au lieu de retirer
$3B dans mon exemple pour avoir un chiffre de 0 … 9, je n'avais
retir‚ que $3A et ainsi obtenu 1 … 10, mon programme aurait
parfaitement fonctionn‚. Il aurait simplement affich‚ n'importe
quoi … la suite d'un appui sur F10. Or si vous avez un tableau de
200 ‚l‚ments que vous appelez avec les touches, les touches+
shifts, +control etc... la v‚rification touche par touche sera
peut ˆtre laiss‚e de cot‚... Dans notre exemple, nous avons
utilis‚ des words dans notre tableau. Il aurait tout … fait ‚t‚
possible d'utiliser des bytes.
Modifiez un peu le programme: supprimer la ligne avec MULU, et
modifiez les datas. Au lieu de mettre DC.W … l'adresse TABLEAU,
mettez DC.B. Pour terminer, puisque notre tableau est maintenant
en bytes et non plus en words,il faut modifier l'adressage
permettant de piocher dedans. Au lieu de MOVE.W 0(A0,D0.W),D1 il
faut mettre maintenant MOVE.B 0(A0,D0.W),D1
Attention cependant car nous avions parl‚ de l'impossibilit‚ de se
servir des adresses impaires. Pourtant, dans ce dernier cas,
comme notre tableau est en bytes, si D0 vaut 3, nous nous retrou-
vons avec une adresse impaire, et pourtant ‡a marche! En effet
cela marche parce que nous pr‚levons un byte. En fait, le 68000
peut trŠs bien pr‚lever un byte … une adresse impaire, en
revanche, ce qu'il ne peut pas faire c'est pr‚lever une donn‚e
plus grande (word ou long) qui commence sur une adresse impaire et
qui donc chevauche les emplacements 'normaux'. Modifions encore
une fois le programme. Remettez le tableau en word, et remettez
l'adressage en word (MOVE.W 0(A0,D0.W),D1). L'erreur va donc
venir du fait que nous avons oubli‚ le MULU, et donc que notre
compteur va ˆtre parfois impaire alors que notre tableau et notre
mode d'adressage demande un compteur paire.
Assemblez et lancez. Appuyez sur F1: tout ce passe bien! Normal,
D0 aprŠs retrait de $3B, vaut 0 qui est donc pair. Appuyez sur
F3: mˆme chose car D0 vaut 2. Par contre, un appui sur F2 se solde
par 3 bombes et le retour … DEVPACK. D‚buggons donc notre pro-
gramme: alternate+D, et descendons jusqu'… la ligne:
MOVE.W 0(A0,D0.W),D1
Pla‡ons cette ligne en haut de la fenˆtre 1 et tapons control+B
Un breakpoint s'y met. Lan‡ons avec control+R, et tapons sur la
touche F2. Breakpoint, nous revoici sous MONST. En regardant la
valeur de A0 nous connaissons l'adresse de notre tableau, adresse
paire en l'occurrence. Par contre, si vous avez appuyez sur F2,
vous devez avoir 1 comme valeur de D0, donc une valeur impaire.
Avancez d'un pas sur MOVE.W 0(A0,D0.W),D1 … l'aide Control+Z.
Erreur d'adresse! Il ne vous reste plus qu'… quitter par
Control+C.
Bon, nous avons vu comment pr‚lever un word ou un byte dans un
tableau. Avec un tout petit peu d'intelligence vous devez ˆtre
capable de pr‚lever un long mot (au lieu de faire un MULU par 2
on en fait un par 4). Prenons un peu de recul et rappelons nous
des cours pr‚c‚dents: nous y avons ‚tudi‚ le principe de ce
'tube', de cette m‚moire que nous commen‡ons … utiliser
abondamment. Si vous avez un peu de m‚moire justement, vous devez
vous rappeler d'une remarque faite au tout d‚but, disant qu'il
fallait bien se m‚fier de confondre contenu du tube et adresse de
ce contenu. Il est en effet tout … fait possible d'avoir
IMAGE incbin A:\MAISON.PI1"
PTN_IMAGE DC.L IMAGE
A l'adresse IMAGE, nous trouvons dans le tube l'image elle-mˆme,
mais … l'adresse PTN_IMAGE, nous trouvons un long mot, qui se
trouve ˆtre l'adresse de l'image. Avec un peu d'imagination, nous
pouvons donc imaginer un tableau compos‚ de long mot, ces longs
mots ‚tant des adresses d'images, de textes, mais aussi (pourquoi
pas!) de routines!!!!!!
Voici le squelette d'un programme r‚alisant une telle chose: Au
d‚part, mˆme chose que pr‚c‚demment, attente d'un appui touche,
v‚rification de la validit‚ de la touche, on trafique pour avoir
un code du type 0,1,2,3,4... puis on le mulu par 4 puisque notre
tableau va ˆtre compos‚ de long mot.
LEA TABLEAU,A0
MOVE.L 0(A0,D0.W),A0
JSR (A0)
BRA DEBUT et on recommence
Nous faisons un JSR (jump subroutine) au lieu d'un BSR. Pourquoi?
essayez, et regardez l'annexe sur les instructions pour voir les
diff‚rences entre les 2 instructions!!!
Mais de quoi est compos‚ notre tableau? eh bien, par exemple
TABLEAU DC.L TOUT_VERT
DC.L TOUT_BLEU
DC.L QUITTER
DC.L DRING
DC.L COUCOU
etc....
Toutes ces entr‚es ‚tant les adresses des routines. Par exemple
COUCOU move.l #message,-(sp)
move.w #9,-(sp)
trap #1
addq.l #6,sp
rts
La routine TOUT_VERT met toute la palette en vert etc....
Il est de mˆme possible de mettre en tableau des adresses de
phrases et de passer l'adresse "pioch‚e" … une routine qui affiche
avec gemdos(9) par exemple.
Une derniŠre chose, qui est plus proche du systŠme de liste que de
celui de tableau, mais qui est aussi bien utile. Nous avons ‚tudi‚
ici des possibilit‚s ‚manant toujours d'une mˆme ‚vidence:
les donn‚es qui nous servent … pointer dans le tableau, se
suivent ! Malheureusement dans de nombreux cas, celles-ci ne se
suivent pas...
Voici donc une autre m‚thode: Imaginons le cas d'un ‚diteur de
texte, avec plusieurs actions possibles (effacer le texte, sauver
le texte, l'imprimer, charger, ‚craser, scroller etc...) appel‚es
par des combinaisons de touches. Pour ˆtre … la norme Wordstart
(c'est la norme clavier utilis‚e par Devack: ALT+W=imprimer par
exemple), j'ai d'abord relev‚ avec un tout petit programme, les
codes renvoy‚s par les combinaisons de touches Ensuite j'ai
r‚alis‚ une liste de ces codes, liste en word car les codes ASCII
ne suffisent plus dans le cas de combinaisons de touches (il est
possible bien s–r de construire la combinaison touche enfonc‚e/-
touche de control).
TAB_CODE dc.w $1519,$1615,$1312,$2e03,$FFFF
Ensuite j'ai r‚alis‚ une liste avec les adresses de mes routines.
Comme au d‚part je n'en avais aucune de faite, j'en ai r‚alis‚ une
'bidon', nomm‚e JRTS et qui ne fait.... qu'RTS!
TAB_ROUTINE dc.l JRTS,JRTS,JRTS,JRTS
Ensuite j'ai fait une boucle pour lire TAB_CODE, en comparant, …
chaque fois, la valeur trouv‚e dans le tableau avec celle de la
touche. En mˆme temps je parcours TAB_ROUTINE afin qu'au moment o—
je lis le 3Šme ‚l‚ment de TAB_CODE, je sois en face du 3 Šme ‚l‚-
ment de TAB_ROUTINE.
Voici le module. D7 contient le word correspondant … la touche ou
… la combinaison de touche.
LEA TAB_CODE,A0
LEA TAB_ROUTINE,A1
.ICI MOVE.W (A0)+,D0
CMP.W #$FFFF,D0
BEQ DEBUT
MOVE.L (A1)+,A2
CMP.W D0,D7
BNE .ICI
JSR (A2)
BRA DEBUT
L'adresse de la liste des codes est mise en A0 et celle des
adresses de routines en A1. On pr‚lŠve un word de code.
C'est $FFFF? si c'est le cas, c'est donc que nous sommes en fin de
liste donc on se sauve puisque la touche choisit n'est pas
valable. Sinon on pr‚lŠve l'adresse dans le tableau des adresses
de routines. Le code du tableau est-il le mˆme que celui de la
touche ? Non, on boucle (notez ici le point devant le label. Cela
indique que le label est local. L'assembleur le rapportera au
label le plus proche portant ce nom. Il est ainsi possible d'avoir
plusieurs label .ICI dans un programme, ou tout autre nom
pourvu qu'il soit pr‚c‚d‚ d'un point. Dans le cas de petites
boucles par exemple, cela ‚vite de chercher des noms de labels
tordus!!!).
Puisque le code est identique … celui de la touche, on saute vers
la routine, et au retour, on recommence.
Les avantages de cette m‚thode sont multiples. Tout d'abord la
petite taille de la routine de test: s'il avait fallu r‚aliser des
tests du genre:
cmp.w #$1519,d7
bne.s .ici1
bsr truc
bra d‚but
.ici1 cmp.w #$1615,d7
bne.s .ici2
bsr truc2
bra d‚but
.ici2
etc.... la taille aurait ‚t‚ sup‚rieure, surtout que dans l'exem-
ple il n'y a que 4 codes... Imaginez avec une trentaine!!! L'autre
avantage concerne la mise au point du programme. En effet rien
n'empˆche de pr‚voir plein de routines mais de simplement mettre
l'adresse d'un RTS, et progressivement de construire ces routines.
Rien n'empˆchera pour autant le programme de marcher. De mˆme, le
systŠme du flag de fin ($FFFF) permet de rajouter trŠs facilement
des codes et donc des routines.
Voila pour les listes et tableaux!! les applications sont innom-
brables et permettent souvent en peu de lignes des tests, des
recherches, des calculs, des conversions ou des branchements
r‚alisables autrement mais au prix de difficult‚s immenses!
Voici des id‚es d'applications:
codage de texte (utilisation du code ASCII pour pointer dans un
tableau donnant la valeur … substituer)
animation (tableau parcouru s‚quentiellement donnant les adresses
des images … afficher)
gestion de touches
gestion de souris (tableau avec les coordonn‚es des zones ‚cran)
menu d‚roulant
etc...
Back to ASM_Tutorial