flat assembler
Message board for the users of flat assembler.

Index > Tutorials and Examples > [fasmg] The amazing 'match' brother: 'rawmatch'!

Author
Thread Post new topic Reply to topic
Jessé



Joined: 03 May 2025
Posts: 92
Location: Brazil
Jessé 01 Mar 2026, 22:44
Hello flat assembler people!

I did a macro recently (not the most useful one, but one will know for sure when it could make the day easier), with an important concept I want to share with you:

The macro:
Code:
macro enum start, names&
    match =step= val, start
        __ENUM_STEP__ = val
    else
        if ~ start eqtype 0
            err "Invalid 'enum' enumeration macro usage", 10
        else
            local count
            count = start
            iterate name, names
                rawmatch const == value, name
                    repeat 1, i:value
                        define const i
                        if defined __ENUM_DEBUG__
                            display "Const: ",`const," Value: ",`i,10
                        end if
                    end repeat
                    count = value
                else
                    repeat 1, i:count
                        define name i
                        if defined __ENUM_DEBUG__
                            display "Const: ", `name, " Value: ", `i, 10
                        end if
                    end repeat
                end rawmatch
                if defined __ENUM_STEP__
                    count = count + __ENUM_STEP__
                else
                    count = count + 1
                end if
            end iterate
        end if
    end match
end macro
    


Test subject:
Code:
; Demonstration on enum macro feature 'VAL = new',
; which creates the new value, and reassign it
; to the enum counter
;
; 'enum' syntax:
;
;    enum <start value>, sym1, sym2, ..., symN
;
;    enum step <step value> ; set step increment value
;
include 'stdmacros.inc'

define __ENUM_DEBUG__

; default step is already 1
enum 1, VALUE_A,\       ; = 1
        VALUE_B,\       ; = 2
        VALUE_C,\       ; = 3
        VALUE_D,\       ; = 4
        VALUE_E,\       ; = 5
        VALUE_J=10,\    ; = 10
        VALUE_K,\       ; = 11
        VALUE_L         ; = 12

enum step 8
enum 8, INDEX_A,\       ; = 8
        INDEX_B,\       ; = 16
        INDEX_C,\       ; = 24
        INDEX_D,\       ; = 32
        INDEX_E,\       ; = 40
        INDEX_J = 10*8,\; = 80
        INDEX_K,\       ; = 88
        INDEX_L         ; = 96

enum step 1
enum 100,   HUN,\       ; = 100
            HUN_P1,\    ; = 101
            HUN_P2,\    ; = 102
            HUN_P3,\    ; = 103
            HUM_P4      ; = 104
    


In the above example (I mean the macro code itself), 'rawmatch' is indispensable for it to work, because it does not evaluate any text (I guess, right?), it just passes it to the matching sentence.

With 'match', it ended not being compiled, and also enters a recursion loop, because it evaluates 'something = else'.

So, not only we have the amazing 'match' directive here, but also its very good complement, 'rawmatch' to this peculiar situations!

Thanks,

_________________
jesse6
Post 01 Mar 2026, 22:44
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4407
Location: vpcmpistri
bitRAKE 02 Mar 2026, 09:27
F&F*, thank you for sharing.

What about making the step more general?

We see with advanced align macro, we can define a function that performs the alignment.

Often with enum we want to work with bits. Sometimes I call these "inums" - inclusive verses exclusive sets.
Code:
; the default would be something like:
enum step # + 1

; and bit masks could be defined like:
enum step # shl 1
enum ,  PERM_READ,\     ; = 1h
        PERM_WRITE,\    ; = 2h
        PERM_EXECUTE,\  ; = 4h
        PERM_DELETE,\   ; = 8h
        PERM_SHARE,\    ; = 10h
        PERM_AUDIT,\    ; = 20h
        PERM_OWNER,\    ; = 40h
        PERM_ADMIN      ; = 80h

; or any complexity the user desires:
enum step MyStep #    
... similar to align, but using a labeled macroinstruction to update the internal value.

Of course, this is just a nicety - we could use indices to access the bits. The masking instructions (TEST/OR/AND/XOR) are typically smaller and faster than the bit indexing instructions (BT*). Perhaps it would just suggest a different usage perspective as fasmg can translate either direction at assemble-time.

* "first and foremost," only a little bit "Fast & Furious" and "Friends & Family." Smile

_________________
¯\(°_o)/¯ AI may [not] have aided with the above reply.
Post 02 Mar 2026, 09:27
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8516
Location: Kraków, Poland
Tomasz Grysztar 02 Mar 2026, 10:34
Jessé wrote:
In the above example (I mean the macro code itself), 'rawmatch' is indispensable for it to work, because it does not evaluate any text (I guess, right?), it just passes it to the matching sentence.

With 'match', it ended not being compiled, and also enters a recursion loop, because it evaluates 'something = else'.
You could work around the problem in a more traditional way (like it was usually done with old fasm's MATCH), with a temporary variable:
Code:
                local proxy
                define proxy name
                match const == value, proxy    
The RAWMATCH has an additional effect, because it not only takes the text as-is, but it also strips it of any context information. This may be not desirable, so you have to decide which solutions works better for your use case.

The difference is subtle and not easy to demonstrate well, but let me try a quick example with your macro:
Code:
macro x args&
    Foo:
        enum 1, args
end macro

Bar:
        x .a, .b, .j=10, .k    
The way fasmg's context works, this macro should define symbols like "Bar.a", "Bar.b", "Bar.j". However, since you used RAWMATCH, the text of name like ".a" becomes contextless again, and is interpreted in the new context, so it becomes viewed as "Foo.a" instead. If you switch between RAWMATCH and the classic solution I proposed above, you can see that one of them defines symbols relative to "Foo", the other one relative to "Bar".
Post 02 Mar 2026, 10:34
View user's profile Send private message Visit poster's website Reply with quote
Jessé



Joined: 03 May 2025
Posts: 92
Location: Brazil
Jessé 03 Mar 2026, 10:12
Very nice suggestion, bitRAKE, I will consider it and change soon.
There were situations where I needed to sequence constants like that.

Tomasz, for a moment I forgot the proxy idea, many thanks for the advices and also the clarification about 'rawmatch'.
It also went unnoticed that all context is removed, and that's certainly an important point to consider.

I also must mention that the fasmg manual has a really cool enum example (really cool) that I overlooked for a moment.
Probably I'll experiment a little with that approach, too.
Post 03 Mar 2026, 10:12
View user's profile Send private message Visit poster's website Reply with quote
Jessé



Joined: 03 May 2025
Posts: 92
Location: Brazil
Jessé 04 Mar 2026, 00:23
I did the correction and add the feature as suggested.

It looks great:
Code:
    macro enum start, names&
        match =step= val, start
            define __ENUM_STEP__ val
        else
            if ~ start eqtype 0
                err "Invalid 'enum' enumeration macro usage", 10
            else
                local count
                count = start
                iterate name, names
                    local proxy
                    define proxy name
                    match const == value, proxy
                        repeat 1, i:value
                            define const i
                            if defined __ENUM_DEBUG__
                                display "Const: ",`const," Value: ",`i,10
                            end if
                        end repeat
                        count = value
                    else
                        repeat 1, i:count
                            define name i
                            if defined __ENUM_DEBUG__
                                display "Const: ", `name, " Value: ", `i, 10
                            end if
                        end repeat
                    end match
                    match =shl?= val, __ENUM_STEP__
                        count = count shl val
                    else
                        if defined __ENUM_STEP__
                            count = count + __ENUM_STEP__
                        else
                            count = count + 1
                        end if
                    end match
                end iterate
            end if
        end match
    end macro
    


I should point out that I had to change the 'if defined' statement one step "below", because it didn't deal well with global variable __ENUM_STEP__ being 'shl 1'. 'match' did it right even when global variable isn't defined, so, not an issue at all.
Anyways, it worked fine, and fully compatible with what I already had published. So, here to stay, from now on... Wink

Test subject (v1.1):
Code:
; Demonstration on enum macro feature 'VAL = new',
; which creates the new value, and reassign it
; to the enum counter
;
; 'enum' syntax:
;
;    enum <start value>, sym1, sym2, ..., symN
;
;    enum step <step value> ; set step increment value
;
include 'stdmacros.inc'

define __ENUM_DEBUG__

; default step is already 1
enum 1, VALUE_A,\       ; = 1
        VALUE_B,\       ; = 2
        VALUE_C,\       ; = 3
        VALUE_D,\       ; = 4
        VALUE_E,\       ; = 5
        VALUE_J=10,\    ; = 10
        VALUE_K,\       ; = 11
        VALUE_L         ; = 12

enum step 8
enum 8, INDEX_A,\       ; = 8
        INDEX_B,\       ; = 16
        INDEX_C,\       ; = 24
        INDEX_D,\       ; = 32
        INDEX_E,\       ; = 40
        INDEX_J = 10*8,\; = 80
        INDEX_K,\       ; = 88
        INDEX_L         ; = 96

enum step 1
enum 100,   HUN,\       ; = 100
            HUN_P1,\    ; = 101
            HUN_P2,\    ; = 102
            HUN_P3,\    ; = 103
            HUN_P4      ; = 104

enum step shl 1
enum 1,     N_E0,\      ; = 1 = 1b
            N_E1,\      ; = 2 = 10b
            N_E2,\      ; = 4 = 100b
            N_E3,\      ; = 8 = 1000b
            N_E4,\      ; = 16 = 10000b
            N_E5,\      ; = 32 = 100000b
            N_E6,\      ; = 64 = 1000000b
            N_E7        ; = 128 = 10000000b
    


Thanks for the advices and recommendations,
Post 04 Mar 2026, 00:23
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.