Logicielsmoto.com
http://www.logicielsmoto.com/phpBB/

Le macro c'est bon. On ne cessera pas de le répéter!
http://www.logicielsmoto.com/phpBB/viewtopic.php?f=3&t=527
Page 1 sur 1

Auteur:  Samuel Devulder [ 08 Juil 2015, 23:09 ]
Sujet du message:  Le macro c'est bon. On ne cessera pas de le répéter!

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 :(

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

Auteur:  Prehisto [ 09 Juil 2015, 17:16 ]
Sujet du message:  Re: Le macro c'est bon. On ne cessera pas de le répéter!

Excellent exposé !
Faut avouer que c'est assez tentant de l'utiliser, ton programme. Arriver à contourner la limitation de récursivité pour faire une répétition de code de la taille voulue avec seulement des macros, je dis bravo :good:
... bien que je n'ai pas encore eu de code qui nécessite 95247845487654421457989216315800 instructions identiques consécutives, et si tel est accessoirement le cas, je préférerais écrire un code... qui fabrique du code ;)

Auteur:  GarlandRaven [ 14 Oct 2018, 17:52 ]
Sujet du message:  Re: Le macro c'est bon. On ne cessera pas de le répéter!

Well, i would resume this topic because i'm experimenting with macros.

Consider the following code:

Code:

DRAWTILE

* Line 1

       LDD #$1122   .Get colors
       STA $8000,Y   .Draw ramA
       STB $6000,Y   .Draw ramB
       LEAY 1,Y         .Advance
       LDD #$2345   .Get colors
       STA $8000,Y   .Draw ramA
       STB $6000,Y   .Draw ramB
       LEAY 1,Y         .Advance
       LDD #$6789   .Get colors
       STA $8000,Y   .Draw ramA
       STB $6000,Y   .Draw ramB
       LEAY 1,Y         .Advance
       LEAY 25,Y       .New Row
...

* Line 16

       LDD #$3333   .Get colors
       STA $8000,Y   .Draw ramA
       STB $6000,Y   .Draw ramB
       LEAY 1,Y         .Advance
       LDD #$4444   .Get colors
       STA $8000,Y   .Draw ramA
       STB $6000,Y   .Draw ramB
       LEAY 1,Y         .Advance
       LDD #$5555   .Get colors
       STA $8000,Y   .Draw ramA
       STB $6000,Y   .Draw ramB
       LEAY 1,Y         .Advance


Now as you can see this is a long code which draws pixel per pixel a tile on the screen (seems the fastest way to render a sprite, isn't that?).

Let's suppose i want to use this code several times to draw a tilemap on screen. So i have basically two options: making it a subroutine or making it as a macro. Making it as a sub will help to keep the code shorter when assembled while on the other hand will result a little slow, am i right? You probably would tell me that i want to use macros for speed, avoiding jumps here and there.

So the code would become

Code:
DRAWTILE MACRO

* Line1
...
         ENDM


But if i look at the code it contains a lot of repetition, which i could shrink like

Code:
DRWT      MACRO
          STA $8000,Y   .Draw ramA
          STB $6000,Y   .Draw ramB
          LEAY 1,Y         .Advance
          ENDM

DRAWTILE MACRO
* Line 1

          LDD #$1122   .Get colors
          DRWT
          LDD #$2345   .Get colors
          DRWT
          LDD #$6789   .Get colors
          DRWT
               
          LEAY 25,Y       .New Row
...

* Line 16

          LDD #$3333   .Get colors
          DRWT
          LDD #$4444   .Get colors
          DRWT
          LDD #$5555   .Get colors
          DRWT

          ENDM



Then in my general draw routine i do:

Code:
          LDY #$0000 .top left corner
          DRAWTILE 
          LDY #$0003
          DRAWTILE 
          LDY #$0006
          DRAWTILE 
          LDY #$0009
          DRAWTILE 
      ...


Is this approach correct? Because there are few points which are giving me troubles and i think i'm missing something for sure:

1) I must place branches carefully because it's easy to hit an Out Of Range, and Long branches are taking extra cycles
2) The code execution seems slower than using subs to repeat the drawings (can't figure why)
3) After a certain number of DRAWTILE calls (i can tell this from how much tiles he draws), the game explodes and i see artifacts on screen, giving me the suspect i generated a code too much long which somehow screws up in memory (my ORG is $4000 and im using addresses from $5000 for my values), but i dunno, however same code with JSR calls instead of macro works perfectly
4) Of course the assembly time takes much much more (but thats expected)

Can you tell me how you would use macros to handle such a situation, where you need to draw n tiles each of which has n rows to draw manually?

Thank you so much :)

Auteur:  Samuel Devulder [ 14 Oct 2018, 19:09 ]
Sujet du message:  Re: Le macro c'est bon. On ne cessera pas de le répéter!

yes, macro expands a lot and eats useful memory. You can work-around this by using pagination and put your code in memory-banks. An other option is to reduce the memory footprint of the code. Typically
Code:
      6  4+4   A003 A7   A9 8000         STA $8000,Y   .Draw ramA
      7  4+4   A007 E7   A9 6000         STB $6000,Y   .Draw ramB
      8  4+1   A00B 31   21              LEAY 1,Y      .Advance
is 10 bytes (624 bytes for a tile)

You can reduce the code by better using the 6809.
1) If you do a lot of LDY, you'd better consider using X or U instead beacuase LDY #somevalue eats 1 byte more than the corresponding LDX or LDU version.
2) try to avoid 16bits displacements: they are slow and eats bytes. In that case if the index register points to $6000 in place of $000, you can replace $6000,Y with ",Y" and spare 2 bytes.
3) LEAY 1,Y is nice but it can be direcly done by the previous instruction: STB ,Y+
Code:
     11  4+4   A010 A7   A9 2000            STA $2000,Y   .Draw ramA
     12  4+2   A014 E7   A0                 STB ,Y+       .Draw ramB + adva>>
is only 6bytes, 40% smaller, resulting in 432bytes for a tile. It can even be smaller if you use two index registers:
Code:
     10  3     A00D 8E   6000               LDX #$6000
     11  3     A010 CE   8000               LDU #$8000
     12
     13  3     A013 CC   1122               LDD #$1122    .Get colors
     14  4+2   A016 A7   80                 STA ,X+       .Draw ramA
     15  4+2   A018 E7   C0                 STB ,U+       .Draw ramB + adva>>
     16  3     A01A CC   3344               LDD #$3344    .Get colors
     17  4+2   A01D A7   80                 STA ,X+       .Draw ramA
     18  4+2   A01F E7   C0                 STB ,U+       .Draw ramB + adva>>
     19  3     A021 CC   5566               LDD #$5566    .Get colors
     20  4+2   A024 A7   80                 STA ,X+       .Draw ramA
     21  4+2   A026 E7   C0                 STB ,U+       .Draw ramB + adva>>

The drawing part is now 4 bytes only in place of the initial 10bytes. This mean that you now only need 3*7*16=336 bytes for a tile, roughly half the initial implementation.

Also notice that ,X+ is slower than n,x (with 0<=n<=8), so you can sppedup the code a little more:
Code:
     10  3     A00D CC   1122               LDD #$1122    .Get colors
     11  4+0   A010 A7   84                 STA ,X        .Draw ramA
     12  4+0   A012 E7   C4                 STB ,U        .Draw ramB
     13  3     A014 CC   3344               LDD #$3344    .Get colors
     14  4+1   A017 A7   01                 STA 1,X       .Draw ramA
     15  4+1   A019 E7   41                 STB 1,U       .Draw ramB
     16  3     A01B CC   5566               LDD #$5566    .Get colors
     17  4+1   A01E A7   02                 STA 2,X       .Draw ramA
     18  4+1   A020 E7   42                 STB 2,U       .Draw ramB
     19                           
     20  4+1   A022 30   88 28              leax 40,x     .Next line
     21  4+1   A025 33   C8 28              leau 40,u     .Next line
which is both relatively small and fast.

Last notes:
1) LDD ,U++ is 8 cycles. "PULU D" does the same in only 7 cycles
2) you can possibly gain both space a speed by writing all ramA data first, than all ramB separately
3) by re-organizing the code and better use of the 6809 instruction set, the subroutine option might not be as slow as one can think.

Auteur:  Prehisto [ 14 Oct 2018, 19:32 ]
Sujet du message:  Re: Le macro c'est bon. On ne cessera pas de le répéter!

Even faster, instead of doing:
Code:
       LDD #$1122   .Get colors
       STA ,U   .Draw ramA
       STB ,Y   .Draw ramB
       LDD #$2345   .Get colors
       STA 1,U   .Draw ramA
       STB 1,Y   .Draw ramB
       LDD #$6789   .Get colors
       STA 2,U   .Draw ramA
       STB 2,Y   .Draw ramB
       LEAY 40,Y       .New Row
       LEAU 40,U       .New Row

do (the display pointer must be increased by 120, short indexed mode is faster than the long one):
Code:
       LDD #$1123   .Get colors
       STD -120,X   .Draw ramA (first line)
       LDD #$6755    .Get colors
       STA -120+2,X   .Draw ramA (first line)
       STB -80,X   .Draw ramA  (next line)
       LDD #$1123   .Get colors
       STD -80+1,X   .Draw ramA  (next line)
       ... as long as you have something to draw in RAMA
       LEAU   $2000-XXX,X   Points to RAMB start of drawing
       LDD #$1123   .Get colors
       STD -120,X   .Draw ramB (first line)
       LDD #$6755    .Get colors
       STA -120+2,X   .Draw ramB (first line)
       STB -80,X   .Draw ramB  (next line)
       LDD #$1123   .Get colors
       STD -80+1,X   .Draw ramB  (next line)
       ... as long as you have something to draw in RAMB

Then, to skip each group of 6 lines (once you have drawn offsets -120, -80, -40, 0, 40, 80), just do something like:
Code:
       LDB    #240
       ABX

... which is faster than LEAX 240,X.

Auteur:  GarlandRaven [ 16 Oct 2018, 22:25 ]
Sujet du message:  Re: Le macro c'est bon. On ne cessera pas de le répéter!

Thanks for the clear explication :) there are more things left which i would know about macros:

1) Is it possible in some way to pass a memory content as argument? I suppose the answer is no, but i would find a way to jump to the right label from a value i can read in memory. For instance, if my tiles ID are coded in one byte, i would have labels as DRAWTILE00, DRAWTILE02 and so on then i would use that byte as first macro argument to call DRAWTILE\0. I want to avoid branches at all costs.

Now on the PULS site i found this useful article, i just wondering if all that ASRA lines to retrive the label won't slow the drawing process too much.

2) Similar question for macro in loops. To avoid multiple labels we use to mark them as arguments, but if i have a loop where i scan a huge collection and i need to call the macro for each element, what should be a nice method to label each iteration? Best thing would be to store a counter and use it as argument, but again i don't know if that's feasable.

Great learning here :) merci beacoup!

Auteur:  Samuel Devulder [ 16 Oct 2018, 22:41 ]
Sujet du message:  Re: Le macro c'est bon. On ne cessera pas de le répéter!

GarlandRaven a écrit:
1) Is it possible in some way to pass a memory content as argument? I suppose the answer is no, but i would find a way to jump to the right label from a value i can read in memory. For instance, if my tiles ID are coded in one byte, i would have labels as DRAWTILE00, DRAWTILE02 and so on then i would use that byte as first macro argument to call DRAWTILE\0. I want to avoid branches at all costs.
I'm not sure to understand. What do you mean by memory content ? Do you mean you have the number of the tile in an accumulator (say reg. B for instance) and want to call DRAWTILE"B" ? If so, you can use an indexed-jump
Code:
   LDB  TILE_NUMBER   ; <== B=1
   LDX  #TABLE
   LSLB
   ABX
   JMP [,X] ; <== will jump to TABLE[B], eg. DRAWTILE01
TILE_NUMBER
   FCB 1
TABLE
   FDB DRAWTILE00,DRAWTILE01,DRAWTILE02,...

Citation:
i just wondering if all that ASRA lines to retrive the label won't slow the drawing process too much.

I can't tell precisely, but ASRA is quite a fast operation when compared to indirect memory accesses.

Citation:
2) Similar question for macro in loops. To avoid multiple labels we use to mark them as arguments, but if i have a loop where i scan a huge collection and i need to call the macro for each element, what should be a nice method to label each iteration? Best thing would be to store a counter and use it as argument, but again i don't know if that's feasable.

The REP macro defined in the first message of the topic does this. It builds a different symbol for each loop unrolling. You can use that generated symbol to create local labels. If you are curious you'll observe that the built symbol is the loop iteration number written in binary where 0 is written as O and 1 as X :)

Auteur:  GarlandRaven [ 18 Oct 2018, 11:54 ]
Sujet du message:  Re: Le macro c'est bon. On ne cessera pas de le répéter!

Thank you PrehisTO and Sam, i spent last days working on your suggestions and now the execution looks faster :) The indexed jump was a nice discovery. Of course since i'm still learning i'd have some new questions to ask.

About organizing the code: i'm working directly in MacroAssembler 3.1 environment using dcmoto. The more i work on my project, the more it grows, and now i'm experiencing some size problems. The assembly process screws up at the second pass, and even if it completes the process, the resulting BIN file crashes on launch. So i was wondering how long can be my code. Just to make some considerations: coming from high level coding paradigms, i tend to compact the code as much as i can to avoid redundance, and this usually means to use subroutines. Now having a lot of JSR in a loop is not the most performant thing and that's why we would use macros. Macros tend to generate tons of code and if you use them very often it seems the assembler can't parse them anymore and the assembly process fails. Consider this code snippet:

Image

This is an excerpt from a loop routine. Of course i would shrink it like this:

Image

But literally this blows up the assembly process:

Image

It works if i assemble only the single ASM, but fails when assembling the whole project.

And however, besides macros, i still have to code a lot of drawing routines (for enemies, bonuses, projectiles and whatever) so i really can't figure how much lines of code i still need and it seems so strange to find myself already stuck at this point, probably i'm missed some premises here :D


Sam a écrit:
You can work-around this by using pagination and put your code in memory-banks.


Can you explain this a little more please? This is my first time with such topics and an example would be really useful :)


PrehisTO a écrit:
Even faster, instead of doing:


Yeah, i edited my code to draw all the ram A and then ram B. I was wondering why this is affecting execution speed if you are using two pages ($6000 and $8000) - i may understand this if you work on page 0 where you have to swap the banks, but not in page 1 2 or 3 :)


Thank you guys :)

Auteur:  Samuel Devulder [ 18 Oct 2018, 12:29 ]
Sujet du message:  Re: Le macro c'est bon. On ne cessera pas de le répéter!

I have little time to answer, but concerning the assembler crash: you seem to be short on memory.

There are at least 2 possibilities to work around this:
1) do cross-compilation using C6809 on a modern machine. C6809 works fine with Assembler v3 data since the asm syntax is the same :)
2) otherwise if you really want to compile on the Thomson, simply create a "small" MAIN.ASM that INCLUD other ASM-files. Then you could possibly spare enough bytes in memory to perform a direct-to-disk compilation. I don't recall the exact "A" syntax (Asomething.. hmm), but I remember something about compiling without the need to have the full code in memory. May-be Prehisto will elaborate on this subject later.

Auteur:  GarlandRaven [ 18 Oct 2018, 13:09 ]
Sujet du message:  Re: Le macro c'est bon. On ne cessera pas de le répéter!

Samuel Devulder a écrit:
I have little time to answer, but concerning the assembler crash: you seem to be short on memory.

There are at least 2 possibilities to work around this:
1) do cross-compilation using C6809 on a modern machine. C6809 works fine with Assembler v3 data since the asm syntax is the same :)
2) otherwise if you really want to compile on the Thomson, simply create a "small" MAIN.ASM that INCLUD other ASM-files. Then you could possibly spare enough bytes in memory to perform a direct-to-disk compilation. I don't recall the exact "A" syntax (Asomething.. hmm), but I remember something about compiling without the need to have the full code in memory. May-be Prehisto will elaborate on this subject later.



1) Ok, but how they did in 1986 then? :D

2) I'm already using AFILENAME/IM to include all the asm and macros and write to disk. My main in very very small but for instance, each ASM which contains drawing code is big, because drawing by code pixel by pixel grows the code so much.

Thanks :)

Auteur:  Samuel Devulder [ 18 Oct 2018, 13:22 ]
Sujet du message:  Re: Le macro c'est bon. On ne cessera pas de le répéter!

Hmm it look like using the macro eats some space. Possibly the assembler require to expand all the macros in memory before compiling requiring lots of memory space, may be more than free memory. My guess is that in 1986 the game making industry did cross-compiling on some 68000-based Sun machines.

Auteur:  GarlandRaven [ 18 Oct 2018, 13:36 ]
Sujet du message:  Re: Le macro c'est bon. On ne cessera pas de le répéter!

Samuel Devulder a écrit:
Hmm it look like using the macro eats some space. Possibly the assembler require to expand all the macros in memory before compiling requiring lots of memory space, may be more than free memory. My guess is that in 1986 the game making industry did cross-compiling on some 68000-based Sun machines.


That would explain a lot of things.
So there's no way to work on a big project by using only dcmoto and macroassembler, i need to go with the C6809 because of that macro parsing issue...?

Page 1 sur 1 Heures au format UTC + 1 heure
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/