flat assembler
Message board for the users of flat assembler.

Index > Main > switching from NASM to FASM

Goto page Previous  1, 2
Author
Thread Post new topic Reply to topic
str8c



Joined: 14 Oct 2014
Posts: 8
str8c 16 Oct 2014, 11:54
l_inc wrote:
I've just blindly rewritten your last macro without considering any meaning behind the code (it's been a long hard day):

Thanks for that, although I am still a bit confused on how you can use the value of 'len' before it has been set (it seems to be treated like a label, while the other variables are not).

Tomasz Grysztar wrote:
The purpose of preprocessor's "local" is to generate a unique name for each invocation of macro, but this name may still need to be a global label from the later assembly point of view, or a unique dot-local name. This should be a conscious choice - the undesired effects that l_inc mentioned may as well be a desired ones, depending on the purpose of macro. It is all left to the programmer.

The possible uses of global-local labels seem very limited to me (resetting the current dot-namespace?), while unique dot-local names are almost always used. It would simplifying writing if local names were dot-local by default, with a special symbol to make them global. Double dots are ugly.
Post 16 Oct 2014, 11:54
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8359
Location: Kraków, Poland
Tomasz Grysztar 16 Oct 2014, 13:29
str8c wrote:
Thanks for that, although I am still a bit confused on how you can use the value of 'len' before it has been set (it seems to be treated like a label, while the other variables are not).
The "=" operator can be used to define either numerical constant (which can be forward-referenced like a label) or assembly-time variable. They are distinguished only by the fact that the former is defined exactly once, and the latter is re-defined one or more times (see section 2.2.1 of the manual).

str8c wrote:
Tomasz Grysztar wrote:
The purpose of preprocessor's "local" is to generate a unique name for each invocation of macro, but this name may still need to be a global label from the later assembly point of view, or a unique dot-local name. This should be a conscious choice - the undesired effects that l_inc mentioned may as well be a desired ones, depending on the purpose of macro. It is all left to the programmer.

The possible uses of global-local labels seem very limited to me (resetting the current dot-namespace?), while unique dot-local names are almost always used. It would simplifying writing if local names were dot-local by default, with a special symbol to make them global. Double dots are ugly.
The macro itself may contain the complete "ecosystem" of labels. For instance, you can take some piece of code (containing both global and local labels) and wrap it up in a macro. To make it re-usable you then need only to insert a "local" directive with the names of global labels to make them unique every time the macro is called.
It's quite straightforward and transparent - the preprocessor does not need to know whether the starting characters of label have any special meaning to the assembler which processes them later, it just blindly reproduces them. If fasm's assembly language introduces some new class of labels, started with "@" or "!", or some other character, the behavior of fasm's preprocessor is still going to be adequate and predictable.

But I do agree that dots are sometimes ugly, it does bother me a bit from time to time. In a simple case like this one you may try to do something about it with an additional macro, like:
Code:
macro .local [name]
 { local .name
   define name .name }

macro str [string]
{ 
    common .local asDst,dst
            local pos, len, a, esc, val
        asDst:: dst rb len
        virtual at 0 
            db string 
            pos = 0 
            esc = 0 
            repeat $ 
                load a byte from %-1 
                if a >= '0' & a <= '7' 
                    if esc > 0 
                        if esc < 4 
                            esc = esc + 1 
                            val = val * 8 + a - '0' 
                        else 
                            esc = 0 
                            store byte val at asDst:dst+pos
                            store byte a at asDst:dst+pos+1
                            pos = pos + 2 
                        end if 
                    else 
                        store byte a at asDst:dst+pos
                        pos = pos + 1 
                    end if 
                else 
                    if a = '\' 
                        if esc > 0 
                            store byte '\' at asDst:dst+pos
                            pos = pos + 1 
                            esc = 0 
                        else 
                            esc = 1 
                            val = 0 
                        end if 
                    else 
                        if esc > 0 
                            esc = 0 
                            store byte val at asDst:dst+pos
                            pos = pos + 1 
                        end if 
                        store byte a at asDst:dst+pos
                        pos = pos + 1 
                    end if 
                end if 
            end repeat 
            if esc > 1 
              store byte val at asDst:dst+pos
              pos = pos + 1 
            end if 
            len = pos 
        end virtual 
}    
Post 16 Oct 2014, 13:29
View user's profile Send private message Visit poster's website Reply with quote
str8c



Joined: 14 Oct 2014
Posts: 8
str8c 16 Oct 2014, 14:08
Tomasz Grysztar wrote:
The macro itself may contain the complete "ecosystem" of labels. For instance, you can take some piece of code (containing both global and local labels) and wrap it up in a macro. To make it re-usable you then need only to insert a "local" directive with the names of global labels to make them unique every time the macro is called.

It may require more work to implement, but this behaviour would be preserved if "local" meant that the label (and its sub labels) should only have an effect on the current label inside the macro, even when it is "global" level label.

Tomasz Grysztar wrote:
Code:
macro .local [name]
 { local .name
   define name .name }    

I like this, but is there a nice way to prevent it from contaminating the name space? I can only think of something like this, which isn't very nice (something with fixes maybe?):
Code:
local asDst, dst
.local asDst, dst    
Post 16 Oct 2014, 14:08
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8359
Location: Kraków, Poland
Tomasz Grysztar 16 Oct 2014, 16:55
str8c wrote:
Tomasz Grysztar wrote:
Code:
macro .local [name]
 { local .name
   define name .name }    

I like this, but is there a nice way to prevent it from contaminating the name space? I can only think of something like this, which isn't very nice (something with fixes maybe?):
Code:
local asDst, dst
.local asDst, dst    
You can clean up the contamination with "restore" directive at the end of a macro. This can also be automated with some kind of enclosing macro construction, to avoid repeating the list of names:
Code:
macro .with [name]
{ common
   irpv previous,.with
   \{ restore previous
      restore .with \}
  forward
   local .name
   match any,name
   \{ define name .name
      define .with name \} }

macro str [string] 
{  
    common local pos, len, a, esc, val
    .with asDst,dst
        asDst:: dst rb len 
        virtual at 0  
            db string  
            pos = 0  
            esc = 0  
            repeat $  
                load a byte from %-1  
                if a >= '0' & a <= '7'  
                    if esc > 0  
                        if esc < 4  
                            esc = esc + 1  
                            val = val * 8 + a - '0'  
                        else  
                            esc = 0  
                            store byte val at asDst:dst+pos 
                            store byte a at asDst:dst+pos+1 
                            pos = pos + 2  
                        end if  
                    else  
                        store byte a at asDst:dst+pos 
                        pos = pos + 1  
                    end if  
                else  
                    if a = '\'  
                        if esc > 0  
                            store byte '\' at asDst:dst+pos 
                            pos = pos + 1  
                            esc = 0  
                        else  
                            esc = 1  
                            val = 0  
                        end if  
                    else  
                        if esc > 0  
                            esc = 0  
                            store byte val at asDst:dst+pos 
                            pos = pos + 1  
                        end if  
                        store byte a at asDst:dst+pos 
                        pos = pos + 1  
                    end if  
                end if  
            end repeat  
            if esc > 1  
              store byte val at asDst:dst+pos 
              pos = pos + 1  
            end if  
            len = pos  
        end virtual
    .with
}    
Post 16 Oct 2014, 16:55
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8359
Location: Kraków, Poland
Tomasz Grysztar 16 Oct 2014, 17:00
revolution wrote:
One extra function that I occasionally find missing (and perhaps inline macros could provide) is string manipulation for label names. For example: stripping a leading character is something I've never been able to do. Perhaps my knowledge is just lacking but it appears that it can't be done. We have the concatenate operator (#) but no equivalent extractor operator.
I've been thinking repeatedly about such feature in the recent years. Something like IRPC should be very simple to implement, but I fear it would be too clunky for the practical applications. Much more useful would be some extended variant of MATCH (MATCHX?) that would be able to cut through the tokens - but it would require a complex implementation. And implementing token-cutting as a macro-processor's operator (like #) would probably require some very cryptic syntax (even for fasm's standards).
Post 16 Oct 2014, 17:00
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20462
Location: In your JS exploiting you and your system
revolution 16 Oct 2014, 17:26
Tomasz Grysztar wrote:
... would probably require some very cryptic syntax (even for fasm's standards).
So only people at the level of advanced-god-3rd-level or higher would be able to figure it out. Smile
Post 16 Oct 2014, 17:26
View user's profile Send private message Visit poster's website Reply with quote
tthsqe



Joined: 20 May 2009
Posts: 767
tthsqe 16 Oct 2014, 20:13
I think this thread is hitting on something I was trying to do earlier. If I am understanding correctly this is not possible with fasm's current syntax?
Code:
macro log2(a) {
  local result=-1
  while a
    result=result+1
    a = a shr 1
  end while
  return result
}

and then use it like

 mov  eax,dword[index]
 shl  rax,log2(sizeof.MYSTRUCT) ; assume sizeof.MYSTRUCT is a power of 2
 add  rax,qword[ArrayOfStructs]    
Post 16 Oct 2014, 20:13
View user's profile Send private message Reply with quote
JohnFound



Joined: 16 Jun 2003
Posts: 3499
Location: Bulgaria
JohnFound 16 Oct 2014, 20:47
tthsqe, no, this is not FASM syntax and will not be compiled at all. There is no "inline macros" in FASM.

But, as explained in the above posts, the same problem can be solved with another code. More FASM-style. Read the whole thread for details.
Post 16 Oct 2014, 20:47
View user's profile Send private message Visit poster's website ICQ Number Reply with quote
cod3b453



Joined: 25 Aug 2004
Posts: 618
cod3b453 17 Oct 2014, 09:08
I've been using the attached macros by baldr to do single inline macros:
Code:
@! shl edx,! @log2 (1000) !    
I'd modified the macro name to @! and the delimiters to ! to distinguish it from my code; you can change these to suit by modifying the match statements. As well as manipulation/calculation it can also provide clearer code:
Code:
struc @imm8 [x]
{
        local c
        local y
 common
        c = 0
 forward
        c = c + 1
 common
        c = 8 / c
        y = 0
 forward
        y = (y shl c) or x
 common
        . equ y
}

@! pshuflw xmm4,xmm2,! @imm8 2,0,1,3 !    


Description:
Download
Filename: inlinemacro.zip
Filesize: 806 Bytes
Downloaded: 518 Time(s)

Post 17 Oct 2014, 09:08
View user's profile Send private message Reply with quote
l_inc



Joined: 23 Oct 2009
Posts: 881
l_inc 17 Oct 2014, 14:23
Tomasz Grysztar
Quote:
Much more useful would be some extended variant of MATCH (MATCHX?) that would be able to cut through the tokens

I've been going to suggest you to reuse numbers for the pattern argument of the match directive (instead of introducing a new matchx), and to defend the resulting insignificant compatibility break with a similar break introduced by the rept computation capability, but then I came across a little inconsistency in the rept computation processor:
Quote:
define 2 3
define 1 2
define y 1
define x y

rept x n : x { display '0'+n,13,10 }

This code displays "2", but it's displayed only once, even though the same symbol x is used. I'm sure, I've already came across this inconsistency when this topic appeared, but I failed to reproduce the problem afterwards.

We can have even more fun with that:
Code:
define 3 2define 4 3define 6 4define 5 6define y 4define x yrept x n : x { display '0'+n,13,10 }    

The output "3 6 4 7" makes me think that the redefinitions affect not only the way the initial value of n is calculated, but also the very incrementation process.

_________________
Faith is a superposition of knowledge and fallacy
Post 17 Oct 2014, 14:23
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8359
Location: Kraków, Poland
Tomasz Grysztar 17 Oct 2014, 15:43
l_inc wrote:
I'm sure, I've already came across this inconsistency when this topic appeared, but I failed to reproduce the problem afterwards.
revolution explained the issue very appropriately in that topic, REPT simply does not evaluate symbolic variables that are named as numbers. It only looks to expand the symbolic variables when it does not recognize the symbol as number. This information is hidden in this passage in the manual:
section 2.3.5 wrote:
(...) each value used in such expression must either be a directly specified number, or a symbolic constant with value also being an expression that can be calculated by preprocessor (...)
but it may be a bit too ambiguous.

l_inc wrote:
The output "3 6 4 7" makes me think that the redefinitions affect not only the way the initial value of n is calculated, but also the very incrementation process.
You are letting the symbolic variables to get evaluated once more, in the final preprocessing of line that then gets passed to assembler. To get a better look at what is going on here, compare it with the value that is generated by REPT's line maker:
Code:
define 3 2
define 4 3
define 6 4
define 5 6
define y 4
define x y

rept x n : x { display `n,' evaluates to ','0'+n,13,10 }     
Post 17 Oct 2014, 15:43
View user's profile Send private message Visit poster's website Reply with quote
l_inc



Joined: 23 Oct 2009
Posts: 881
l_inc 17 Oct 2014, 16:09
Tomasz Grysztar
Oh, I'm sorry. You're right. I've missed again, that the symbols are expanded once more. It's a kind of a situation, when I'm facing the same problem multiple times and can resolve it only a subset of those times.

_________________
Faith is a superposition of knowledge and fallacy
Post 17 Oct 2014, 16:09
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page Previous  1, 2

< 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-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.