flat assembler
Message board for the users of flat assembler.

Index > Compiler Internals > [fasmg] Undocumented number feature: '_'

Author
Thread Post new topic Reply to topic
Jessé



Joined: 03 May 2025
Posts: 92
Location: Brazil
Jessé 08 Mar 2026, 10:24
Recently, while browsing fasmg's source code (which I do sometimes), I found something - at 'expressions.inc' file - which seems that it could be used as a "number joining" char, just like I already do with '#':

Code:
format ELF64 executable 3

include 'fastcall_v1.inc'
include 'stdmacros.inc'
include 'stdio.inc'

_code   Start entry         endbr64
                            push        60                  ; compute value for 1 minute aprox. collect
                            fild        qword [rsp]
                            fild        [loop_delay.sec]
                            fild        [nsec_2sec]
                            fild        [loop_delay.nsec]
                            fdivrp
                            faddp
                            fdivp
                            fistp       qword [rsp]
                            wait
                            pop         rdx
                            printf("Wait result: %lu repeats."\n, rdx);
                            exit(0);

        align 8
        loop_delay:
            .sec            dq 0
            .nsec           dq 100_000_000

        nsec_2sec           dq 1_000_000_000
        testbin             db 1000_0000b
        testoct             dd 0716_3477_11o
        testhex             dd 0A3F_1237h

    


This is a simple test I was doing, and it compiles successfully, and the binary generated numbers are correct. By finding it working properly, I already included in a syntax highlighting file I'm doing for fasm2/fasmg (which I will make it public soon), as well as with '#' char (that can be used to fit the same purpose).

This is great, because it improves number readability a lot, and I was quite used to it because of my previous assembler - nasm. And I also found that ' (0x27) char can also be used as well.

The main question is: should we rely on it, or it is not promised to be kept working in fasmg?
I can't find anything about it at current documentation.

Regards,

_________________
jesse6
Post 08 Mar 2026, 10:24
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8518
Location: Kraków, Poland
Tomasz Grysztar 08 Mar 2026, 10:56
It's one of the fasm-compatibility features. Apparently I did not put any information about this feature into fasm's manual either, but you may find the discussion that lead to it's introduction here.
Post 08 Mar 2026, 10:56
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: 20913
Location: In your JS exploiting you and your system
revolution 08 Mar 2026, 18:05
Both single-quote and underscore are valid numeric padding characters.
Code:
db 1_0'0
db 1'0_0    
They get ignored when parsing numbers.
Post 08 Mar 2026, 18:05
View user's profile Send private message Visit poster's website Reply with quote
Jessé



Joined: 03 May 2025
Posts: 92
Location: Brazil
Jessé 13 Mar 2026, 21:34
Indeed, great stuff to have both syntaxes in fasm(g|2)!

Code:
; cmpxchg demo

format ELF64 executable 3

include 'fastcall_v1.inc'
include 'stdmacros.inc'
include 'stdio.inc'

macro prefetcht2? var*
    match =byte? [mem], var
        prefetcht2 byte [mem]
    else match [mem], var
        prefetcht2 byte [mem]
    else
        err "Syntax error", 10
    end match
end macro

_code rwx Start entry       endbr64
                            libc.StartMain ( & @f );

        align 4
        counter             dd 200

                    @@      endbr64
                            prefetcht2  [ counter ]
                            enter       16, 0

                            pthread_create ( rsp, NULL, & Thread_dec, NULL );
                            mov         eax, [ counter ]

                    @@      fprintf ( ** stdout, < 8,8,8,8,8,8,8,8, \
                                32,32,32,32,32,32,32,32,13,"Counter is now at: %d",0 >, eax );
                            usleep ( 50'000 );
                            fflush ( ** stdout );
                            mov         eax, -201
                            mov         edx, 8000_0001h
                            cmpxchg     [ counter ], edx
                            jne         @b
                            fprintf ( ** stdout, \n "Done."\n "Replaced by: 0x%08X"\n, * counter );

                            xor         eax, eax
                            leave
                            ret

        Thread_dec:         endbr64
                            enter       0, 0

                    @@      usleep ( 100'000 );
                            cmp         [ counter ], 8000_0001h
                            je          @f
                            lock dec    [ counter ]
                            jmp         @b

                    @@      leave
                            xor         eax, eax
                            ret

    


To my "eyes", each one now has its own place.
Post 13 Mar 2026, 21:34
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-2026, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.