Joined: 16 Jun 2003
Location: Kraków, Poland
Tricky stuff in fasmg, part 4: Generated macros
This is the fourth part of a series on advanced trickery that can be done with fasmg. The other installments: part 1, part 2, part 3.
As the samples in the previous part demonstrated, it is very easy to make macro generate another macro, and the text of the new one may contain values created by the outer macro or passed from its arguments (and with copied identifier recognition context):
ddv - o
BASE = 100h
BASE = 200h
offset220h; dd 20h
However it is no longer so easy when we need to algorithmically generate a macro that may contain a variable number of lines. Let's say that we need a "generate" macro that could be called like this:
We can iterate through the arguments of "generate" and construct the text of the lines we need after deconstructing the arguments with MATCH, however after we start the definition of an inner macro, the iteration is no longer going to work. Any ITERATE or END ITERATE encountered when a macro definition is under way would simply become the part of the macro instead of being immediately processed.
A relatively simple solution that comes to mind, is to generate the text of macro that we need to construct in form of data in a VIRTUAL block, then execute it with EVAL:
Another variant could achieve the same effect without VIRTUAL, by building the text variable directly with a string concatenation macro (currently there is no built-in string concatenation in fasmg, so this has to be done with bit shifts):
(temporarily replacing EVAL with DB allows to ensure that the generated text is correct).
But these solutions have some disadvantages. Not only may they be considered wasteful, since they generate a raw text than then needs to be parsed back by the assembler - but the raw text generated in such way can no longer preserve any context for identifiers - this can sometimes be a serious flaw.
The trick that we can use to construct a macro from a variable number of lines that we have prepared as a preprocessed text (which may include some context information) lies in the nested macro calls. Let's look at the following sample:
The call to the final "builder" macro initiates the cascade of nested macro calls until it reaches the deepest one which begins the definition of new macro "test". The one after one the nested macros get closed, each one adding an additional line to the macro, until the topmost one is reached which closes the definition with "end macro". The result is definition of this plain and simple macro:
Before we apply this trick to our problem, we need to realize that we still need EVAL to generate the name of macro parameter, because any parameter is recognized by the preprocessor only when it is a single token. But this EVAL is going to be much shorter and simpler. We are also going to use IRPV to quickly retrieve previously prepared symbolic values into a parameter to generate the line of newly created macro:
The initial ".#" is attached to the line while defining a "builder" macro, to avoid associating any foreign context with the initial dot, because this dot needs to be interpreted in the context of builded "struc" macro. On the other hand, any contexts for the identifiers in the definitions of the default values are preserved correctly this time.
If we define the building macro as "macro builder!", it is possible to use it to generate only a portion of a macro, because the unconditional macro gets expanded even when it is encountered while definition of a new macro is under way. This allows to re-structure the above sample:
In this variant ESC is used to avoid calling the previous unconditional macro when defining the next one - to create the cascade like in the previous example. But it would still work without ESC and in such case each consecutive macro would contain the entire sequence of prepared lines.
Joined: 16 Jun 2003
Location: Kraków, Poland
In the Mach-O macros I created to let fasmg assemble itself as MacOS executable I used this simple set of macros based on the above ideas. They allow to build new macro line-by-line with an easy to use syntax:
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