News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Macro Expansion

Started by WillofIrony, November 02, 2007, 08:32:57 PM

Previous topic - Next topic

WillofIrony

I have noticed that many macros are used as operands eg:
        push    GetLoWord(in_lParam)
        push    in_wParam
        push    in_hWnd
        call    addr_handler
In this case the macro is defined thus:
GetLoWord macro data32
        mov             eax, data32
        and             eax, 0000ffffh
        exitm   <eax>
endm
I am reliably assured that the first snippet will expand thus:
        mov     eax, data32
        and     eax, 0000ffffh
        push    eax
        push    in_wParam
        push    in_hWnd
        call    addr_handler

From this I deduce that when used as an operand (rather than an instruction which is the 'normal' form of macro use) a macro's body is expanded BEFORE the instruction mnemonic for which it is the 'operand' and the argument for exitm is placed where the macro is placed in the text. Am I correct in this? Is this always the case? I failed to find this fact in Chapter 9 of the MASM programmer's guide (v6.1). Does anybody know of where I might find the documentation on Macro expansion?

Thank you in anticipation,
Michael

BogdanOntanu

It is implementation dependent but basically yes that is what actually happens.

I can not guess what was in the mind of MASM creators but i can tell you what I do in Solar Assembler in this case.

The encoding of push <macro_name> is postponed because a macro is detected and an recursive parser takes over and parses/encodes the macro body. When that parser returns the push encoding will continue and be finished up.

However at this time a "lot" of code was already generated by the macro body that could also contain another macro ... ;).

Ambition is a lame excuse for the ones not brave enough to be lazy.
http://www.oby.ro

Rockoon

This makes sense because the assembler doesnt know which opcode to use until it knows the types of each parameter, so it cannot have emitted an opcode until the macro is expanded and the types are known.

Remember that there isnt a 1:1 correspendence with Intel syntax and opcodes. 'mov' definately maps to more than 1 opcode, as do most instructions.
When C++ compilers can be coerced to emit rcl and rcr, I *might* consider using one.

jj2007

Quote from: BogdanOntanu on November 02, 2007, 09:19:44 PM
The encoding of push <macro_name> is postponed because a macro is detected and an recursive parser takes over and parses/encodes the macro body. When that parser returns the push encoding will continue and be finished up.

However at this time a "lot" of code was already generated by the macro body that could also contain another macro ... ;).

Just for fun: This is a valid Basic code, with Rep$ being a "replace macro". The principle is the same: Tell the parser to look for the innermost element, expand it, look for the second-innermost element, etc...

My$=@Rep$("|",CrLf$,@Rep$("#EN",ElName$(1),@Rep$("#NE",STR$(nr_c&),@Rep$("#NI",STR$(ColVal&-EvCt&),t$))))+"."

Mark Jones

Quote from: jj2007 on November 03, 2007, 09:07:55 AM
My$=@Rep$("|",CrLf$,@Rep$("#EN",ElName$(1),@Rep$("#NE",STR$(nr_c&),@Rep$("#NI",STR$(ColVal&-EvCt&),t$))))+"."

All I can say to that is... YUCK! :lol
"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

WillofIrony

Quote from: BogdanOntanu on November 02, 2007, 09:19:44 PM

The encoding of push <macro_name> is postponed because a macro is detected and an recursive parser takes over and parses/encodes the macro body. When that parser returns the push encoding will continue and be finished up.

Thanks for that comprehensive answer. It also answers how the FNMacros work. It is none intuitive, however, and could easily fool the neophyte who might not realise that the order of his instructions would be changed. I can see it as a very powerful featrure. It is a shame that somebody has not documented it.

Thanks again to all those responding.

Michael