flat assembler
Message board for the users of flat assembler.

Index > Programming Language Design > [fasmg] Inline macros. Why not?

Goto page 1, 2, 3  Next

Do you like the idea of inline macros?
Yes, I like
80%
 80%  [ 8 ]
No, I don't
10%
 10%  [ 1 ]
Don't care
10%
 10%  [ 1 ]
Total Votes : 10

Author
Thread Post new topic Reply to topic
VEG



Joined: 06 Feb 2013
Posts: 80
VEG 30 May 2017, 15:14
I've read somewhere here that Tomasz Grysztar doesn't like the idea of inline macros. But why? Maybe because it can add some ambiguity or it seems not easy to implement? Or it has some drawbacks?

Maybe you will like this idea of syntax which will fit FASMG well IMHO. And it will not be required to rewrite much things. The main idea is to use <? ... ?> construction in place where it is possible to put a variable name. Like:
Code:
db <? ... ?>
varname = <? ... ?>
mov eax, <? ... ?>
invoke demo, 1, 2, <? ... ?>, 4    
Between <? and ?> we can put just one instruction which will be translated by preprocessor to a call of a "struc" macro before current instruction, but with an anonymous label. Like this:
Code:
invoke demo, 1, 2, <? makeinlinestr "teststr" ?>, 4    
It has to be translated to this:
Code:
anonlabel makeinlinestr "teststr"
invoke demo, 1, 2, anonlabel, 4    

All instructions from every <? ?> have to be added before the current instruction in the order from left to right. It is possible to enclose one <? ?> into another. Like this:
Code:
invoke demo, 1, 2, <? makeinlinestr <? i32tohex 12345 ?> ?>, 4    
It has to be translated to this:
Code:
anonlabel1 i32tohex 12345
anonlabel2 makeinlinestr anonlabel1
invoke demo, 1, 2, anonlabel2, 4    


These makeinlinestr, i32tohex and similar macros (which will be usable inline) can be just struc macros which emit nothing at this place and just set a value to a variable. If it emits something, it will be emitted exactly before an actual instruction.

It will allow even things like:
Code:
errcode = 123 ; some calculations
err "error code: ", <? i32tostr errcode ?>, ', it is not good'    
So, it will be a really universal thing, as I can see. And it will be pretty safe because of using a really rare combination of operators <? ... ?>.

What do you think?


Last edited by VEG on 01 Jun 2017, 13:47; edited 3 times in total
Post 30 May 2017, 15:14
View user's profile Send private message Visit poster's website Reply with quote
zhak



Joined: 12 Apr 2005
Posts: 501
Location: Belarus
zhak 30 May 2017, 15:37
allowing a macro to return a result of some inner calculations could be a nice feature
Post 30 May 2017, 15:37
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8359
Location: Kraków, Poland
Tomasz Grysztar 30 May 2017, 15:40
VEG wrote:
I've read somewhere here that Tomasz Grysztar doesn't like the idea of inline macros. But why? Maybe because it can add some ambiguity or it seems not easy to implement? Or it has some drawbacks?
It is not that I don't like them (although I do think that it's an attempt to introduce some HLL familiarity into a language that does not necessarily have to be structured this way), it is just that my design of fasm was based on some assumptions about the syntax of assembly languages, including one that this is a line-based language where the individual commands reside in separate lines. These assumptions are embedded deeply in the design of fasm and fasmg parsers and symbol structures and it is not possible to implement anything resembling inline macros without altering the basic building blocks of these engines.

Of course it is possible to emulate inline macros by pre-processing all lines with "macro ?". I don't know whether this is viable - it would be slow, of course, bo so are many other macro-based solutions in fasmg. And the syntax you proposed would be quite easy to detect and pre-process with MATCH in the "macro ?" handler.
Post 30 May 2017, 15:40
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8359
Location: Kraków, Poland
Tomasz Grysztar 30 May 2017, 15:41
zhak wrote:
allowing a macro to return a result of some inner calculations could be a nice feature
Allowing to return a value is not very useful when the only place where the macro can be recognized and processed is as the initial symbol of a line.
Post 30 May 2017, 15:41
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8359
Location: Kraków, Poland
Tomasz Grysztar 30 May 2017, 16:45
Just because I simply cannot resist writing some interesting macros for fasmg, I implemented the pre-processor using "macro ?" that I mentioned above. It uses the syntax with "<?" and "?>" markers that you suggested:
Code:
macro preprocess_and_execute line&
        local buffer,preprocessed,inline,cursor
        define buffer line :
        define preprocessed :
        while 1
                match a <=? b, preprocessed buffer
                        redefine preprocessed a
                        redefine buffer b

                        match x =?> y, buffer
                                redefine cursor x
                                redefine buffer y
                        else
                                err 'missing ?>'
                                break
                        end match
                        redefine inline :
                        while 1
                                match <=? d, cursor
                                        match i, inline
                                                redefine inline i <?
                                        end match
                                        redefine cursor d ?>
                                else match c <=? d, cursor
                                        match i, inline
                                                redefine inline i c <?
                                        end match
                                        redefine cursor d ?>
                                else match i, inline cursor
                                        redefine inline i
                                        break
                                end match
                                match =?> y, buffer
                                        redefine buffer y
                                else match x =?> y, buffer
                                        match c, cursor
                                                redefine cursor c x
                                        end match
                                        redefine buffer y
                                else
                                        err 'missing ?>'
                                        break
                                end match
                        end while
                        match :command, inline
                                preprocess_and_execute command
                                match text, preprocessed $result
                                        redefine preprocessed text
                                end match
                        end match
                else match a, preprocessed buffer
                        redefine preprocessed a
                        break
                end match
        end while
        match :command:, preprocessed
                command
        end match
end macro

macro ? line&
        preprocess_and_execute line
end macro    
An inline macro should define "$result" variable holding the returned value (it can be symbolic).

A simple example how it works:
Code:
macro low value
        $result = value and 0FFFFh
end macro

macro high value
        $result = value shr 16
end macro

        include '8086.inc'

        address = 12345678h

        mov     ax,<? low address ?>
        mov     dx,<? high address ?>    
And nesting is also allowed.
Post 30 May 2017, 16:45
View user's profile Send private message Visit poster's website Reply with quote
VEG



Joined: 06 Feb 2013
Posts: 80
VEG 30 May 2017, 17:17
Tomasz Grysztar, you're crazy (in a good sense) =)

I've tested how it affects time of assembly. In my situation it is +33% of time (4 seconds instead of 3). It seems that I can live with it. Thank you very much.

It is really a must have feature for me. IMHO, 1 line = 1 macroinstruction is good for instructions which actually emit some bytes to output. But if some instruction just makes some work with variables, like conversion from int to string or just merging some strings into one variable, and doesn't emit anything, and this data will be used just as an argument of the next instruction which will emit some code, it looks not good and actually makes the code more cluttered.

Also I think I'll add some kind of prefix for these inline macro, just to avoid possible intersection with general macros. I'll add the "imacro" macros which will define such kind of inline macros with names like "imacro.usermacroname", and I'll add to the <? ?> handler automatic addition of the "imacro.", so it still will be possible to write <? usermacroname ?>, and it will not prevent a programmer from creation and using a normal (not inline) macro with the same name if it will be required.
Post 30 May 2017, 17:17
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8359
Location: Kraków, Poland
Tomasz Grysztar 30 May 2017, 18:20
VEG wrote:
Tomasz Grysztar, you're crazy (in a good sense) =)
People keep telling me that. Wink
Post 30 May 2017, 18:20
View user's profile Send private message Visit poster's website Reply with quote
VEG



Joined: 06 Feb 2013
Posts: 80
VEG 31 May 2017, 18:05
It seems that I completely misunderstand FASMG macros Sad I thought that it will be the easiest one, but it doesn't work. It has to work line a normal macro, but with adding of the _imacro postfix for an inline macro name. (I've decided to use postfix because in this case it will take into account namespaces).
Code:
macro imacro line&
        match iname args, line
                esc macro iname#_imacro args
        else match iname, line
                esc macro iname#_imacro
        end match
end macro

macro end?.imacro
        esc end macro
end macro

imacro low value
        $result = value and 0FFFFh
end imacro    
Result:
Code:
flat assembler  version g.ht7g2
imacro.asm [94]:
        imacro low value
macro ? [1] macro imacro_preprocess [63] macro imacro [1]:
        match iname args, line
Error: missing end directive.    
Inline macros is not a built-in feature, so all error messages have this preprocessing macro in the stack.

The preprocess macro which uses inline macros with _imacro postfix:
Code:
macro imacro_preprocess line&
        local buffer,preprocessed,inline,cursor
        define buffer line :
        define preprocessed :
        while 1
                match a <=? b, preprocessed buffer
                        redefine preprocessed a
                        redefine buffer b

                        match x =?> y, buffer
                                redefine cursor x
                                redefine buffer y
                        ; dd <? ?> ; catches this error
                        ; dd <? sub 2, <? ?> ?> ; doesn't catch it
                        ; else match =?> y, buffer
                                ; err 'empty <? ?>'
                                ; break
                        else
                                err 'missing ?>'
                                break
                        end match
                        redefine inline :
                        while 1
                                match <=? d, cursor
                                        match i, inline
                                                redefine inline i <?
                                        end match
                                        redefine cursor d ?>
                                else match c <=? d, cursor
                                        match i, inline
                                                redefine inline i c <?
                                        end match
                                        redefine cursor d ?>
                                else match i, inline cursor
                                        redefine inline i
                                        break
                                end match
                                match =?> y, buffer
                                        redefine buffer y
                                else match x =?> y, buffer
                                        match c, cursor
                                                redefine cursor c x
                                        end match
                                        redefine buffer y
                                else
                                        err 'missing ?>'
                                        break
                                end match
                        end while
                        match :command, inline
                                match inst args, command
                                        imacro_preprocess inst#_imacro args
                                else match inst, command
                                        imacro_preprocess inst#_imacro
                                end match
                                match text, preprocessed $result
                                        redefine preprocessed text
                                end match
                        end match
                else match a, preprocessed buffer
                        redefine preprocessed a
                        break
                end match
        end while
        match :command:, preprocessed
                command
        end match
end macro

macro ? line&
        imacro_preprocess line
end macro    


Last edited by VEG on 31 May 2017, 18:09; edited 2 times in total
Post 31 May 2017, 18:05
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8359
Location: Kraków, Poland
Tomasz Grysztar 31 May 2017, 18:08
When you start the nested macro, END MATCH becomes part of the inner macro and the original block remains unclosed.

You may find this article helpful: https://board.flatassembler.net/topic.php?t=19496
Post 31 May 2017, 18:08
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8359
Location: Kraków, Poland
Tomasz Grysztar 31 May 2017, 18:16
I modified your sample to show how you can get it working:
Code:
macro imacro line&
        local begin
        match iname args, line
                macro begin
                        esc macro iname#_imacro args
                end macro
        else match iname, line
                macro begin
                        esc macro iname#_imacro
                end macro
        end match
        begin
end macro 

macro end?.imacro!
        esc end macro 
end macro 

imacro low value 
        $result = value and 0FFFFh 
end imacro    
First, it uses the "begin" proxy macro to start the new macro only after closing the MATCH block. Second, the "end?.imacro" needs to be unconditional (hence the "!" modifier) to be unrolled while a macro definition is in process (otherwise it is consumed into a macro body).
Post 31 May 2017, 18:16
View user's profile Send private message Visit poster's website Reply with quote
VEG



Joined: 06 Feb 2013
Posts: 80
VEG 31 May 2017, 18:34
Oh, nice trick with the "begin" local macro. But it seems that it has some conflicts with the preprocessing macro:
Code:
macro imacro_preprocess line&
        local buffer,preprocessed,inline,cursor
        define buffer line :
        define preprocessed :
        while 1
                match a <=? b, preprocessed buffer
                        redefine preprocessed a
                        redefine buffer b

                        match x =?> y, buffer
                                redefine cursor x
                                redefine buffer y
                        ; dd <? ?> ; catches this error
                        ; dd <? sub 2, <? ?> ?> ; doesn't catch it 
                        ; else match =?> y, buffer
                                ; err 'empty <? ?>'
                                ; break
                        else
                                err 'missing ?>'
                                break
                        end match
                        redefine inline :
                        while 1
                                match <=? d, cursor
                                        match i, inline
                                                redefine inline i <?
                                        end match
                                        redefine cursor d ?>
                                else match c <=? d, cursor
                                        match i, inline
                                                redefine inline i c <?
                                        end match
                                        redefine cursor d ?>
                                else match i, inline cursor
                                        redefine inline i
                                        break
                                end match
                                match =?> y, buffer
                                        redefine buffer y
                                else match x =?> y, buffer
                                        match c, cursor
                                                redefine cursor c x
                                        end match
                                        redefine buffer y
                                else
                                        err 'missing ?>'
                                        break
                                end match
                        end while
                        match :command, inline
                                match inst args, command
                                        imacro_preprocess inst#_imacro args
                                else match inst, command
                                        imacro_preprocess inst#_imacro
                                end match
                                match text, preprocessed $result
                                        redefine preprocessed text
                                end match
                        end match
                else match a, preprocessed buffer
                        redefine preprocessed a
                        break
                end match
        end while
        match :command:, preprocessed
                command
        end match
end macro

macro ? line&
        imacro_preprocess line
end macro

macro imacro line&
        local begin
        match iname args, line
                macro begin
                        esc macro iname#_imacro args
                end macro
        else match iname, line
                macro begin
                        esc macro iname#_imacro
                end macro
        end match
        begin
end macro

macro end?.imacro!
        esc end macro
end macro

imacro low value
        $result = value and 0FFFFh
end imacro    
Result:
Code:
flat assembler  version g.ht7g2
imacro.asm [102]:
        imacro low value
macro ? [1] macro imacro_preprocess [64]:
        match :command:, preprocessed
Error: missing end directive.    
It seems that it starts a new macro and the end of preprocessing macro becomes a part of this inner macro =(
Post 31 May 2017, 18:34
View user's profile Send private message Visit poster's website Reply with quote
VEG



Joined: 06 Feb 2013
Posts: 80
VEG 31 May 2017, 18:37
I've replaced this:
Code:
        match :command:, preprocessed
                command
        end match
end macro    
to this (using your trick):
Code:
        local execute
        match :command:, preprocessed
                macro execute
                        command
                end macro
        end match
        execute
end macro    
And it seems that it works.
Post 31 May 2017, 18:37
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8359
Location: Kraków, Poland
Tomasz Grysztar 31 May 2017, 18:47
You may need to make all things unconditional otherwise the "macro ?" jumps in in wrong places:
Code:
macro imacro! line&
        match iname args, line 
                macro begin_imacro!
                        esc macro iname#_imacro args 
                end macro 
        else match iname, line 
                macro begin_imacro!
                        esc macro iname#_imacro 
                end macro 
        end match 
        begin_imacro
end macro 

macro end?.imacro! 
        esc end macro
        purge begin_imacro
end macro    
I remade the sample without use of LOCAL, because I just noticed a problem with LOCAL in current version of fasmg. I think it should have been defined as unconditional in a manner similar to ESC.
Post 31 May 2017, 18:47
View user's profile Send private message Visit poster's website Reply with quote
VEG



Joined: 06 Feb 2013
Posts: 80
VEG 31 May 2017, 19:26
But the "macro ?" is supposed to not affect any code without <? ?>. Is this fix ok for such purpose?

I've just read why unconditional macros could be required (and it is understandable). But it seems that the FASMG Manual says nothing about unconditional ESC (and LOCAL). Or you're talking about stuff from this topic?
Post 31 May 2017, 19:26
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8359
Location: Kraków, Poland
Tomasz Grysztar 31 May 2017, 19:34
VEG wrote:
But the "macro ?" is supposed to not affect any code without <? ?>. Is this fix ok for such purpose?
It should be OK, but it is better to skip unnecessary processing of "macro ?" where possible.

VEG wrote:
I've just read why unconditional macros could be required (and it is understandable). But it seems that the FASMG Manual says nothing about unconditional ESC (and LOCAL). Or you're talking about stuff from this topic?
Yes, the manual currently does not define a complete "catalog" of unconditional directives other that control directives (these are unambiguously defined as unconditional in section 11). The details of what other instructions are unconditional are still being worked out, as shown on the example of LOCAL. I may update the documentation with a precise information in the future.
Post 31 May 2017, 19:34
View user's profile Send private message Visit poster's website Reply with quote
VEG



Joined: 06 Feb 2013
Posts: 80
VEG 01 Jun 2017, 06:00
A critical bug:
Code:
address = 12345678h
dw <? low address ?>,<? high address ?>    
It outputs 0x1234 twice. I think that it is because this macro uses one result variable for all results, so previous results are overwritten to the latest one.

I'm trying to resolve it like this:
Code:
macro imacro_preprocess line&

        local buffer,preprocessed,inline,cursor,resultn
        resultn = 0

        define buffer line :
        define preprocessed :
        while 1
                match a <=? b, preprocessed buffer
                        redefine preprocessed a
                        redefine buffer b

                        match x =?> y, buffer
                                redefine cursor x
                                redefine buffer y
                        else
                                err 'missing ?>'
                                break
                        end match

                        redefine inline :
                        while 1
                                match <=? d, cursor
                                        match i, inline
                                                redefine inline i <?
                                        end match
                                        redefine cursor d ?>
                                else match c <=? d, cursor
                                        match i, inline
                                                redefine inline i c <?
                                        end match
                                        redefine cursor d ?>
                                else match i, inline cursor
                                        redefine inline i
                                        break
                                end match
                                match =?> y, buffer
                                        redefine buffer y
                                else match x =?> y, buffer
                                        match c, cursor
                                                redefine cursor c x
                                        end match
                                        redefine buffer y
                                else
                                        err 'missing ?>'
                                        break
                                end match
                        end while

                        local result#resultn

                        match :command args, inline
                                imacro_preprocess command#_imacro result#resultn, args
                        else match :command, inline
                                imacro_preprocess command#_imacro result#resultn
                        else
                                err 'should not be here'
                        end match

                        match text, preprocessed result#resultn
                                redefine preprocessed text
                        end match

                        resultn = resultn + 1

                else match a, preprocessed buffer
                        redefine preprocessed a
                        break
                end match
        end while

        local execute
        match :command:, preprocessed
                macro execute
                        command
                end macro
        end match
        execute

end macro

macro ? line&
        imacro_preprocess line
end macro

macro imacro line&
        local begin
        match iname args, line
                macro begin
                        esc macro iname#_imacro result, args
                end macro
        else match iname, line
                macro begin
                        esc macro iname#_imacro result
                end macro
        end match
        begin
end macro

macro end?.imacro!
        esc end macro
end macro

imacro low value
        result = value and 0FFFFh
end imacro

imacro high value
        result = value shr 16
end imacro

address = 12345678h
dw <? low address ?>,<? high address ?>
address = 11223344h
dw <? low address ?>,<? high address ?>    
But it doesn't work because local result#resultn always generates "resultresultn", not "result0" and etc. How to attach a number from a variable to another variable name?

I've changed the code a bit. Now the result variable isn't a global variable, it is a local variable which is passed as the first argument for an imacro, and the imacro sets a value to this variable. Also I'm using just "result" as a name of the result variable, like it is in good old Pascal/Delphi Smile

An idea. Maybe it will be very convenient to allow another variant of label which will generate a new local variable every time when this instruction is executed. Like when "newlocal temp" will be used inside a loop, this "temp" variable will be new every iteration of this loop. It will make such code much simpler. It will be possible to use just "local result", and every iteration this "result" will be a new local variable.


Last edited by VEG on 01 Jun 2017, 06:38; edited 3 times in total
Post 01 Jun 2017, 06:00
View user's profile Send private message Visit poster's website Reply with quote
VEG



Joined: 06 Feb 2013
Posts: 80
VEG 01 Jun 2017, 06:07
I've used such trick:
Code:
                        repeat 1, n:resultn
                                local result#n
                                result reequ result#n
                        end repeat    
and now I'm using just "result" in every place where "result#resultn" was used. It seems that "result" contains right names like "result0", but the code still outputs the same value twice.

The whole code:
Code:
macro imacro_preprocess line&

        local buffer,preprocessed,inline,cursor,result,resultn
        resultn = 0

        define buffer line :
        define preprocessed :
        while 1
                match a <=? b, preprocessed buffer
                        redefine preprocessed a
                        redefine buffer b

                        match x =?> y, buffer
                                redefine cursor x
                                redefine buffer y
                        else
                                err 'missing ?>'
                                break
                        end match

                        redefine inline :
                        while 1
                                match <=? d, cursor
                                        match i, inline
                                                redefine inline i <?
                                        end match
                                        redefine cursor d ?>
                                else match c <=? d, cursor
                                        match i, inline
                                                redefine inline i c <?
                                        end match
                                        redefine cursor d ?>
                                else match i, inline cursor
                                        redefine inline i
                                        break
                                end match
                                match =?> y, buffer
                                        redefine buffer y
                                else match x =?> y, buffer
                                        match c, cursor
                                                redefine cursor c x
                                        end match
                                        redefine buffer y
                                else
                                        err 'missing ?>'
                                        break
                                end match
                        end while

                        repeat 1, n:resultn
                                local result#n
                                result reequ result#n
                        end repeat

                        match :command args, inline
                                imacro_preprocess command#_imacro result, args
                        else match :command, inline
                                imacro_preprocess command#_imacro result
                        end match

                        match text, preprocessed result
                                redefine preprocessed text
                        end match

                        resultn = resultn + 1

                else match a, preprocessed buffer
                        redefine preprocessed a
                        break
                end match
        end while

        local execute
        match :command:, preprocessed
                macro execute
                        command
                end macro
        end match
        execute

end macro

macro ? line&
        imacro_preprocess line
end macro

macro imacro line&
        local begin
        match iname args, line
                macro begin
                        esc macro iname#_imacro result, args
                end macro
        else match iname, line
                macro begin
                        esc macro iname#_imacro result
                end macro
        end match
        begin
end macro

macro end?.imacro!
        esc end macro
end macro

imacro low value
        result = value and 0FFFFh
end imacro

imacro high value
        result = value shr 16
end imacro

address = 12345678h
dw <? low address ?>,<? high address ?>
address = 11223344h
dw <? low address ?>,<? high address ?>    
Post 01 Jun 2017, 06:07
View user's profile Send private message Visit poster's website Reply with quote
VEG



Joined: 06 Feb 2013
Posts: 80
VEG 01 Jun 2017, 06:26
Ok, I've fixed it. I moved the whole block which uses the "result" variable into the "repeat" block, and now I'm using it like result#n, and it works.

So, working version without the bug:
Code:
macro imacro_preprocess line&

        local buffer,preprocessed,inline,cursor,resultn
        resultn = 0

        define buffer line :
        define preprocessed :
        while 1
                match a <=? b, preprocessed buffer
                        redefine preprocessed a
                        redefine buffer b

                        match x =?> y, buffer
                                redefine cursor x
                                redefine buffer y
                        else
                                err 'missing ?>'
                                break
                        end match

                        redefine inline :
                        while 1
                                match <=? d, cursor
                                        match i, inline
                                                redefine inline i <?
                                        end match
                                        redefine cursor d ?>
                                else match c <=? d, cursor
                                        match i, inline
                                                redefine inline i c <?
                                        end match
                                        redefine cursor d ?>
                                else match i, inline cursor
                                        redefine inline i
                                        break
                                end match
                                match =?> y, buffer
                                        redefine buffer y
                                else match x =?> y, buffer
                                        match c, cursor
                                                redefine cursor c x
                                        end match
                                        redefine buffer y
                                else
                                        err 'missing ?>'
                                        break
                                end match
                        end while

                        repeat 1, n:resultn
                                local result#n
                                match :command args, inline
                                        imacro_preprocess command#_imacro result#n, args
                                else match :command, inline
                                        imacro_preprocess command#_imacro result#n
                                end match
                                ; if ~ defined result#n
                                        ; err 'result is undefined'
                                ; end if
                                match text, preprocessed result#n
                                        redefine preprocessed text
                                end match
                        end repeat
                        resultn = resultn + 1

                else match a, preprocessed buffer
                        redefine preprocessed a
                        break
                end match
        end while

        local execute
        match :command:, preprocessed
                macro execute
                        command
                end macro
        end match
        execute

end macro

macro ? line&
        imacro_preprocess line
end macro

macro imacro line&
        local begin
        match iname args, line
                macro begin
                        esc macro iname#_imacro result, args
                end macro
        else match iname, line
                macro begin
                        esc macro iname#_imacro result
                end macro
        end match
        begin
end macro

macro end?.imacro!
        esc end macro
end macro

imacro low value
        result = value and 0FFFFh
end imacro

imacro high value
        result = value shr 16
end imacro

address = 12345678h
dw <? low address ?>,<? high address ?>
address = 11223344h
dw <? low address ?>,<? high address ?>    
But how can I assign an alias for a name from a "repeat" block for further using without inclusion of the whole block into the repeat?

UPD. Now I understand why an alias will not work. It's just because this code will remember the name of an alias:
Code:
                                match text, preprocessed result
                                        redefine preprocessed text
                                end match    


Last edited by VEG on 01 Jun 2017, 06:44; edited 2 times in total
Post 01 Jun 2017, 06:26
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8359
Location: Kraków, Poland
Tomasz Grysztar 01 Jun 2017, 06:41
VEG wrote:
A critical bug:
Code:
address = 12345678h
dw <? low address ?>,<? high address ?>    
It outputs 0x1234 twice. I think that it is because this macro uses one result variable for all results, so previous results are overwritten to the latest one.
You're right, I made the macro that originally relied on $result being symbolic. In sample I used "=" because it seemed to work (though I still noted that it can be symbolic) but now you found the problems with it.

So the only good way to use that original macro is in fact to define $result symbolically:
Code:
imacro low value
        local x
        x = value and 0FFFFh
        $result equ x
end imacro

imacro high value
        local x
        x = value shr 16
        $result equ x
end imacro    
Note that I designed it this way because I wanted the ability for inner macro to return any text which would replace the <? ... ?> block in the original line:
Code:
imacro var number
        if number = 0
                $result equ edx
        else
                local offset
                offset = number*4
                $result equ dword [ebp+offset]
        end if
end imacro

        inc     <? var 0 ?>
        inc     <? var 1 ?>    
Post 01 Jun 2017, 06:41
View user's profile Send private message Visit poster's website Reply with quote
VEG



Joined: 06 Feb 2013
Posts: 80
VEG 01 Jun 2017, 07:21
Tomasz Grysztar, oh, nice idea! I haven't thought about this use case. It seems that my variant also works with symbolic variables.

Thank you so much. It was really one of features I was dreaming for. I'll write a bunch of useful inline macros and publish them.
Post 01 Jun 2017, 07:21
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:  
Goto page 1, 2, 3  Next

< 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.