flat assembler
Message board for the users of flat assembler.

Index > Programming Language Design > Reinterpretable arguments to macros in fasmg

Author
Thread Post new topic Reply to topic
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8305
Location: Kraków, Poland
Tomasz Grysztar 14 Dec 2023, 15:01
In release "k9u0" I have added a new feature that allows better access to one of the fundamental mechanics of fasmg's engine.

Normally, when executing an instruction, fasmg adds a context information to the text of each argument, ensuring that symbols in this text are going to refer to the same entities that the caller of the macro saw. This is very handy under normal circumstances, as it allows to use the values passed in the arguments without worrying that switching namespaces may have changed their meaning. There are, however, situations when it may be necessary to reinterpret the same text in the new context.

This is what the new feature provides. By prefixing the parameter name with "&" character you can tell the assembler to not add context information to the text of the argument, allowing it to be interpreted in whichever context is present at the time of evaluation. An example I added in the manual demonstrates it on one of the simplest cases:
Code:
        char = 'A'
        other.char = 'W'

        macro both a, &b
                namespace other
                        db a, b
                end namespace
        end macro

        both char+1, char+1 ; db 'B', 'X'    
Both the arguments have the same text, but one carries additional context, while the other one is kept raw and therefore becomes reinterpreted in the context of the "other" namespace.

While this allows macros to interpret some expressions in a special way, it also opens the way to have fully transparent line interceptors, which may pass the text of the intercepted line further without tainting it with unwanted context:
Code:
macro ? &line&    
This is likely to become a new preferred idiom.

Another approach would be to strip the context from the text when needed (this could always be done with help of RMATCH, or even by converting the text into raw bytes with backtick operator or STRINGIFY and then tokenizing it again with EVAL), but the effect is not exactly the same. While &-prepended parameters do not add any context information, they also do not remove any. The argument to the macro may contain pieces of text that already have some context carried from elsewhere, and this information is going to remain there, while it would be removed by RMATCH. This example:
Code:
char = 'A'
other.char = 'W'

macro both a, &b
        namespace other
                db a, b
        end namespace
end macro

i = 1
other.i = 2

macro with addend
        both char+addend, char+addend
end macro

with i    
still produces "BX" output, because symbol "i" keeps it original context when being passed around (and this context is recorded at the time when "i" is packed up for the value of "addend").
Post 14 Dec 2023, 15:01
View user's profile Send private message Visit poster's website Reply with quote
MaoKo



Joined: 07 May 2019
Posts: 100
Location: Paris/French
MaoKo 14 Dec 2023, 19:51
Seem very promising. This feature would save me from some headache Smile.
Post 14 Dec 2023, 19:51
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8305
Location: Kraków, Poland
Tomasz Grysztar 17 Dec 2023, 21:06
Combining it with another relatively recent addition, "??" interceptor, I made what I believe is the simplest and cleanest macro builder yet:
Code:
calminstruction ?? &line&
        match >>line?, line
        jyes commit
        match >line?, line
        jyes collect
        assemble line
        exit
        local stack
    collect:
        take stack, line
        exit
    commit:
        take line, stack
        jyes commit
    assembly:
        assemble line
        take , line
        take line, line
        jyes assembly
end calminstruction    
It can be used to build any definitions, like macros, CALM instructions, or structures, where control directives like IF or REPEAT would not be allowed during the definition, but we can use them to prepare all the lines first, and then feed them to the assembler all at once. Here an example with STRUCT macro:
Code:
BITS = 64

> struct POINT
    if BITS = 64
        > x dq ?
    else
        > x dd ?
    end if
    if BITS = 64
        > y dq ?
    else
        > y dd ?
    end if
>> ends

> struct OCTAGON
    repeat 8
        > vertex#% POINT
    end repeat
>> ends    
The lines starting with ">" are collected, and the line starting with ">>" launches the execution of the entire generated block.

Also by adding a couple of commands after the "assemble line" it's possible to view what definition is generated:
Code:
        assemble line
        stringify line
        display line
        display 10    
With the above sample it shows:
Code:
 struct POINT
 x dq ?
 y dq ?
 ends
 struct OCTAGON
 vertex#1 POINT
 vertex#2 POINT
 vertex#3 POINT
 vertex#4 POINT
 vertex#5 POINT
 vertex#6 POINT
 vertex#7 POINT
 vertex#8 POINT
 ends    
The process is simple and transparent. Because there is no context information added to the generated lines, there should be no hidden traps.
Post 17 Dec 2023, 21:06
View user's profile Send private message Visit poster's website Reply with quote
fabbel



Joined: 30 Oct 2012
Posts: 77
fabbel 18 Dec 2023, 09:52
Hi Tomasz. nice indeed !
Wouldn't that be good to include in the standard FASMG distribution package ? What do u think ?
Post 18 Dec 2023, 09:52
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8305
Location: Kraków, Poland
Tomasz Grysztar 18 Dec 2023, 11:51
Yes, something like this (especially when I get a good feedback) deserves at least inclusion in the utility package, and perhaps it could also go as an example in auxiliary documentation if I decide to write a section about the new tricks.

Another door this new feature opens: it allows to make custom directives to define symbolic variables carrying contextless text. Playing with this, I have another example, this time implementing a fasm-like FIX directive, making a global replacement of a symbol with some other text (in a non-interfering way thanks to the new "&line&" idiom):
Code:
define fix? fix?

calminstruction (name) fix? &value&
        arrange name, fix.name
        publish name, value
end calminstruction

calminstruction ?! &line&
        local any
        match any =fix? any?, line
        jyes skip
        transform line, fix
    skip:
        assemble line
end calminstruction    
Post 18 Dec 2023, 11:51
View user's profile Send private message Visit poster's website Reply with quote
fabbel



Joined: 30 Oct 2012
Posts: 77
fabbel 18 Dec 2023, 13:04
thumbs up !
Post 18 Dec 2023, 13:04
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8305
Location: Kraków, Poland
Tomasz Grysztar 18 Dec 2023, 21:19
One more thing: this also makes it easier to emulate some of the fasm 1 syntax more closely. This specific snippet used to be quite problematic in fasmg, because context was fixed for the entire line:
Code:
foo dd .size
.size = $ - foo    
A simple macro that splits the context evaluation is now sufficient to properly simulate fasm's behavior:
Code:
struc (name) dd? &values&
        label name: 4
        emit 4: values
end struc    
I should update fasm 2 macros to use this for better compatibility.
Post 18 Dec 2023, 21:19
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< 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.