Quel curieux titre, surtout que j'aurais du écrire "macro à répétition".
Hein? Mais de quoi il nous parle sam, il a pété une durite?
Non non, c'est un sujet bien sérieux. En fait je voulais parler de l'optimisation consistant à répéter le même code plein de fois en mémoire (déroulage de boucle).
L'idée première est de bêtement copier/coller le code de la boucle (instruction1...instruction100) autant de fois qu'il faut.
Code:
instruction1
instruction2
...
instruction100
instruction1
instruction2
...
instruction100
...
instruction1
instruction2
...
instruction100
Cette solution marche mais n'est pas très glorieuse. Si on veut remplacer instruction3 par instr3bis il faut repasser sur toutes les répétitions et n'en manquer aucune.
Le bon refexe est alors d'utiliser une macro et un macro-processeur (c6809 ou assembleur v3)
Code:
CODE macro
instruction1
instruction2
...
instruction100
endm
CODE
CODE
...
CODE
C'est mieux! il ne suffit de remplacer instruction3 que dans la définition de la macro.
Ok, c'est tout? C'est pas une nouveauté d'utiliser le macro-processeur pour ca.
Oui je sais, mais on peut l'utiliser encore mieux.
Petite question: comment faites vous lorsque CODE est répété disons 150 fois et qu'à présent il n'en faut plus que 112? Réponse: Ben on efface les 150-112=14x, heuu 13x.. non (trop chiant la soustraction), on efface tout les 150 et on en recopie 112. Pas terrible pour la maintenance n'est-ce pas.
En fait j'ai une solution rigolote. Moi je fais juste
Code:
REP 112,CODE
Bon ok, vous l'avez compris "REP n,macro" est une macro qui répète n fois une autre macro. Facile! Non pas tant que ca. Essayez d'écrire une telle macro. C'est pas facile il n'y a pas d'instruction de boucle dans les macros.
On peut essayer de faire une macro qui s'appelle elle même en incrémentant un compteur externe
Code:
cpt set 0
REP macro
\1
cpt set cpt+1
ifne cpt-\0
REP \0,\1
endc
endm
Mais on butte assez vite sur une profondeur de récursion limitée (que je suppose autour de 8), et l'évaluation de cpt=cpt+1 est lente. Il ne faut pas non plus oublier de le ré-initialiser à 0 avant d'appeler REP, sinon on est parti pour une boucle sans fin. Autre soucis comment fait-on pour pouvoir générer des étiquettes différentes. En effet, on ne peut concaténer la valeur de cpt à un label: lbl<cpt> car l'assembleur ne l'autorise pas. On peut essayer de ruser en passant cpt en 3eme argument, mais lbl\2 ne se transforme pas en lbl1 lbl2 lbl3, mais en plein de lblcpt identiques. En effet c'est le symbole cpt et pas sa valeur qui est passée en 3eme argument. Bref ca marche pas
![:(](./images/smilies/triste.gif)
C'est fichu alors?
Et bien non, j'ai trouvé une construction de REP qui fait le taf en évitant tous ces écueils
Code:
REP MACRO
IF (\0)&1
\1 \2
ENDC
IFGE (\0)-1
REP (\0)<-1,\1,O\2
REP (\0)<-1,\1,X\2
ENDC
ENDM
La limitation de récursion est contournée par un appel récursif double, ce qui fait une profondeur bien plus petite. Pour répéter n fois, il ne faut pas descendre n fois en profondeur (exemple 64), mais log(n)/log(2) fois (donc 5 fois pour compter 64 fois). Avec une limitation de 8 en profondeur de récursion on peut compter jusqu'à 256. Si on veut un label généré, il faut utiliser l'argument passée à la macro qui est un symbole à base de O et X représentant une sorte de comptage binaire qui ne se répète jamais.
Code:
CODE1 macro
lbl\0
inca un code idiot pour illustrer
decb
endm
CODE2 macro
fcb lbl\0
endm
REP 5,CODE1
REP 5,CODE2
donne
Code:
acro Pass
Pass1
Pass2
2 9000 ORG $9000
3
4 REP MACRO
5 IF (\0)&1
6 \1 \2
7 ENDC
8 IFGE (\0)-1
9 REP (\0)<-1,\1,O\2
10 REP (\0)<-1,\1,X\2
11 ENDC
12 ENDM
13
14 CODE1 macro
15 lbl\0
16 inca un code idiot pour illustrer
17 decb
18 endm
19 CODE2 macro
20 fdb lbl\0
21 endm
5 IF (5)&1
15 9000 lbl
16 2 9000 4C inca un code idiot pour illustrer
17 2 9001 5A decb
7 ENDC
8 IFGE (5)-1
5 IF ((5)<-1)&1
6 CODE1 O
7 ENDC
8 IFGE ((5)<-1)-1
5 IF (((5)<-1)<-1)&1
15 9002 lblOO
16 2 9002 4C inca un code idiot pour illustrer
17 2 9003 5A decb
7 ENDC
8 IFGE (((5)<-1)<-1)-1
5 IF ((((5)<-1)<-1)<-1)&1
6 CODE1 OOO
7 ENDC
8 IFGE ((((5)<-1)<-1)<-1)-1
9 REP ((((5)<-1)<-1)<-1)<-1,CODE1,OOOO
10 REP ((((5)<-1)<-1)<-1)<-1,CODE1,XOOO
11 ENDC
5 IF ((((5)<-1)<-1)<-1)&1
6 CODE1 XOO
7 ENDC
8 IFGE ((((5)<-1)<-1)<-1)-1
9 REP ((((5)<-1)<-1)<-1)<-1,CODE1,OXOO
10 REP ((((5)<-1)<-1)<-1)<-1,CODE1,XXOO
11 ENDC
11 ENDC
5 IF (((5)<-1)<-1)&1
15 9004 lblXO
16 2 9004 4C inca un code idiot pour illustrer
17 2 9005 5A decb
7 ENDC
8 IFGE (((5)<-1)<-1)-1
5 IF ((((5)<-1)<-1)<-1)&1
6 CODE1 OXO
7 ENDC
8 IFGE ((((5)<-1)<-1)<-1)-1
9 REP ((((5)<-1)<-1)<-1)<-1,CODE1,OOXO
10 REP ((((5)<-1)<-1)<-1)<-1,CODE1,XOXO
11 ENDC
5 IF ((((5)<-1)<-1)<-1)&1
6 CODE1 XXO
7 ENDC
8 IFGE ((((5)<-1)<-1)<-1)-1
9 REP ((((5)<-1)<-1)<-1)<-1,CODE1,OXXO
10 REP ((((5)<-1)<-1)<-1)<-1,CODE1,XXXO
11 ENDC
11 ENDC
11 ENDC
5 IF ((5)<-1)&1
6 CODE1 X
7 ENDC
8 IFGE ((5)<-1)-1
5 IF (((5)<-1)<-1)&1
15 9006 lblOX
16 2 9006 4C inca un code idiot pour illustrer
17 2 9007 5A decb
7 ENDC
8 IFGE (((5)<-1)<-1)-1
5 IF ((((5)<-1)<-1)<-1)&1
6 CODE1 OOX
7 ENDC
8 IFGE ((((5)<-1)<-1)<-1)-1
9 REP ((((5)<-1)<-1)<-1)<-1,CODE1,OOOX
10 REP ((((5)<-1)<-1)<-1)<-1,CODE1,XOOX
11 ENDC
5 IF ((((5)<-1)<-1)<-1)&1
6 CODE1 XOX
7 ENDC
8 IFGE ((((5)<-1)<-1)<-1)-1
9 REP ((((5)<-1)<-1)<-1)<-1,CODE1,OXOX
10 REP ((((5)<-1)<-1)<-1)<-1,CODE1,XXOX
11 ENDC
11 ENDC
5 IF (((5)<-1)<-1)&1
15 9008 lblXX
16 2 9008 4C inca un code idiot pour illustrer
17 2 9009 5A decb
7 ENDC
8 IFGE (((5)<-1)<-1)-1
5 IF ((((5)<-1)<-1)<-1)&1
6 CODE1 OXX
7 ENDC
8 IFGE ((((5)<-1)<-1)<-1)-1
9 REP ((((5)<-1)<-1)<-1)<-1,CODE1,OOXX
10 REP ((((5)<-1)<-1)<-1)<-1,CODE1,XOXX
11 ENDC
5 IF ((((5)<-1)<-1)<-1)&1
6 CODE1 XXX
7 ENDC
8 IFGE ((((5)<-1)<-1)<-1)-1
9 REP ((((5)<-1)<-1)<-1)<-1,CODE1,OXXX
10 REP ((((5)<-1)<-1)<-1)<-1,CODE1,XXXX
11 ENDC
11 ENDC
11 ENDC
11 ENDC
5 IF (5)&1
20 900A 9000 fdb lbl
7 ENDC
8 IFGE (5)-1
5 IF ((5)<-1)&1
6 CODE2 O
7 ENDC
8 IFGE ((5)<-1)-1
5 IF (((5)<-1)<-1)&1
20 900C 9002 fdb lblOO
7 ENDC
8 IFGE (((5)<-1)<-1)-1
5 IF ((((5)<-1)<-1)<-1)&1
6 CODE2 OOO
7 ENDC
8 IFGE ((((5)<-1)<-1)<-1)-1
9 REP ((((5)<-1)<-1)<-1)<-1,CODE2,OOOO
10 REP ((((5)<-1)<-1)<-1)<-1,CODE2,XOOO
11 ENDC
5 IF ((((5)<-1)<-1)<-1)&1
6 CODE2 XOO
7 ENDC
8 IFGE ((((5)<-1)<-1)<-1)-1
9 REP ((((5)<-1)<-1)<-1)<-1,CODE2,OXOO
10 REP ((((5)<-1)<-1)<-1)<-1,CODE2,XXOO
11 ENDC
11 ENDC
5 IF (((5)<-1)<-1)&1
20 900E 9004 fdb lblXO
7 ENDC
8 IFGE (((5)<-1)<-1)-1
5 IF ((((5)<-1)<-1)<-1)&1
6 CODE2 OXO
7 ENDC
8 IFGE ((((5)<-1)<-1)<-1)-1
9 REP ((((5)<-1)<-1)<-1)<-1,CODE2,OOXO
10 REP ((((5)<-1)<-1)<-1)<-1,CODE2,XOXO
11 ENDC
5 IF ((((5)<-1)<-1)<-1)&1
6 CODE2 XXO
7 ENDC
8 IFGE ((((5)<-1)<-1)<-1)-1
9 REP ((((5)<-1)<-1)<-1)<-1,CODE2,OXXO
10 REP ((((5)<-1)<-1)<-1)<-1,CODE2,XXXO
11 ENDC
11 ENDC
11 ENDC
5 IF ((5)<-1)&1
6 CODE2 X
7 ENDC
8 IFGE ((5)<-1)-1
5 IF (((5)<-1)<-1)&1
20 9010 9006 fdb lblOX
7 ENDC
8 IFGE (((5)<-1)<-1)-1
5 IF ((((5)<-1)<-1)<-1)&1
6 CODE2 OOX
7 ENDC
8 IFGE ((((5)<-1)<-1)<-1)-1
9 REP ((((5)<-1)<-1)<-1)<-1,CODE2,OOOX
10 REP ((((5)<-1)<-1)<-1)<-1,CODE2,XOOX
11 ENDC
5 IF ((((5)<-1)<-1)<-1)&1
6 CODE2 XOX
7 ENDC
8 IFGE ((((5)<-1)<-1)<-1)-1
9 REP ((((5)<-1)<-1)<-1)<-1,CODE2,OXOX
10 REP ((((5)<-1)<-1)<-1)<-1,CODE2,XXOX
11 ENDC
11 ENDC
5 IF (((5)<-1)<-1)&1
20 9012 9008 fdb lblXX
7 ENDC
8 IFGE (((5)<-1)<-1)-1
5 IF ((((5)<-1)<-1)<-1)&1
6 CODE2 OXX
7 ENDC
8 IFGE ((((5)<-1)<-1)<-1)-1
9 REP ((((5)<-1)<-1)<-1)<-1,CODE2,OOXX
10 REP ((((5)<-1)<-1)<-1)<-1,CODE2,XOXX
11 ENDC
5 IF ((((5)<-1)<-1)<-1)&1
6 CODE2 XXX
7 ENDC
8 IFGE ((((5)<-1)<-1)<-1)-1
9 REP ((((5)<-1)<-1)<-1)<-1,CODE2,OXXX
10 REP ((((5)<-1)<-1)<-1)<-1,CODE2,XXXX
11 ENDC
11 ENDC
11 ENDC
11 ENDC
Joli non?
On peut regretter que le comptage n'ai lieu qu'en binaire avec des O et des X. Les labels sont un peu longues avec le binaire. On peut aller plus vite et avoir des labels 3 fois plus petites et avec un comptage en base 8. La base 8 permet de compter toujours avec une profondeur de 8 jusqu'à 8^8= 2^24 = 16 millions, le tout avec un macro-assembleur tournant sur 8 bits. Magique! Voici la formule
Code:
REP MACRO
IFGE ((\0)&7)-1
\1 1\2
ENDC
IFGE ((\0)&7)-2
\1 2\2
ENDC
IFGE ((\0)&7)-3
\1 3\2
ENDC
IFGE ((\0)&7)-4
\1 4\2
ENDC
IFGE ((\0)&7)-5
\1 5\2
ENDC
IFGE ((\0)&7)-6
\1 6\2
ENDC
IFGE ((\0)&7)-7
\1 7\2
ENDC
IFGE (\0)-8
REP (\0)<-3,\1,0\2
REP (\0)<-3,\1,1\2
REP (\0)<-3,\1,2\2
REP (\0)<-3,\1,3\2
REP (\0)<-3,\1,4\2
REP (\0)<-3,\1,5\2
REP (\0)<-3,\1,6\2
REP (\0)<-3,\1,7\2
ENDC
ENDM