flat assembler
Message board for the users of flat assembler.

Index > Macroinstructions > Interesting idea for macro repetition

Goto page 1, 2, 3  Next
Author
Thread Post new topic Reply to topic
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8354
Location: Kraków, Poland
Tomasz Grysztar 19 Feb 2005, 18:16
I've got an interesting and quite easy to implement idea of a new directive, which would allow repeating some pieces of code at preprocessing time. This is the preprocessor's equivalent of "times" directive, I have for now called it "breed", below I provide the instructions how to implement it into fasm if someone wanted to try.

It works like "times", but is implemented in preprocessor, so it accepts only a raw number (not an expression) as a parameter. Anything that follows is duplicated as many times as the number specified. The "times" directive just processes the given instruction the given amount of times, "breed" makes this number of a completely new lines into preprocessed source, and processes them the same way as macro does - so # and ` operators are also recognized and processed. Also "breed" replaces any occurence of % symbol with the symbol representing the number of current copy of the original line. Simple example:
Code:
breed 3 display `%,13,10    

generates this code:
Code:
display '1',13,10
display '2',13,10
display '3',13,10    

Since "breed" is a preprocessor directive, it can be used to repeat a macro (unlike "times"). Such code:
Code:
macro makeloop label
 {
   label:
    loop label
 }

breed 10 makeloop label#%    

invokes the macroinstruction 10 times, each time making an unique label.
And since the zero count is also allowed, one more possible application of "breed" is conditional preprocessing:
Code:
DEBUG fix 0
breed DEBUG debug_code ; nothing this time
DEBUG fix 1
breed DEBUG debug_code ; debug code invoked    


What do you think about it?


And now instructions how to implement it. First add it to the list of preprocessors directives. Since the list have to be sorted alphabetically, put it right on the beginning, after the "preprocessor_directives" label:
Code:
 db 5,'breed'
 dw breed_lines-preprocessor    

And then add this "breed" handler anywhere in the preprocessor's source:
Code:
breed_lines:
        push    dword [macro_status]
        or      [macro_status],40h
        call    get_number
        jc      invalid_value
        or      ebp,ebp
        jnz     invalid_number
        cmp     dword [edi+4],0
        jne     value_out_of_range
        mov     ebp,[edi]
        xor     edx,edx
      breed_line:
        inc     edx
        cmp     edx,ebp
        ja      breeding_done
        push    esi
        mov     ebx,edi
        xor     eax,eax
        stos    dword [edi]
        mov     eax,edx
        or      eax,80000000h
        stos    dword [edi]
        mov     eax,[current_line]
        stos    dword [edi]
        stos    dword [edi]
      do_breeding:
        lods    byte [esi]
        stos    byte [edi]
        or      al,al
        jz      line_bred
        cmp     al,1Ah
        je      breed_symbol
        cmp     al,22h
        je      breed_string
        jmp     do_breeding
      breed_symbol:
        cmp     word [esi],1 + '%' shl 8
        je      breeding_counter
        lods    byte [esi]
        stos    byte [edi]
        movzx   ecx,al
        rep     movs byte [edi],[esi]
        jmp     do_breeding
      breed_string:
        lods    dword [esi]
        stos    dword [edi]
        mov     ecx,eax
        rep     movs byte [edi],[esi]
        jmp     do_breeding
      breeding_counter:
        add     esi,2
        inc     edi
        push    ebx edx
        push    edi
        mov     ecx,1000000000
        mov     eax,edx
        xor     edx,edx
        xor     bl,bl
      store_counter_value:
        div     ecx
        push    edx
        or      bl,bl
        jnz     store_counter_digit
        or      al,al
        jz      counter_digit_ok
        not     bl
      store_counter_digit:
        add     al,30h
        stos    byte [edi]
      counter_digit_ok:
        mov     eax,ecx
        xor     edx,edx
        mov     ecx,10
        div     ecx
        mov     ecx,eax
        pop     eax
        or      ecx,ecx
        jnz     store_counter_value
        pop     ebx
        mov     eax,edi
        sub     eax,ebx
        mov     [ebx-1],al
        pop     edx ebx
        jmp     do_breeding
      line_bred:
        push    [current_line]
        push    edx ebp
        mov     [current_line],ebx
        call    preprocess_line
        pop     ebp edx
        pop     [current_line]
        pop     esi
        jmp     breed_line
      breeding_done:
        pop     eax
        and     al,0F0h
        and     [macro_status],0Fh
        or      [macro_status],al
        jmp     line_preprocessed    

(the error handling might need also to be corrected to work with the breed-generated lines, since they have zeroed the field that normally contains the name of macro)
Post 19 Feb 2005, 18:16
View user's profile Send private message Visit poster's website Reply with quote
mike.dld



Joined: 03 Oct 2003
Posts: 235
Location: Belarus, Minsk
mike.dld 19 Feb 2005, 18:24
Do you mean we could define jump tables with this directive?
Post 19 Feb 2005, 18:24
View user's profile Send private message Visit poster's website ICQ Number Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8354
Location: Kraków, Poland
Tomasz Grysztar 19 Feb 2005, 18:49
It depends on what do you exacly mean by "jump tables". The proposed "breed" directive uses an arbitrarily given value for the repeat count, it have to be specified directly. If you make some jump table by couting some given items, you have to use the standard fasm's techniques. But if you wanted to make some jump table just by directly giving the count of labels, then "breed" would be useful for you.
Post 19 Feb 2005, 18:49
View user's profile Send private message Visit poster's website Reply with quote
JohnFound



Joined: 16 Jun 2003
Posts: 3499
Location: Bulgaria
JohnFound 19 Feb 2005, 21:02
Hi.
The idea to have some iteractive operator in preprocessor is very good. I have only some thoughts:
1. Is it be possible to use "breed" in macroses or only constant (and "fix") are allowed:
Code:
macro MyMacro count {
  breed count nop
}

MyMacro 5
    


2. What about:
Code:
breed DEBUG include "debug.asm"    


3. Definitely we need in preprocessor all powerfull operators from assembling stage, like: if, repeat, aritmethics.
Now we have similar functionality, but with different names. Don't you though about some more common solution - for example "if", "repeat" and "times" to be processed both in preprocessor and assembling stages, depending on parameters - for example, if the values are known in preprocessor - why not to process the statement in preprocessor?
Example:
Code:
repeat one, two, three  ; because preprocessor have no arithmetics
%:
end repeat

DEBUG equ TRUE

if DEBUG eq TRUE   ; as far as DEBUG is symbolic constant, its value is known at preprocessing stage, so "if" can be executed.
  include 'debug.asm'
end if
    


Of course I don't actually know whether all this is possible in FASM architecture.

Regards
Post 19 Feb 2005, 21:02
View user's profile Send private message Visit poster's website ICQ Number Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8354
Location: Kraków, Poland
Tomasz Grysztar 19 Feb 2005, 21:11
1. As you already know, macro parameters are replaced before doing anything else, even before "fix" - so this will work as expected, since "breed" will meet just the 5 value when it is processed.

2. Yes, this will also work - everything that follows "breed" is preprocessed in a standard way after duplicating, so any preprocessor directive is allowed as macros are. Even "breed" nesting is possible (however % gets replaced everywhere by the first "breed", I don't know could I improve it, but it's different from how the "times" nesting works).

3. No, such mixing would make it all backward-incompatible and even unpredicatable.
Post 19 Feb 2005, 21:11
View user's profile Send private message Visit poster's website Reply with quote
JohnFound



Joined: 16 Jun 2003
Posts: 3499
Location: Bulgaria
JohnFound 19 Feb 2005, 21:27
Privalov wrote:
3. No, such mixing would make it all backward-incompatible and even unpredicatable.


Well, yes, you are probably right - the compatibility is important. Also, the idea to name with different names preprocessor operators and assembler equivalents have some advantages - this will make the source code more readable and unambiguous.

Anyway, "breed" is excelent idea and I can only acclaim it. Smile

Quote:
(the error handling might need also to be corrected to work with the breed-generated lines, since they have zeroed the field that normally contains the name of macro)


Could you explain more detailed? Any solution?

Regards.
Post 19 Feb 2005, 21:27
View user's profile Send private message Visit poster's website ICQ Number Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8354
Location: Kraków, Poland
Tomasz Grysztar 19 Feb 2005, 21:33
The command line version use to this field to display the name of macro followed by number of macro line when displaying error info. They will probably crash on a "breed"-generated line, since it has zero pointer there. The solution is simple - check for zero pointer and display only line number (which will be number of "breed"-generated duplicate).
Post 19 Feb 2005, 21:33
View user's profile Send private message Visit poster's website Reply with quote
JohnFound



Joined: 16 Jun 2003
Posts: 3499
Location: Bulgaria
JohnFound 19 Feb 2005, 21:58
Ah, it is clear now. Thank you.

Regards.
Post 19 Feb 2005, 21:58
View user's profile Send private message Visit poster's website ICQ Number Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8354
Location: Kraków, Poland
Tomasz Grysztar 19 Feb 2005, 22:20
Another idea: maybe it would be better to make it not replace anything by default, but let you specify a name for counter symbol when you need it.
So something like:
Code:
breed 7 db %    

would keep the % unchanged, only make 7 duplicates of line; while
Code:
breed [counter] 7 db counter    

would replace "counter" symbol with the number of each copy.
But I don't have an idea for any nicer syntax for this setting yet.
Post 19 Feb 2005, 22:20
View user's profile Send private message Visit poster's website Reply with quote
beppe85



Joined: 23 Oct 2004
Posts: 181
beppe85 19 Feb 2005, 22:29
Cool.

To avoid introducing another kwyword, I could suggest this: (@ means AT)
breed 7 @ counter db counter
Post 19 Feb 2005, 22:29
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8354
Location: Kraków, Poland
Tomasz Grysztar 19 Feb 2005, 22:33
There might be a macro called @ and then "breed 7 @ ..." would just duplicate this macro. That's why I tried to invent some syntax with specifying the name of counter symbol before the actual count.
Post 19 Feb 2005, 22:33
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8354
Location: Kraków, Poland
Tomasz Grysztar 20 Feb 2005, 13:49
The additional parameters, maybe in the square brackets before the count, as I proposed above, might be also available to specify a few different counter symbols with different some options, like counting from 0 instead of 1 or formatting the number differently, etc.

This idea needs to mature before I consider implementing it oficially (to quick decisions may lead to breaking compatibility later, when better solutions are invented, and I try to avoid such things with fasm*). But feel free to play with it, since the implementation, as given in my first post, is really simple and should be also easy to modify by anyone.

And I'm now going back to the 64-bit object output implementation.

* Though there was one case when I failed, it was version 1.20 when I changed the way of defining macro blocks. But these were still "early" development stages.
Post 20 Feb 2005, 13:49
View user's profile Send private message Visit poster's website Reply with quote
MCD



Joined: 21 Aug 2004
Posts: 602
Location: Germany
MCD 21 Feb 2005, 10:48
Privalov wrote:

This idea needs to mature before I consider implementing it oficially (to quick decisions may lead to breaking compatibility later, when better solutions are invented, and I try to avoid such things with fasm*). But feel free to play with it, since the implementation, as given in my first post, is really simple and should be also easy to modify by anyone.

I think this is very wise, but anyway, nice ideas. (Why not adding some stuff to the preprocessor while you're at?). But, please avoid ambiguous syntax elements, like the % you have proposed. Having the same symbol for both the preprocessor and the parser really can confuse. Anyway, I would be interested in where you got the word "breed" Wink from for repetitions

_________________
MCD - the inevitable return of the Mad Computer Doggy

-||__/
.|+-~
.|| ||
Post 21 Feb 2005, 10:48
View user's profile Send private message Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia
vid 21 Feb 2005, 14:22
yes, i think there is plenty of not used symbols, and if you use "%" then if you want to generate "%" for assembly-time repeats you would have to fix it somehow
Post 21 Feb 2005, 14:22
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
beppe85



Joined: 23 Oct 2004
Posts: 181
beppe85 21 Feb 2005, 16:39
MCD wrote:
Anyway, I would be interested in where you got the word "breed" Wink from for repetitions

I was also wondering about. The only place I've heard this word was from Nirvana. I asked to a dictionary, and seems that 'breed' in this case means 'proliferate'.

_________________
"I assemble, therefore I am"

If you got some spare time, visit my blog: http://www.beppe.theblog.com.br/ and sign my guestmap
Post 21 Feb 2005, 16:39
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8354
Location: Kraków, Poland
Tomasz Grysztar 21 Feb 2005, 16:44
Yes, I have used this word, because this directive, as opposed to "times", which just does the multiple processing of a line, creates a physical duplicates of line. The "clone" word might also be appropriate, however the clones are supposed to be identical, while those lines might actually differ (because of the counting symbols).
Post 21 Feb 2005, 16:44
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8354
Location: Kraków, Poland
Tomasz Grysztar 21 Feb 2005, 16:50
vid wrote:
yes, i think there is plenty of not used symbols, and if you use "%" then if you want to generate "%" for assembly-time repeats you would have to fix it somehow

That's why I go into the direction of specifying the name for counter symbol for each "breed" (or not specifying at all when you don't need it) - this would also prevent problems with accessing different counter levels when nesting "breeds".
Post 21 Feb 2005, 16:50
View user's profile Send private message Visit poster's website Reply with quote
pelaillo
Missing in inaction


Joined: 19 Jun 2003
Posts: 878
Location: Colombia
pelaillo 21 Feb 2005, 19:02
Quote:

That's why I go into the direction of specifying the name for counter symbol for each "breed" (or not specifying at all when you don't need it)

This is good !
I agree with MCD about the naming: "for" seems a better/unambiguous/classic/used term to refer to this feature.
Post 21 Feb 2005, 19:02
View user's profile Send private message Yahoo Messenger Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia
vid 22 Feb 2005, 03:23
i like breed, let's reserve for until it will really be capable of real for.
Post 22 Feb 2005, 03:23
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
THEWizardGenius



Joined: 14 Jan 2005
Posts: 382
Location: California, USA
THEWizardGenius 24 Feb 2005, 23:23
Is this going to be included in future versions of FASM? It doesn't look like we need to vote on it... Go ahead and think about it all you want, but I'm going to add it to MY second copy of FASM, which I call "tweaked FASM"; I add all tweaks that you suggest but don't put into official FASM releases, to tweaked FASM... I love FASM tweaks, maybe I'll post my "tweaked FASM" for you to play with... it doesn't have anything of my own because I don't know how to make up my own tweaks, but whenever you or someone else posts a tweaked version I like, I add it. I put instructions for all tweaks into a text file so when new version of FASM comes out I can add it to that one. Maybe I'll post the text file...
Post 24 Feb 2005, 23:23
View user's profile Send private message AIM Address Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page 1, 2, 3  Next

< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.