flat assembler
Message board for the users of flat assembler.

Index > Main > switching from NASM to FASM

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



Joined: 14 Oct 2014
Posts: 8
str8c 14 Oct 2014, 21:51
I am writing some x86-64 assembly for a hobby project and have decided to switch from NASM to FASM, but FASM seems to be missing some useful features.

1. "constant" macros;
Code:
%define htons(x) (((x & 0xFF) << 8) | (x >> 8))
;then
mov eax, htons(1)
;is equivalent to
mov eax, 0x100
    

I did not find how to do this with FASM.

2. escape sequences in strings;
Code:
db `Hello World!\0`
;same as
db 'Hello World', 0
    

For this one, I modified the FASM source, replacing the ` operation with % and allowing backquote (`) strings with escape sequences like NASM.
Post 14 Oct 2014, 21:51
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20295
Location: In your JS exploiting you and your system
revolution 14 Oct 2014, 21:59
In both cases macro could do such things. It would look something like this:
Code:
macro htons reg,value {
   ;macro code here
}
macro cstring [string] {
   forward
   ;macro code here
}

htons eax,1
cstring 'Hello World!\0'    
Post 14 Oct 2014, 21:59
View user's profile Send private message Visit poster's website Reply with quote
str8c



Joined: 14 Oct 2014
Posts: 8
str8c 14 Oct 2014, 23:02
For the first case, consider this:
Code:
mov dword [rax + 12], htons(0x806) | (htons(1) << 16)
mov dword [rax + 16], htons(0x800) | ((6 | (4 << 8)) << 16)
    

How would I make a generic "htons" macroinstruction which can deal with cases like these too?

For the second case, I don't know how to make a macro to replace escape sequences in the string (my knowledge of FASM macros is still somewhat limited), can you provide a quick example?
Post 14 Oct 2014, 23:02
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20295
Location: In your JS exploiting you and your system
revolution 15 Oct 2014, 02:53
I've only ever seen htons used once in any particular program. And the prospect of writing a special macro to deal with all the millions of different ways it might be entered is probably not worth all the effort IMO. A macro could be made to do all of the above but it would be rather long an involved and its usefulness is limited.

For the c-string thing, I seem to recall someone else already doing that and posting a solution somewhere here. I don't have time to find it right now, but perhaps a but of search-fu could reveal an answer?
Post 15 Oct 2014, 02:53
View user's profile Send private message Visit poster's website Reply with quote
typedef



Joined: 25 Jul 2010
Posts: 2909
Location: 0x77760000
typedef 15 Oct 2014, 03:06
str8c wrote:
but FASM seems to be missing some useful features.


lol Confused Confused
Post 15 Oct 2014, 03:06
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20295
Location: In your JS exploiting you and your system
revolution 15 Oct 2014, 04:53
One useful feature that is missing is inline macros. This is why things like the htons example above require a bit more work to do with the current macro capabilities.

The c-string style is more a matter of familiarity than being demonstrably better or worse. With fasm's use of the angle brackets (<>) we can make single string values with embedded characters:
Code:
invoke function,<'abc',9,'123',0>    
Post 15 Oct 2014, 04:53
View user's profile Send private message Visit poster's website Reply with quote
edfed



Joined: 20 Feb 2006
Posts: 4330
Location: Now
edfed 15 Oct 2014, 07:49
fasmw:

ctrl + h: replace, "`" by "'"
and then, "\0'" by "',0"

Wink

replacing nasm by fasm is a very good idea then Smile
welcome
Post 15 Oct 2014, 07:49
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8349
Location: Kraków, Poland
Tomasz Grysztar 15 Oct 2014, 09:10
str8c wrote:
For the first case, consider this:
Code:
mov dword [rax + 12], htons(0x806) | (htons(1) << 16)
mov dword [rax + 16], htons(0x800) | ((6 | (4 << 8)) << 16)
    
How would I make a generic "htons" macroinstruction which can deal with cases like these too?

The language of fasm's preprocessor is very different from the counterparts in the other assembler. When you cannot translate something directly it appears to be a deficiency of the target language, but it may simply arise from the different philosophy behind it that causes a very different style to be used to perform analogous tasks. It may be like in the case of translating from language that allows multiple consecutive commands in the same line into a Python-like language, where you are suddenly forced to use line breaks.

And it is even worse in this case. fasm's preprocessor does not have inline macros - by design, it was intended to reflect the fact that assembly language is a "line-based" language, in which every instruction occupies a separate line. This leads to a different way of arranging the thoughts in code. Probably the closest possible translation of your "htons" snippet to fasm would look like:
Code:
struc htons x { . = ((x and 0xFF) shl 8) or (x shr 8) }

LO htons 0x806
HI htons 1
mov dword [rax+12],LO or (HI shl 16)    
And while I see that it could be viewed as inferior compared to HLL-like statements that use inline macros, I think it would be mainly because of the failure of direct translation. If the project as a whole was designed with language like fasm's in mind, perhaps a different overall structure would be used, stating all the programmer's thoughts just as clearly, only in a much different way.

str8c wrote:
For the second case, I don't know how to make a macro to replace escape sequences in the string (my knowledge of FASM macros is still somewhat limited), can you provide a quick example?

It is something I prepared quickly, but it is not really simple, even though it handles only the decimal escape values:
Code:
macro cstring [string] {
  common local src,len,a,esc,val
    virtual at 0
      src:: db string
      len = $
    end virtual
    esc = 0
    repeat len
      load a byte from src:%-1
      if esc>0
        if a>='0' & a<='9'
          esc = esc + 1
          val = val*10 + a-'0'
        else
          db val
          esc = 0
        end if
      else if a<>'\'
        db a
      end if
      if a='\'
        esc = 1
        val = 0
      end if
    end repeat
    if esc>1
      db val
    end if
}

cstring 'Hello World!\13\10\0'    
Post 15 Oct 2014, 09:10
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: 20295
Location: In your JS exploiting you and your system
revolution 15 Oct 2014, 10:48
I think the C escape values are in octal, not decimal.

"\12" is a line feed. And you have to limit the count of numbers to 3 so that things like ASCII numbers following can be supported.

"\0123" decodes to <10,"3">
Post 15 Oct 2014, 10:48
View user's profile Send private message Visit poster's website Reply with quote
str8c



Joined: 14 Oct 2014
Posts: 8
str8c 15 Oct 2014, 11:04
Tomasz Grysztar wrote:

...

Thanks for the reply.

As a C programmer, I would not say your solution for the first case is perfect, but it is more than satisfying.

For the second, the macro you provided was useful, but did not behave as expected (it skipped characters following escape sequences). Here is my revised version which works as expected:
Code:
macro str [string] {
common local src, len, a, esc, val
virtual at 0
    src:: db string
    len = $
end virtual
    esc = 0
    repeat len
        load a byte from src:%-1
        if a >= '0' & a <= '7'
            if esc > 0
                esc = esc + 1
                val = val * 8 + a - '0'
            else
                db a
            end if
        else
            if a = '\'
                if esc > 0
                    db '\'
                    esc = 0
                else
                    esc = 1
                    val = 0
                end if
            else
                if esc > 0
                    esc = 0
                    db val
                end if
                db a
            end if
        end if
    end repeat

    if esc > 1
      db val
    end if
}
    
Post 15 Oct 2014, 11:04
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20295
Location: In your JS exploiting you and your system
revolution 15 Oct 2014, 11:23
What does the following give?
Code:
str "\0123"    
And the C spec doesn't have a limit for hex values at all:
Code:
"\x1223420522545feda45" ;how many characters are generated?    
Post 15 Oct 2014, 11:23
View user's profile Send private message Visit poster's website Reply with quote
str8c



Joined: 14 Oct 2014
Posts: 8
str8c 15 Oct 2014, 11:32
revolution wrote:
What does the following give?
Code:
str "\0123"    
And the C spec doesn't have a limit for hex values at all:
Code:
"\x1223420522545feda45" ;how many characters are generated?    

I didn't need it for my uses, but here is another revised version which should correctly limit octal sequences to 3 characters ("\0123" becomes 10, "3"):
Code:
macro str [string] {
common local src, len, a, esc, val
virtual at 0
    src:: db string
    len = $
end virtual
    esc = 0
    repeat len
        load a byte from src:%-1
        if a >= '0' & a <= '7'
            if esc > 0
                if esc < 4
                    esc = esc + 1
                    val = val * 8 + a - '0'
                else
                    esc = 0
                    db val
                    db a
                end if
            else
                db a
            end if
        else
            if a = '\'
                if esc > 0
                    db '\'
                    esc = 0
                else
                    esc = 1
                    val = 0
                end if
            else
                if esc > 0
                    esc = 0
                    db val
                end if
                db a
            end if
        end if
    end repeat

    if esc > 1
      db val
    end if
}    
Post 15 Oct 2014, 11:32
View user's profile Send private message Reply with quote
l_inc



Joined: 23 Oct 2009
Posts: 881
l_inc 15 Oct 2014, 11:43
str8c
One remark about addressing space labels. If you use an addressing space label in a virtual addressing space, then the addressing space data becomes persistent across a compilation pass and this way more memory is used during the compilation. If you don't put an addressing space label into a virtual addressing space, then the memory is freed on closing the address space. This is an empirical discovery, thus I hope Tomasz Grysztar will confirm that.

For that reason I'd rather suggest to put an addressing space label outside of the virtual block and to store the converted data from inside of it to the outside addressing space. That's what I normally do to prevent wasting memory.

P.S. And you should always start label names (including addressing space labels) used in macros with a double dot. Otherwise you'll have to confront undesired effects.

_________________
Faith is a superposition of knowledge and fallacy
Post 15 Oct 2014, 11:43
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20295
Location: In your JS exploiting you and your system
revolution 15 Oct 2014, 11:47
l_inc wrote:
str8c
One remark about addressing space labels. If you use an addressing space label in a virtual addressing space, then the addressing space data becomes persistent across a compilation pass and this way more memory is used during the compilation. If you don't put an addressing space label into a virtual addressing space, then the memory is freed on closing the address space. This is an empirical discovery, thus I hope Tomasz Grysztar will confirm that.

For that reason I'd rather suggest to put an addressing space label outside of the virtual block and to store the converted data from inside of it to the outside addressing space. That's what I normally do to prevent wasting memory.
I don't know how one closes an address space? Confused Do you mean when switching to a new address space that the previous space is "closed"?

Also, are you meaning that the converted data should overwrite the original data?

Plus, I've never seen any method or function in fasm to "free" memory. It doesn't work that way.
Post 15 Oct 2014, 11:47
View user's profile Send private message Visit poster's website Reply with quote
l_inc



Joined: 23 Oct 2009
Posts: 881
l_inc 15 Oct 2014, 12:01
Quote:
I don't know how one closes an address space?

Closing a virtual addressing space is done with end virtual.
Quote:
Also, are you meaning that the converted data should overwrite the original data?

No. I mean, that the converted data should be written into a preallocated buffer.
Quote:
Plus, I've never seen any method or function in fasm to "free" memory

fasm does it's own kind of memory management, but I don't know the details.

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



Joined: 16 Jun 2003
Posts: 8349
Location: Kraków, Poland
Tomasz Grysztar 15 Oct 2014, 13:17
l_inc wrote:
If you don't put an addressing space label into a virtual addressing space, then the memory is freed on closing the address space. This is an empirical discovery, thus I hope Tomasz Grysztar will confirm that.
Yes, it's true. The details are a bit more complex, but it suffices to say that virtual block without "::" label saves both the memory and a bit of assembly time. But you have to be using them extensively in order to notice the difference.
Post 15 Oct 2014, 13:17
View user's profile Send private message Visit poster's website Reply with quote
str8c



Joined: 14 Oct 2014
Posts: 8
str8c 15 Oct 2014, 15:44
l_inc wrote:
For that reason I'd rather suggest to put an addressing space label outside of the virtual block and to store the converted data from inside of it to the outside addressing space. That's what I normally do to prevent wasting memory.

Can you provide an example of how you would do this (I am still a bit lost when I comes to FASM's more complex macro features)?

l_inc wrote:

P.S. And you should always start label names (including addressing space labels) used in macros with a double dot. Otherwise you'll have to confront undesired effects.

I realized this, is there any reason FASM doesn't do this automatically for local labels?
Post 15 Oct 2014, 15:44
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8349
Location: Kraków, Poland
Tomasz Grysztar 15 Oct 2014, 16:17
str8c wrote:
l_inc wrote:

P.S. And you should always start label names (including addressing space labels) used in macros with a double dot. Otherwise you'll have to confront undesired effects.

I realized this, is there any reason FASM doesn't do this automatically for local labels?
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.
Post 15 Oct 2014, 16:17
View user's profile Send private message Visit poster's website Reply with quote
l_inc



Joined: 23 Oct 2009
Posts: 881
l_inc 15 Oct 2014, 22:55
Tomasz Grysztar
Quote:
Yes, it's true. The details are a bit more complex

OK. Thanks for the confirmation.
Quote:
But you have to be using them extensively in order to notice the difference.

I suppose, string definition is something that might appear many times in a project. Lots of the resulting persistent memory spaces might eat up the memory in case of larger projects.
str8c
Quote:
Can you provide an example of how you would do this

I've just blindly rewritten your last macro without considering any meaning behind the code (it's been a long hard day):
Code:
macro str [string]
{
    common local ..asDst, ..dst, 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
}    

Quote:
I realized this, is there any reason FASM doesn't do this automatically for local labels?

Tomasz Grysztar has already answered that, thus I just want to explain my wording. "Always" and "undesired" refer to common cases. If you know that the effects of a regular global label are exactly what you want to have, then you obviously would not prepend it with a double dot. For the same reason I could say, that you should never use an anonymous label in a macro, but I expect readers to sieve that through a bit of common sense and not to take that "always" for an immutable law.

_________________
Faith is a superposition of knowledge and fallacy
Post 15 Oct 2014, 22:55
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20295
Location: In your JS exploiting you and your system
revolution 16 Oct 2014, 02:32
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.
Post 16 Oct 2014, 02:32
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:  
Goto page 1, 2  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.