I was wondering what are the differences between macros
and procedures
in MASM ?
Is there a difference with what the program will do or how the assembler will assemble my code, if I call a macro
instead of a procedure
that do the exact same thing ?
If no, I might want to understand why do macros
exist ?
Thanks.
A macro is just text replacement. So any time you "call" a macro, that call will be replaced by the full contents of the macro at compile-time. When you call a procedure, there's typically only one instance of that procedure, so you'll branch to a different place in the program.
Consider the following example:
.586
.model flat, stdcall
option casemap :none
.code
; Multiply the argument by 3/2
Mul3_2 MACRO reg
lea reg,[reg + reg*2]
shr reg,1
ENDM
; Multiply the argument by 3/2 and return in eax
Mul3_2Proc PROC arg:DWORD
mov eax,[arg]
lea eax,[eax + eax*2]
shr eax,1
ret
Mul3_2Proc ENDP
main PROC
Mul3_2 eax
Mul3_2 ebx
invoke Mul3_2Proc,eax ; Equivalent to push eax / call Mul3_2Proc
invoke Mul3_2Proc,ebx
main ENDP
END main
If we let MASM's preprocessor expand our macro we get this:
.586
.model flat, stdcall
option casemap :none
.code
; Multiply the argument by 3/2 and return in eax
Mul3_2Proc PROC arg:DWORD
mov eax,[arg]
lea eax,[eax + eax*2]
shr eax,1
ret
Mul3_2Proc ENDP
main PROC
lea eax,[eax + eax*2]
shr eax,1
lea ebx,[ebx + ebx*2]
shr ebx,1
invoke Mul3_2Proc,eax ; Equivalent to push eax / call Mul3_2Proc
invoke Mul3_2Proc,ebx
main ENDP
END main
As you can see, at the two places where we used the Mul3_2
macro, the contents of that macro has been inserted, with reg
replaced by whatever we passed as the argument to the macro. The macro itself no longer exists in our code, because it has served its purpose.
On the other hand, the two occurrences where we invoked the Mul3_2Proc
procedure remain unchanged. At runtime there will be a jump (call
) from each of those places to Mul3_2Proc
, which in turn will ret
urn back to the call site when it is done.