I recently downloaded one of Hutch's routine (touch) to see what it does. Looking at the asm code, he makes use of the rv macro which I had not played with, so I went to see what the macro did.
rv MACRO args:VARARG
LOCAL cnt
cnt = 0
arg equ <>
FOR var,<args>
arg CATSTR arg,<var> ;; get the proc name as 1st arg
EXITM
ENDM
FOR var,<args>
IF cnt gt 0
arg CATSTR arg,<,reparg(var)> ;; replace quotes and append arg
ENDIF
cnt = cnt + 1
ENDM
invoke arg
EXITM <eax>
ENDM
Ok, so it substitutes quoted strings with the address of that string created in the data section, and runs an invoke.
Other than being more complicated, how is that macro different than-
rvx MACRO args:VARARG
arg equ <>
FOR var,<args>
arg CATSTR arg,<,reparg(var)>
ENDM
arg SUBSTR arg,2 ;; remove comma
invoke arg
EXITM <eax>
ENDM
?
They seem to work the same, what am I missing here?
Jim,
The extra loop is to get the correct number of parameters passed to the macro just in case a call is made wth no arguments. Its been a while since I did that one so I forget the details.
Do you mean for example fn GetTickCount ?
I made the following macros, just to test:
fnx MACRO args:VARARG
arg equ <>
FOR var,<args>
arg CATSTR arg,<,reparg(var)>
ENDM
arg SUBSTR arg,2 ;; remove comma
invoke arg
ENDM
rvx MACRO args:VARARG
arg equ <>
FOR var,<args>
arg CATSTR arg,<,reparg(var)>
ENDM
arg SUBSTR arg,2 ;; remove comma
invoke arg
EXITM <eax>
ENDM
rvx2 MACRO args:VARARG
fn args
EXITM <eax>
ENDM
And tried the following test code-
invoke GetTickCount
PrintDec eax
mov eax,0
fn GetTickCount
PrintDec eax
mov eax,0
fnx GetTickCount
PrintDec eax
mov eax,0
mov ebx,rv(GetTickCount)
PrintDec ebx
mov eax,0
mov ebx,rvx(GetTickCount)
PrintDec ebx
mov eax,0
mov ebx,rvx2(GetTickCount)
PrintDec ebx
fn MessageBox,0,"testing",0,0
fnx MessageBox,0,"testing",0,0
And everything seems to work properly.
If you meant for example
mov ebx,rv()
then both old and new macros failed.
Jim,
I set up a test piece and I now see how you have done it. The original did the first CATSTR operation without a leading comma and the rest with the leading comma where your design runs the leading comma for each CATSTR operation then removes the first one with the SUBSTR operation. Yours is more efficient and does that same task in less macro operations.
LATER STILL:
fn MACRO FuncName:REQ,args:VARARG
arg equ <invoke FuncName> ;; construct invoke and function name
FOR var,<args> ;; loop through all arguments
arg CATSTR arg,<,reparg(var)> ;; replace quotes and append arg
ENDM
arg ;; write the invoke macro
ENDM
; ------------------------------------------------
; Function return value version of the above macro
; ------------------------------------------------
rv MACRO FuncName:REQ,args:VARARG
arg equ <invoke FuncName> ;; construct invoke and function name
FOR var,<args> ;; loop through all arguments
arg CATSTR arg,<,reparg(var)> ;; replace quotes and append arg
ENDM
arg ;; write the invoke macro
EXITM <eax> ;; EAX as the return value
ENDM
I have these two macros tested and reliable and are now in the macros.asm file.
Very nice. :U
Paul
Isn't it though. Don't know why I didn't see that when I was fooling around :U