flat assembler
Message board for the users of flat assembler.

Index > Macroinstructions > How to get each character from a string in a macro (fasmg)

Author
Thread Post new topic Reply to topic
Rostrocop



Joined: 24 Nov 2025
Posts: 4
Rostrocop 24 Nov 2025, 13:36
Hi everyone,

I am trying to create a macro to add an attribute value (a byte) between each character of a given string. For example, the following call:

Code:
str_with_attr game_over_string "GAME OVER", 0x1F
    


would become:

Code:
game_over_string:
'G',0x1F,'A',0x1F,'M',0x1F,'E',0x1F,' ',0x1F,'O',0x1F,'V',0x1F,'E',0x1F,'R',0x1F
    


This is what I have tried, unfortunately it does not work, it takes the entire string, not each character from it.

Code:
macro str_with_attr label_name, str, attr
        label_name:
        iterate char, str
            db char, attr
        end iterate
end macro
    
[/code]
Post 24 Nov 2025, 13:36
View user's profile Send private message Reply with quote
Serke



Joined: 26 Aug 2006
Posts: 9
Serke 24 Nov 2025, 16:13
Code:
macro str_with_attr label_name, str, attr
        label_name:
        repeat lengthof str
                db (str shr ((%-1) * 8)) and 0xff
                db attr
        end repeat
end macro    

or
Code:
macro str_with_attr label_name, str, attr
        local area_label
        label_name:
        virtual at 0
            area_label::
                db str
        end virtual
        repeat sizeof area_label
                load char : byte from area_label : %-1
                db char, attr
        end repeat
end macro    
Post 24 Nov 2025, 16:13
View user's profile Send private message Reply with quote
Rostrocop



Joined: 24 Nov 2025
Posts: 4
Rostrocop 24 Nov 2025, 16:31
Thank you so much Serke, I have a lot to learn. Could you please explain a little bit the first example? It looks great, but I am having a hard time understaing how it works.

By the way, do you know if there is any documentation about fasmg macro syntax besides the official fasmg user manual?

Best regards.
Post 24 Nov 2025, 16:31
View user's profile Send private message Reply with quote
Serke



Joined: 26 Aug 2006
Posts: 9
Serke 24 Nov 2025, 19:48
Rostrocop wrote:
Thank you so much Serke, I have a lot to learn. Could you please explain a little bit the first example? It looks great, but I am having a hard time understaing how it works.

By the way, do you know if there is any documentation about fasmg macro syntax besides the official fasmg user manual?

Best regards.

The first and second examples are similar, the difference lies in how the string is processed.
In the second example, the string is basically treated as an array-like sequence of characters (or bytes).
In the first example, however, the string is implicitly converted to a number because a bitwise operation is applied to it. That number is right-shifted (shr) for each character by the character’s position multiplied by 8 (since each ASCII character occupies 8 bits) and masked with 'and 0xff' to extract the individual character’s byte.

For example, consider the string "Bye".
'B' 'y' 'e' correspond to ASCII codes 42 79 65.
When converted to a single number, this becomes 0x657942 ('eyB' in memory order).

Here is what happens inside the repeat loop:

Iteration 1
Shift right by (%-1) * 8 = (1-1) * 8 = 0 bits: 0x657942
Mask with 0xff: 0x42 ('B')

Iteration 2
Shift right by (%-1) * 8 = (2-1) * 8 = 8 bits: 0x006579
Mask with 0xff: 0x79 ('y')

Iteration 3
Shift right by (%-1) * 8 = (3-1) * 8 = 16 bits: 0x000065
Mask with 0xff: 0x65 ('e')

I hope this helps.
Post 24 Nov 2025, 19:48
View user's profile Send private message Reply with quote
Rostrocop



Joined: 24 Nov 2025
Posts: 4
Rostrocop 24 Nov 2025, 21:22
Thank you for taking the time to write such a detailed explanation. In the first example, when you say that the string is implicitly converted to a number, do you mean a sequence of bytes? Otherwise there would be a limit of bits depending on the target processor (for example, 8 bytes in x64). Also, the order is little endian, is that dependant on the target processor or is it always the same order regardless of the processor?

As for the second example, I suppose the use of "virtual at 0" is some kind of "discard" area that is only valid while the macro is being executed, am I right?
Post 24 Nov 2025, 21:22
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8490
Location: Kraków, Poland
Tomasz Grysztar 24 Nov 2025, 21:49
Rostrocop wrote:
Thank you for taking the time to write such a detailed explanation. In the first example, when you say that the string is implicitly converted to a number, do you mean a sequence of bytes? Otherwise there would be a limit of bits depending on the target processor (for example, 8 bytes in x64). Also, the order is little endian, is that dependant on the target processor or is it always the same order regardless of the processor?
fasmg operates on numbers with arbitrary length, you do not get an overflow. Also fasm/fasmg define all the operations on numbers as if they were done on the infinite 2-adic representations of those numbers, and the little-endian order comes as a natural consequence of that (see my video about the 2-adic approach for more information). Any string of bytes can therefore be interpreted as an arbitrary-length number, and this is what fasmg does when you use a string in an arithmetic expression.

Rostrocop wrote:
As for the second example, I suppose the use of "virtual at 0" is some kind of "discard" area that is only valid while the macro is being executed, am I right?
Yes, a "discard area" is a good way to put it. VIRTUAL is one of fasm's defining features that it had since the beginning. It allows to define any data and/or instructions (plus labels) without them going into the output. LOAD/STORE commands can access such block of bytes, allowing for many possible uses, including string conversion like done here.
Post 24 Nov 2025, 21:49
View user's profile Send private message Visit poster's website Reply with quote
Rostrocop



Joined: 24 Nov 2025
Posts: 4
Rostrocop 24 Nov 2025, 23:42
Hi Tomasz! Thank you for your response, everything is clear now.

P.S. I was just watching your videos about real mode, they are great. I am really enjoying programming again after many years (I am 47 now). I had my first computer (an Amstrad PCW) when I was 7 years old, so I like the simplicity of old school computers and operating systems, and fasm is a great tool for experimenting with that. In fact, I have just finished my first boot sector game Smile

Best regards.
Post 24 Nov 2025, 23:42
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8490
Location: Kraków, Poland
Tomasz Grysztar 25 Nov 2025, 17:17
One more thing: I think it would be more natural to use STRUC here instead of MACRO:
Code:
struc (label_name) str_with_attr str, attr
        local area_label
        label_name:
        virtual at 0
            area_label::
                db str
        end virtual
        repeat sizeof area_label
                load char : byte from area_label : %-1
                db char, attr
        end repeat
end struc

game_over_string str_with_attr "GAME OVER", 0x1F    
Post 25 Nov 2025, 17:17
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-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.