COURS206.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 6 *
******************************************************************
LES AUTO-MODIFICATIONS
Autre chose simple … utiliser et qui facilite beaucoup la program-
mation: les programmes auto-modifiables. Comme tous les sujets
abord‚s jusqu'ici, celui n'est pas compliqu‚ mais demande un peu
d'attention. Je dois cependant avouer que le premiŠre fois que
j'ai rencontr‚ une telle chose dans un listing, de nombreuses heu-
res m'ont ‚t‚ n‚cessaires avant de comprendre ! La principale dif-
ficult‚ r‚sidant non pas dans la compr‚hension du sujet lui-mˆme
mais plut“t dans le choix de la m‚thode d'explication, j'espŠre
que celle-ci vous donnera satisfaction!
Il est tout … fait possible d'imaginer une addition avec des va-
riables. Par exemple A=1, B=2 pour une op‚ration du genre A+B=C
Nous imaginons ‚galement sans mal que les valeurs de A et B puis-
sent changer en cours de programme pour devenir par exemple A=2 et
B=3 ce qui laisse notre op‚ration A+B=C toujours aussi valable.
Mais, comment faire pour que cette op‚ration A+B=C devienne tout …
coup A-B=C ou encore A/B=C ?
L… se fait toute la diff‚rence entre un langage ‚volu‚ et l'assem-
bleur. Nous avons vu, dans les premiers cours, que l'assembleur ne
faisait que traduire en chiffres les instructions. A la diff‚rence
des compilateurs qui 'arrangent' les instructions, l'assembleur ne
r‚alise qu'une traduction, instruction par instruction. Nous nous
retrouvons donc avec une suite de chiffres, ces chiffres ‚tant
dans le 'tube'. Tout comme nous avons ‚crit dans le tube pour
modifier des valeurs donn‚es … des variables, il est donc tout a
fait possible d'‚crire dans le tube pour modifier les chiffres qui
sont en fait des instructions. Il est ‚vident que la prudence
s'impose car les chiffres que nous allons ‚crire doivent ˆtre
reconnus par le 68000 comme une nouvelle instruction et non pas
comme n'importe quoi, ce qui conduirait … une erreur. Voyons
concrŠtement un exemple simple.Nous avons une liste de lettres co-
d‚e en word, et nous voulons afficher ces lettres les unes aprŠs
les autres.
Voici un programme r‚alisant cette op‚ration.
INCLUDE "B:\START.S"
LEA TABLEAU,A6 dans A6 car GEMDOS n'y touche pas
DEBUT MOVE.W (A6)+,D0 pr‚lŠve le word
CMP.W #$FFFF,D0 c'est le flag de fin?
BEQ FIN oui, bye bye
MOVE.W D0,-(SP) non, donc le passe sur la pile
MOVE.W #2,-(SP) pour l'afficher
TRAP #1
ADDQ.L #4,SP
MOVE.W #7,-(SP) attend un appui touche
TRAP #1
ADDQ.L #2,SP
BRA DEBUT et on recommence
FIN MOVE.W #0,-(SP)
TRAP #1
*--------------------------------*
SECTION DATA
TABLEAU DC.W 65,66,67,68,69,70,$FFFF
SECTION BSS
DS.L 100
PILE DS.L 1
END
Imaginons maintenant que cet affichage soit dans une subroutine,
et que nous voulions afficher une lettre … chaque appel de cette
subroutine: On attend un appui sur une touche, si c'est 'espace',
alors on s'en va, sinon on saute … la routine qui affiche un ca-
ractŠre puis revient. Voici un premier essai:
INCLUDE "B:\START.S"
DEBUT MOVE.W #7,-(SP)
TRAP #1
ADDQ.L #2,SP
CMP.W #" ",D0
BEQ FIN
BSR AFFICHE
BRA DEBUT
FIN MOVE.W #0,-(SP)
TRAP #1
*------------------------------*
AFFICHE LEA TABLEAU,A6 adresse du tableau
MOVE.W A6)+,D0 pr‚lŠve le word
MOVE.W D0,-(SP) le passe sur la pile
MOVE.W #2,-(SP) pour l'afficher
TRAP #1
ADDQ.L #4,SP
RTS puis on remonte
*--------------------------------*
SECTION DATA
TABLEAU DC.W 65,66,67,68,69,70,$FFFF
SECTION BSS
DS.L 100
PILE DS.L 1
END
Assemblez et lancez le programme. Constatation: … chaque appui sur
une touche, on obtient un 'A' mais pas les autres lettres!!!
Evidemment, puisqu'… chaque fois que nous sautons dans notre su-
broutine AFFICHE, celle-ci recharge l'adresse du tableau. Le ca-
ractŠre pr‚lev‚ est donc toujours le premier. Pour ‚viter cela, il
faut donc cr‚er un pointeur qui avancera dans ce tableau. Dans no-
tre exemple, il suffisait en fait de placer le LEA TABLEAU,A6 au
d‚but du programme. A6 n'‚tant modifi‚ par personne, cela aurait
fonctionn‚.... jusqu'au 7Šme appui sur une touche, A6 pointant
alors hors du tableau ! De plus, nous sommes ici pour apprendre et
nous envisageons donc le cas o—, en dehors de la routine, tous les
registres sont modifi‚s! Impossible donc de garder A6 comme poin-
teur. Voici donc la routine AFFICHE modifi‚e:
AFFICHE MOVEA.L PTN_TAB,A0
MOVE.W (A0)+,D0
CMP.W #$FFFF,D0
BNE .ICI
LEA TABLEAU,A0
MOVE.L A0,PTN_TAB
BRA AFFICHE
.ICI MOVE.L A0,PTN_TAB
MOVE.W D0,-(SP)
MOVE.W #2,-(SP)
TRAP #1
ADDQ.L #4,SP
RTS
De plus il faut rajouter aprŠs le INCLUDE (donc avant le label
d‚but)
LEA TABLEAU,A0
MOVE.L A0,PTN_TAB
et en section BSS
PTN_TAB DS.L 1
Un peu d'analyse aprŠs ces changements! Tout d'abord nous consta-
tons avec bonheur que ‡a marche! Au d‚but nous mettons en place un
pointeur.
LEA TABLEAU,A0 met l'adresse du tableau en A0
MOVE.L A0,PTN_TAB et la sauve dans PTN_TAB
Nous avons donc maintenant dans le tube en face de l'‚tiquette
PTN_TAB un long mot, ce long mot ‚tant l'adresse du d‚but du ta-
bleau. Ensuite dans la routine, nous pr‚levons cette adresse. Ici
une petite remarque s'impose car la confusion est fr‚quente: Si
nous avons:
IMAGE INCBIN "A:\MAISON.PI1"
et que nous voulons travailler avec cette image, nous ferons
LEA IMAGE,A0
A0 pointera alors sur l'image. Par contre si nous avons :
PTN_IMAG DC.L IMAGE
C'est-…-dire une ‚tiquette pour un long mot se trouvant ˆtre
l'adresse de l'image, en faisant LEA PTN_IMAGE,A0 nous ne r‚cup‚-
rons pas en A0 l'adresse de l'image mais en fait l'adresse de
l'adresse de l'image! Pour r‚cup‚rer directement un pointeur sur
l'image il faut faire:
MOVEA.L PTN_IMAGE,A0
Cependant, pour r‚cup‚rer l'adresse du tableau il aurait ‚galement
‚t‚ possible de faire:
MOVEA.L #TABLEAU,A0
Ceci dit, continuons notre exploration: Dans PTN_TAB nous avons
donc l'adresse du d‚but du tableau. Attente d'un appui touche, hop
on saute dans la routine. Transfert l'adresse contenue dans
PTN_TAB dans A0 puis on pr‚lŠve le word contenu dans le tube …
cette adresse et on le met en D0. Comme nous avons r‚alis‚ cette
op‚ration avec (A0)+, A0 point donc maintenant sur le prochain
word du tableau. Testons si le word pr‚lev‚ est $FFFF, ce qui in-
diquerait la fin du tableau. Si ce n'est pas le cas, on saute …
.ICI et on sauve la nouvelle valeur de A0 dans PTN_TAB.
Si le word pr‚lev‚ est $FFFF, on recharge PTN_TAB avec l'adresse
du haut du tableau, et c'est reparti comme en 14!!!
Ce systŠme de pointeur, trŠs fr‚quemment utilis‚, est simple d'em-
ploi et bien commode! Voyons cependant une autre m‚thode, plus
tordue! Supprimons tout d'abord la routine AFFICHE et rempla‡ons
la par la suivante:
AFFICHE MOVEA.L #TABLEAU,A0
MOVE.W (A0)+,D0
MOVE.W D0,-(SP)
MOVE.W #2,-(SP)
TRAP #1
ADDQ.L #4,SP
RTS
R‚assemblons et lan‡ons. Il est bien ‚vident que cela ne marche
plus puisqu'… chaque appel de la routine, nous rechargeons A0 avec
l'adresse du TABLEAU, donc le word pr‚lev‚ sera toujours le pre-
mier du tableau. Passons sous MONST avec Alt+D. Descendons sur le
label AFFICHE. Nous trouvons en face MOVEA.L #TABLEAU,A0 etc....
Quittons avec control+C puis r‚assemblons, mais attention avant de
cliquer sur 'assembler', jetons un coup d'oeil sur les options.
Nous avons par d‚faut DEBUG INFO indiquant Extend. Cela signifie
que les noms des labels vont ˆtre incorpor‚s dans le programme.
Cela nous permet de retrouver les noms de ces labels lorsque nous
sommes sous MONST. Choisissons l'option NONE pour DEBUG INFO as-
semblons et repassons sous MONST.
Surprise, les noms des labels ont disparu et sont remplac‚s par
des chiffres. C'est logique puisque, de toute fa‡on, l'assembleur
traduit notre source en chiffres. Cherchons notre routine AFFI-
CHAGE. C'est un peu plus dur puisque son ‚tiquette n'est plus vi-
sible! Pour se rep‚rer, on peut chercher au d‚but (aprŠs le start)
CMP.W #$20,D0 qui est la comparaison avec la touche espace aprŠs
l'appui touche. Ensuite, un BEQ vers la fin et le BSR vers notre
routine. Relevons l'adresse situ‚e en face du BSR et allons-y. La
premiŠre ligne de notre routine c'est MOVEA.L #$XXXXXXX,A0 XXXXXXX
‚tant l'adresse du tableau. Je rappelle que sur un 68000 le pro-
gramme peut se trouver n'importe o— en m‚moire, cette adresse sera
donc diff‚rente suivant les machines. Pour ma part c'est $924C6.
J'active la fenˆtre 3 avec Alt+3 puis avec alt+a je demande … la
fenˆtre de se positionner sur cette adresse. MONST m'affiche au
centre les codes ASCII des lettres de mon tableau ($41,$42 etc...)
et … droite ces lettres en 'texte'.
En avan‡ant dans cette routine d'affichage, je vais donc mettre
(pour moi) $924C6 en A0, cette adresse ‚tant celle pointant sur
le 'A' du tableau. Ce qui m'int‚resserait, c'est que, la prochaine
fois, cela me permette de pointer sur le 'B'. Pour cela il
faudrait avoir:
MOVEA.L #$924C6,A0 pour le 'A'
et ensuite
MOVEA.L #$924C8,A0 pour le 'B'.
Les lettres ‚tant sous forme de word dans mon tableau il faut une
avance de 2 !
Retournons dans la fenˆtre 2, en face de ce MOVEA.L, regardons
l'adresse … laquelle il se trouve (colonne de gauche), notons
cette adresse, et notons ‚galement l'adresse de l'instruction sui-
vante (MOVE.W (A0)+,D0). Activons la fenˆtre 3, et pla‡ons nous …
l'adresse du MOVEA.L.
Dans mon cas, et puisque j'avais:
MOVEA.L #$924C6,A0 je trouve 207C 0009 24C6
J'en d‚duis que ces 3 words constituent la repr‚sentation de mon
instruction MOVEA.L, puisque l'adresse du word suivant correspond
… celle de l'instruction suivante. Or, je retrouve dans ce codage,
l'adresse de mon tableau. Avec un peu d'imagination, je con‡ois
ais‚ment qu'il est possible d'‚crire directement dans le 'tube' et
par exemple de modifier le word qui a pour valeur actuelle 24C6.
Si je lui ajoute 2, mon instruction deviendra 207C 0009 24C8 ce
qui reviendra … MOVEA.L #$924C8,A0 et qui me fera pointer sur le
second word du tableau!!!!!!!!
Voici donc la version auto-modifiable de la routine AFFICHE.
AFFICHE MOVEA.L #TABLEAU,A0
MOVE.W A0),D0
CMP.W #$FFFF,D0
BNE ICI
MOVE.L #TABLEAU,AFFICHE+2
BRA AFFICHE
.ICI ADD.W #2,AFFICHE+4
MOVE.W D0,-(SP)
MOVE.W #2,-(SP)
TRAP #1
ADDQ.L #4,SP
RTS
Note: PTN_TAB ne nous sert plus, et de mˆme le LEA tableau du
d‚but.
Assemblez avec NONE en DEBUG INFO, puis passez sous MONST, faites
avancer pas … pas et regardez la ligne
MOVEA.L #TABLEAU,A0 se modifier!
Expliquons bien clairement ce qui se passe.
Nous pla‡ons TABLEAU en A0 puis nous pr‚levons le word. Admettons
tout d'abord qu'il ne s'agisse pas de $FFFF, nous sautons donc …
.ICI. Il faut donc ajouter 2 pour augmenter l'adresse et pointer
la prochaine fois sur la seconde lettre du tableau. Nous avons vu
qu'en ‚tant cod‚e la ligne MOVEA.L etc... tient sur 3 words donc 6
bytes. L'ajout de 2 doit donc porter sur le 3Šme word. Le d‚but de
ce word c'est le byte 4. Pour cette raison nous donnons comme des-
tination de l'addition AFFICHE+4.
Si nous avions pr‚lev‚ $FFFF, il aurait fallu r‚initialiser notre
ligne MOVEA.L avec
MOVE.L #TABLEAU,AFFICHE+2.
Pourquoi +2 ? Parce que l'adresse de tableau est un long mot et
que, dans le codage de l'instruction, cela commence sur le second
word. Il faut donc sauter un seul word c'est-…-dire 2 bytes.
Dans le mˆme ordre de chose, il est tout … fait possible de modi-
fier plus profond‚ment un programme. En voici un exemple flagrant.
(voir listing num‚ro 4)
Sachant que l'instruction RTS (Return from subroutine) est cod‚e
avec $4E75 et que l'instruction NOP (No operation) est cod‚e par
$4E71, en pla‡ant un NOP ou un RTS, on change en fait la fin de la
routine. NOP ne fait rien du tout. C'est une op‚ration qui est bi-
don dans le sens o— rien ne change, mais cette instruction
consomme un peu de temps. Elle nous servira donc pour r‚aliser des
petites attentes (bien utile pour des effets graphiques par exem-
ple).
Suivez bien le d‚roulement de ce programme sous MONST afin de voir
les modifications se faire. Un cas plus complexe:
MOVE.W #23,D0
MOVE.W #25,D1
VARIANTE ADD.W D0,D1
MULU.W #3,D1
SUB.W #6,D1
MOVE.W D1,D5
AprŠs assemblage de ce petit morceau de programme, passez sous
MONST et jetez un coup d'oeil … la fenˆtre 3. En pointant sur
VARIANTE et en regardant les adresses en face des instructions, on
en d‚duit que:
ADD.W D0,D1 est converti en $D240
MULU.W #3,D1 est converti en $C2FC $0003
SUB.W #6,D1 est converti en $0441 $0006
Si nous prenons maintenant:
MOVE.W #23,D0
MOVE.W #25,D1
VARIANTE MULU.W D0,D1
SUB.W #8,D1
ADD.W #4,D0
MOVE.W D1,D5
Nous assemblons, passons sous MONST:
MULU.W D0,D1 est converti en $C2C0
SUB.W #8,D1 est converti en $0441 $0008
ADD.W #4,D0 est converti en $0640 $0004
Donc, si dans un programme utilisant cette 'routine' je fais
LEA VARIANTE,A0
MOVE.W #$D240,(A0)+
MOVE.L #$C2FC0003,(A0)+
MOVE.L #$04410006,(A0)+
J'obtiendrai la premiŠre version:
ADD.W D0,D1;
MULU.W #3,D1;
SUB.W #6,D1
alors que si je fais:
LEA VARIANTE,A0
MOVE.W #$C2C0,(A0)+
MOVE.L #$04410008,(A0)+
MOVE.L #$06400004,(A0)+
j'obtiendrai la seconde version!
Essayez avec le programme ci-aprŠs, en le suivant sous MONST:
Note: ce programme n'a pas de fin donc quitter avec Control+C:
LEA VARIANTE,A0
MOVE.W #$D240,(A0)+
MOVE.L #$C2FC0003,(A0)+
MOVE.L #$04410006,(A0)+
LEA VARIANTE,A0
MOVE.W #$C2C0,(A0)+
MOVE.L #$04410008,(A0)+
MOVE.L #$06400004,(A0)+
MOVE.W #23,D0
MOVE.W #25,D1
VARIANTE MULU.W D0,D1
SUB.W #8,D1
ADD.W #4,D0
MOVE.W D1,D5
END
Remarques: Il est tout … fait possible d'envisager plus de 2 ver-
sions d'une mˆme partie de programme. Si les tailles de ces diff‚-
rentes versions diffŠrent, ce n'est pas grave car il est toujours
possible de combler avec des NOP. Les applications de ce genre de
'ruse' peuvent ˆtre assez nombreuses: raccourcissement de program-
mes, rapidit‚ (une routine devant ˆtre appel‚e 15000 fois aura
tout int‚rˆt … ˆtre modifi‚e avant, au lieu d'y incorporer des
tests, par exemple), modifications al‚atoires des routines de pro-
tection (un coup, j'en mets une en place la prochaine fois, j'en
mettrai une autre...)....
Faites cependant bien attention, car une erreur d'un chiffre et le
nouveau code mis en place ne voudra plus rien dire du tout! Faites
‚galement attention … vos commentaires car l…, ils deviennent
hyper importants, ‚tant donn‚ que le listing que vous avez sous
les yeux ne sera pas forc‚ment celui qui sera ex‚cut‚!!!!!!!
Back to ASM_Tutorial