flat assembler
Message board for the users of flat assembler.

Index > Macroinstructions > coalesce - a data migration scheme for fasmg

Author
Thread Post new topic Reply to topic
bitRAKE



Joined: 21 Jul 2003
Posts: 4046
Location: vpcmpistri
bitRAKE 16 Mar 2021, 02:45
coalesce.inc
Code:
; coalesce - a data migration scheme for fasmg
;
; Often we want to specify data with our code, but we want to position the data
; elsewhere within the object file. This is one way.

__MAX_DATA_ALIGNMENT__ := 64

; initialize global contexts to empty for the needed alignments
repeat 1 + (bsf __MAX_DATA_ALIGNMENT__)
        ; reverse order to eliminate alignment gaps
        repeat 1,k:1 shl (%% - %)
                ; gather into single collection for each zone
                ; other complex structures can be added to these (align if needed!)
                __DATA  equ DATA#k
                __CONST equ CONST#k
                __BSS   equ BSS#k

                DATA#k  equ __
                CONST#k equ __
                BSS#k   equ __
        end repeat
end repeat
macro __
end macro

; Now we can defined data anywhere like:
;       DATA1 equ myString db "Hello World!",0
;       BSS8 equ hOutput rq 1
;
; ...and custom weird data object:
;       __DATA_table equ align 256                      ; literally specified
;       __DATA_table equ file 'byte_table.bin'          ; complex type
;       __DATA equ __DATA_table                         ; add to collection


; DATA, CONST, BSS are put in place with the following code, respectively:

align __MAX_DATA_ALIGNMENT__
irpv DN,__DATA
irpv D,DN
D ; define data
end irpv
end irpv

align __MAX_DATA_ALIGNMENT__
irpv CN,__CONST
irpv C,CN
C ; define data
end irpv
end irpv

align __MAX_DATA_ALIGNMENT__
irpv BN,__BSS
irpv B,BN
B ; define data
end irpv
end irpv    
It's not pretty, but it does work.

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup


Last edited by bitRAKE on 16 Mar 2021, 03:39; edited 3 times in total
Post 16 Mar 2021, 02:45
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4046
Location: vpcmpistri
bitRAKE 16 Mar 2021, 03:04
Of course, we extend with other macros for convenient data defining:
Code:
struc(name) const_utf8_array quoted&
CONST8 equ label name:8
iterate S,quoted
        CONST1 equ name#% db S,0
        CONST8 equ dq name#%
end iterate
CONST8 equ dq 0
end struc    

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup
Post 16 Mar 2021, 03:04
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4046
Location: vpcmpistri
bitRAKE 16 Mar 2021, 10:04
There are a lot of tricks to force the scheme to work:
Code:
macro FatalAppExit quoted&
        repeat 1,x:`quoted
        CONST2. equ ?x du quoted,0
        xor ecx,ecx
        lea edx,[?x.]
        call [FatalAppExitW]
        end repeat
end macro    
The above can be used from one namespace deep, but doesn't work through several layers. The solutions is to switch to ".." prefixes which makes the symbols global. That doesn't work though - I don't think there really is a global context - only global within one namespace.

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup
Post 16 Mar 2021, 10:04
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8356
Location: Kraków, Poland
Tomasz Grysztar 16 Mar 2021, 10:56
When making symbolic links, DEFINE might be safer choice than EQU. But perhaps it does not matter here, since your framework seems to require a strict ordering - IRPV cannot forward-reference, so it needs to have everything defined before the place where it is put into.
bitRAKE wrote:
There are a lot of tricks to force the scheme to work:
Code:
macro FatalAppExit quoted&
        repeat 1,x:`quoted
        CONST2. equ ?x du quoted,0
        xor ecx,ecx
        lea edx,[?x.]
        call [FatalAppExitW]
        end repeat
end macro    
The above can be used from one namespace deep, but doesn't work through several layers. The solutions is to switch to ".." prefixes which makes the symbols global. That doesn't work though - I don't think there really is a global context - only global within one namespace.
Why not simply use a truly local namespace here?
Code:
macro FatalAppExit quoted&
        local x
        CONST2. equ x du quoted,0
        xor ecx,ecx
        lea edx,[x]
        call [FatalAppExitW]
end macro    
Post 16 Mar 2021, 10:56
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4046
Location: vpcmpistri
bitRAKE 16 Mar 2021, 13:10
Quote:
IRPV cannot forward-reference, so it needs to have everything defined before the place where it is put into.
I tried really hard to get it to do that, lol.

Tried the local namespace but didn't realize my "CONST2" naming was the problem at that point, and didn't back-track once I did solve that.

Thought I was taking the difficult route. Thank you.

Should be able to refactor most things to a couple namespaces.

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup
Post 16 Mar 2021, 13:10
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4046
Location: vpcmpistri
bitRAKE 16 Mar 2021, 14:15
IRPV also works with DEFINE - I don't know why I thought it didn't.
Now if it worked with macros I'd be shocked.

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup
Post 16 Mar 2021, 14:15
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8356
Location: Kraków, Poland
Tomasz Grysztar 16 Mar 2021, 14:38
bitRAKE wrote:
Quote:
IRPV cannot forward-reference, so it needs to have everything defined before the place where it is put into.
I tried really hard to get it to do that, lol.
The easiest would be to use POSTPONE to convert the collected lines into a macro that you can forward-reference. In order to define macro contents with IRPV loop, you need something like a "macro builder".

To make one, you could use the same pattern that works for fasm 1 (and I actually used the same method in the Mach-O formatter for fasmg, search for "macroBuilder" there).

However, CALM allows to do the trick in a less resource-hungry fashion. This instruction assembles all lines collected in variable named MacroBuilder:
Code:
define MacroBuilder

calminstruction MacroBuilder.instantiate
        local stack, line
    reverse:
        take stack, MacroBuilder
        jyes reverse
    process:
        take line, stack
        jno  done
        assemble line
        jump process
    done:
end calminstruction

restore MacroBuilder    
You can use it to convert collected lines into forward-referable macros in POSTPONE block:
Code:
postpone

        define MacroBuilder macro DATA
        define MacroBuilder align __MAX_DATA_ALIGNMENT__
        irpv DN,__DATA
                irpv D,DN
                        define MacroBuilder D
                end irpv
        end irpv
        define MacroBuilder end macro
        MacroBuilder.instantiate

        define MacroBuilder macro CONST
        define MacroBuilder align __MAX_DATA_ALIGNMENT__
        irpv CN,__CONST
                irpv C,CN
                        define MacroBuilder C
                end irpv
        end irpv
        define MacroBuilder end macro
        MacroBuilder.instantiate

        define MacroBuilder macro BSS
        define MacroBuilder align __MAX_DATA_ALIGNMENT__
        irpv BN,__BSS
                irpv B,BN
                        define MacroBuilder B
                end irpv
        end irpv
        define MacroBuilder end macro
        MacroBuilder.instantiate

end postpone    
and then you can put the data definitions anywhere in the source simply by calling these macros:
Code:
; DATA, CONST, BSS are put in place with the following code, respectively:
DATA
CONST
BSS     
Post 16 Mar 2021, 14:38
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4046
Location: vpcmpistri
bitRAKE 16 Mar 2021, 15:29
When I use EQU the IRPV only evaluates for non-empty items - no matter how many alignment groups I have. The dummy no-op macro was created to force each alignment group being examined, and it doesn't work like I thought fasmg skips over them. Whereas because DEFINE is symbolic it loops over empty symbols - even if they are blank. I'm not sure how it works, but EQU seems optimal unless I need delayed evaluation.

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup
Post 16 Mar 2021, 15:29
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8356
Location: Kraków, Poland
Tomasz Grysztar 16 Mar 2021, 18:13
I only meant specific places where you use EQU to form symbolic links, like:
Code:
                __DATA  equ DATA#k
                __CONST equ CONST#k
                __BSS   equ BSS#k    
Here DEFINE would be safer in general, as it would always create a link, even if symbols like DATA1 were already defined (because EQU would then evaluate them in the value before assignment).

EDIT: In fact, this is what may be causing the behavior that you describe. When you have DATA1 defined only once (with default "___" value), it becomes forward-referable and then:
Code:
__DATA equ DATA#1    
becomes equivalent to:
Code:
__DATA equ ___    
or, strictly speaking, equivalent to:
Code:
define __DATA ___    
This is the same as with fasm 1 - EQU replaces symbolic variables in the text to assign, DEFINE doesn't. The difference from fasm 1 is that symbolic variables may be forward-referenced in a manner similar to how fasm 1 allowed forward-referencing numeric ones.
Post 16 Mar 2021, 18:13
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4046
Location: vpcmpistri
bitRAKE 17 Mar 2021, 01:28
Any alignment groups I don't use are factored out early. Even for the case of empty macro results - which is a wonderfully scalable thing. fasmg is amazing.

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup
Post 17 Mar 2021, 01:28
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-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.