flat assembler
Message board for the users of flat assembler.
Index
> Macroinstructions > Tricky stuff in fasmg, part 4: Generated macros |
Author |
|
Tomasz Grysztar 10 Oct 2016, 20:57
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): Code: macro origin o macro offset v dd v - o end macro end macro BASE = 100h origin BASE BASE = 200h offset 220h ; dd 20h Code: generate POINT, x dd ?,y dd ?,z dd ? Code: struc POINT xValue:?,yValue:?,zValue:? .x dd xValue .y dd yValue .z dd zValue end struc 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: Code: macro generate name,fields& virtual at 0 db 'struc ',`name,' ' iterate field, fields if % > 1 db ',' end if match label= type= default, field db `label,'Value:',`default end match end iterate db 13,10 iterate field, fields match label= type= default, field db '.',`label,' ',`type,' ',`label,'Value',13,10 end match end iterate db 'end struc' local text load text:$ from 0 eval text end virtual end macro Code: macro append variable,texts& iterate text, texts variable = string (variable) + (text) shl (lengthof (variable) shl 3) end iterate end macro macro generate name,fields& local text text = 'struc ' append text,`name,' ' iterate field, fields if % > 1 append text,',' end if match label= type= default, field append text,`label,'Value:',`default end match end iterate append text,13,10 iterate field, fields match label= type= default, field append text,'.',`label,' ',`type,' ',`label,'Value',13,10 end match end iterate append text,'end struc' eval text end macro 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: Code: macro builder esc macro test end macro macro builder builder db 1 end macro macro builder builder db 2 end macro macro builder builder esc end macro end macro builder Code: macro test db 1 db 2 end macro Code: macro append variable,texts& iterate text, texts variable = string (variable) + (text) shl (lengthof (variable) shl 3) end iterate end macro macro generate name,fields& local declarations,argument,line,rmatchN,builder iterate field, fields match label= type= default, field rmatchN = 'rmatch N,' append rmatchN,`label append rmatchN,'Value' eval rmatchN define argument N:default define line label type N end rmatch if % = 1 declarations equ argument else declarations equ declarations,argument end if end match end iterate match arguments, declarations macro builder struc name arguments end macro end match irpv definition, line macro builder builder .#definition end macro end irpv builder end struc end macro 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: Code: macro append variable,texts& iterate text, texts variable = string (variable) + (text) shl (lengthof (variable) shl 3) end iterate end macro macro generate name,fields& local declarations,argument,rmatchN,builder macro builder! end macro iterate field, fields match label= type= default, field rmatchN = 'rmatch N,' append rmatchN,`label append rmatchN,'Value' eval rmatchN define argument N:default macro builder! esc builder .#label type N end macro end rmatch if % = 1 declarations equ argument else declarations equ declarations,argument end if end match end iterate match arguments, declarations struc name arguments builder end struc end match end macro |
|||
10 Oct 2016, 20:57 |
|
bitRAKE 10 Dec 2018, 02:16
Maybe a not so obvious, but natural extension:
Code: macro builderBuilder name* define name? macro name? declaration& macro name?.definition esc macro declaration end macro end macro macro name?.line? content& macro name?.definition name?.definition content end macro end macro macro name?.block? macro ?! line& match =name?.=block?,line purge ? else macro name?.definition name?.definition line end macro end match end macro end macro macro name?.end? name?.definition esc end macro end macro end macro _________________ ¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup |
|||
10 Dec 2018, 02:16 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.