Hi,
I'm designing some complex macro system in MASM. The basics looks as follows:


AddToListmacro const1, const2, ... ; add new constants to list, no code
somemacro1 bbc ; expand some code
somemacro2 cbc
endingmacro dbc
AddToListmacro const3, const4, ... ; add new constants to list, no code
somemacro3 fbc ; expand some other code
somemacro4 gbc
somemacro5 hbc
endingmacro ibc
...

i.e. there is always block of somemacros (somemacroX), which is always inducted by AddToListmacro.

The problem lies in fact that all somemacros depend the whole list (being created by AddToList), not only on the partial list created at time of expanding the somemacros.
I have only one idea: declare blocks between AddToListmacros as macros (wrap the block with macro) and expand them at the end, when whole list is already created, using some macro, say "ExpandAllmacro". It causes prohibition of expanding of somemacros at their original locations.
I got an idea that the AddToListmacro could define header of the wrapping macro "wrappingmacroX MACRO" and the endingmacro footer, actually only "ENDM".

It could look like that:


AddToListmacro MACRO
; ...original macro code...

temp1 TEXTEQU %WRAPPING_CNT ; ordinal number of current wrapping macro
WRAPPING_CNT = WRAPPING_CNT + 1

temp2 CATSTR <wrappingmacro>, %temp1, <MACRO>
temp2 ; defines header of wrappingmacro after expanding this macro
ENDM



endingmacro MACRO
temp TEXTEQU <ENDM>
temp ; defines footer of currently opened wrappingmacro

; ...oiginal macro code...
ENDM



ExpandAllmacro MACRO
; concatenate names of all defined wrapping macros
ENDM

I did some testing and it seems to be working.
Nevertheless, I'm asking here because I'm not absolutely sure (I'm no so experienced) and other members could see any other solution to this macro problem.
Posted on 2004-10-24 11:30:15 by MazeGen
IIRC, a macro within a macro has access to local and passed params of parent macro. It is difficult to discern what you are trying to achieve. Hopefully you found a new technique.
Posted on 2004-10-24 18:22:25 by bitRAKE
:) Hi guru,

It is difficult to discern what you are trying to achieve.

I'll show it with a sample:


.686
.MODEL FLAT, STDCALL

.LISTMACROALL

AddToListmacro MACRO arg1, arg2
; ...original code here...

; in this example, this macro creates no list, only creates CONST1-4;
; CONST3 and 4 would be forward-referenced by somemacro1 and somemacro2

CONST&arg1 EQU arg1
CONST&arg2 EQU arg2

; concatenate header of wrappingmacro

temp2 CATSTR <wrappingmacro>, %WRAPPING_CNT, < MACRO>
temp2 ; defines header of wrappingmacro after expanding this macro

WRAPPING_CNT = WRAPPING_CNT + 1
ENDM

endingmacro MACRO
temp TEXTEQU <ENDM>
temp ; defines footer of currently opened wrappingmacro
; ...original code here...
ENDM

ExpandAllmacro MACRO
; concatenate names of all defined wrapping macros:

count = 0
WHILE count NE WRAPPING_CNT
@CatStr( <wrappingmacro>, %count ) ; call all wrappingmacros at the end
count = count + 1
ENDM
ENDM

somemacro1 MACRO arg
mov eax,arg
ENDM

somemacro2 MACRO arg
mov ebx,arg
ENDM

somemacro3 MACRO arg
mov ecx,arg
ENDM

somemacro4 MACRO arg
mov edx,arg
ENDM

.CODE
Start:

WRAPPING_CNT = 0 ; init

AddToListmacro 1, 2
somemacro1 CONST3 ; forward-referenced constants:
somemacro2 CONST4 ; they will be defined after calling
endingmacro ; "AddToListmacro 3, 4"
AddToListmacro 3, 4
somemacro3 CONST1
somemacro4 CONST2
endingmacro

ExpandAllmacro ; call all somemacros via wrappingmacros

END Start

Unfortunately, such system is not working. It successfully defines header of first wrappingmacro ("wrappingmacro0 MACRO") and the compiler accept it:


00000000 .CODE
Start:

= 00000000 WRAPPING_CNT = 0 ; init

AddToListmacro 1, 2
1 ; ...original code here...
1
1 ; in this example, this macro creates no list, only creates CONST1-4;
1 ; CONST3 and 4 would be forward-referenced by somemacro1 and somemacro2
1
1 CONST1 EQU 1
1 CONST2 EQU 2
1
1 ; concatenate header of wrappingmacro
1
1 temp2 CATSTR <wrappingmacro>, %WRAPPING_CNT, < MACRO>
1 wrappingmacro0 MACRO ; defines header of wrappingmacro after expanding this macro
1 somemacro1 CONST3 ; forward-referenced constants:
1 somemacro2 CONST4 ; they will be defined after calling
1 endingmacro ; "AddToListmacro 3, 4"
1 AddToListmacro 3, 4
1 somemacro3 CONST1
1 somemacro4 CONST2
1 endingmacro
1
1 ExpandAllmacro ; call all somemacros via wrappingmacros
1
1 END Start

BUT, as you can see, the endingmacro will not expand to "ENDM" :( Even though I tried different combinations of expansion operators, even "endignmacro TEXTEQU <ENDM>" does not work...

It does work as needed only when I replace "endingmacro" with "ENDM":


AddToListmacro 1, 2
somemacro1 CONST3 ; forward-referenced constants:
somemacro2 CONST4 ; they will be defined after calling
; endingmacro ; "AddToListmacro 3, 4"
ENDM
AddToListmacro 3, 4
somemacro3 CONST1
somemacro4 CONST2
; endingmacro
ENDM

ExpandAllmacro ; call all somemacros via wrappingmacros


00000000 .CODE
Start:

= 00000000 WRAPPING_CNT = 0 ; init

AddToListmacro 1, 2
1 ; ...original code here...
1
1 ; in this example, this macro creates no list, only creates CONST1-4;
1 ; CONST3 and 4 would be forward-referenced by somemacro1 and somemacro2
1
1 CONST1 EQU 1
1 CONST2 EQU 2
1
1 ; concatenate header of wrappingmacro
1
1 temp2 CATSTR <wrappingmacro>, %WRAPPING_CNT, < MACRO>
1 wrappingmacro0 MACRO ; defines header of wrappingmacro after expanding this macro
1 somemacro1 CONST3 ; forward-referenced constants:
1 somemacro2 CONST4 ; they will be defined after calling
1 ; endingmacro ; "AddToListmacro 3, 4"
1 ENDM
1
= 00000001 1 WRAPPING_CNT = WRAPPING_CNT + 1
AddToListmacro 3, 4
1 ; ...original code here...
1
1 ; in this example, this macro creates no list, only creates CONST1-4;
1 ; CONST3 and 4 would be forward-referenced by somemacro1 and somemacro2
1
1 CONST3 EQU 3
1 CONST4 EQU 4
1
1 ; concatenate header of wrappingmacro
1
1 temp2 CATSTR <wrappingmacro>, %WRAPPING_CNT, < MACRO>
1 wrappingmacro1 MACRO ; defines header of wrappingmacro after expanding this macro
1 somemacro3 CONST1
1 somemacro4 CONST2
1 ; endingmacro
1 ENDM



But the goal is not to use any additional macro directives, like this "ENDM".

Are you aware of any way how to force the endingmacro to expand to "ENDM"? Or is it mission: impossible?
Posted on 2004-10-25 07:51:25 by MazeGen
I doubt that the compiler can be forced to expand any macros inside a macro definition :S, because it seems to be stone-dead, there's no room to swing a cat.
Posted on 2004-10-25 11:21:34 by MazeGen
Crazy MACRO
EXITM @CatStr("ENDM")
ENDM

...oh this is just asking for trouble - like flirting with a redhead. :lol:
Posted on 2004-12-04 02:14:12 by bitRAKE
Thanks for your stable interest :), but how did you mean it exactly?
As I see it, the problem lies in macro definition, which is totally static - if you put your Crazy macro in a definition of another macro, it will not be expanded to "ENDM", so the definition will be not closed. :(
Posted on 2004-12-06 14:17:18 by MazeGen
Symbols are not resolved in search of ENDM.

Something as simple as "testend EQU <ENDM>" will not resolve.

teststart MACRO
testend

But you already knew that. :oops:
Posted on 2004-12-06 23:47:52 by bitRAKE
Yea, that's it.

It would be very nice and useful make it working, because we would use MASM as custom multi-pass assembler then!

:evil:
Posted on 2004-12-07 07:58:22 by MazeGen