I was reading an old post. So I created a macro to "partially replace" invoke.
xcall MACRO function:REQ, parameters:VARARG

LOCAL psize, paddr, plen
IFNB <parameters>
psize = 0
FOR param, <parameters>
psize = psize + 4
ENDM
sub esp, psize
psize = 0
FOR param, <parameters>
IF @SizeStr(<param>) GT 4
paddr SUBSTR <param>, 1, 5
IFIDNI paddr, <ADDR >
paddr SUBSTR <param>, 6, @SizeStr(<param>) - 5
lea eax, paddr
mov DWORD PTR [esp+psize*4], eax
ELSE
mov DWORD PTR [esp+psize*4], param
ENDIF
ELSE
mov DWORD PTR [esp+psize*4], param
ENDIF
psize = psize + 1
ENDM
ENDIF
call function
ENDM
How To Use It: xcall functionName, parameter1, parameter2, ...

Cons:
    [*]Limitation #1 : Cannot Handle Direct Memory
    Solution #1 : Place the value from memory into a register
    [*]Limitation #2 : Cannot handle BYTE, WORD, QWORD, TBYTE size parameters.
    Solution #2 : None. If I know how to access the protoype of a function or the procedure structure, then this problem will be solved.Pros:
      [*]Supports use of the ADDR macro
      [*]"Faster" compared to the normal pushing of parameters used by invoke
      Sidenote :
        [*]Please limit the use of the ADDR to local variables, use OFFSET if you can. Why? It will execute the lea instruction, which is used to get the address of a variable, so if you use ADDR even if the variable is declared in the data section, you'll be adding 1 instruction more to your program. If I can access the variable declarations on the data, code section plus the locals, this issue will be solved.
        [*]When using ADDR be sure to use another register instead of EAX because ADDR macro uses EAX as a placeholder of the memory address. So if you have a function call like this:
        mov eax, hWnd
        
        xcall myfunction, ADDR mystring, eax
        This will break your app. Though this only happens when using ADDR then the post-parameter/s uses the EAX register, aside from this, there should be no problem/s(except the ones mentioned above on the cons list).

        Have Fun!!! :grin:
Posted on 2002-06-21 00:12:08 by stryker
/me is waiting until bitRAKE sees this thread and comes with a 5 lines shorter and 10 times faster version...





:grin:
Posted on 2002-06-21 01:10:27 by bazik
I can remove some error checkings if you want to and no ADDR support...I maximized the features to my extent. :grin: stripped-down version(no ADDR support)
xcall MACRO function:REQ, parameters:VARARG

LOCAL psize
IFNB <parameters>
psize = 0
FOR param, <parameters>
psize = psize + 4
ENDM
sub esp, psize
psize = 0
FOR param, <parameters>
mov DWORD PTR [esp+psize*4], param
psize = psize + 1
ENDM
ENDIF
call function
ENDM
Is this what your looking for? :grin:
Posted on 2002-06-21 01:16:39 by stryker
Nice!

What about that:



xcall MACRO function:REQ, parameters:VARARG
LOCAL psize
IFNB <parameters>
psize = 0
FOR param, <parameters>
sub esp, 4
mov DWORD PTR [esp+psize*4], param
psize = psize + 1
ENDM
ENDIF
call function
ENDM



Would this work? :)
Posted on 2002-06-21 01:40:47 by bazik
Just tested it... nice, it works :) Damn, I am good! :stupid:
Posted on 2002-06-21 01:42:47 by bazik
really, hmm why did my app crashed? :confused: If it did worked, I believe there would be a lot of sub esp, 4 for each parameter -> bloat.
[size=9].386

.model flat, stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib

xcall MACRO function:REQ, parameters:VARARG
LOCAL psize
IFNB <parameters>
psize = 0
FOR param, <parameters>
sub esp, 4
mov DWORD PTR [esp+psize*4], param
psize = psize + 1
ENDM
ENDIF
call function
ENDM


.code
start:
xcall MessageBox, 0, 0, 0, 0
invoke ExitProcess,NULL
end start[/size]
Dunno why mine crashed??? and yours not???


I know, you probably used only 1 parameter. :)


push 0
push 0
push 0
xcall MessageBox, 0
Posted on 2002-06-21 01:45:41 by stryker
Maybe because I didn't save the source before clicking "compile" :)

Ok, it crashes too. Can you explain why? In fact it does the same as your app, with the difference that it subtracts for each param and not all at ones?!
Posted on 2002-06-21 02:00:13 by bazik
I just modified your macro to make it work
xcall MACRO function:REQ, parameters:VARARG

IFNB <parameters>
FOR param, <parameters>
sub esp, 4
mov DWORD PTR [esp], param
ENDM
ENDIF
call function
ENDM
but the problem is the redundant sub esp, 4 which will add bloat to your app.

As for why the above macro didn't work is because of garbage
Param 4 - garbage, current esp, TOS

Param 3 - garbage
Param 2 - garbage
Param 1 - only the lower part was constantly changed
during the execution of the MOV instruction
Also if we are going to use the macro I just modified we need to reverse the parameters, Param1 should be on the TOS. I'll search for ParReverse macro tomorrow, it seems to me I've lost it in my MACRO collections. Anyway, as far as I can remember ParReverse will be slower because it has to parse the parameters in reverse order.

BTW, this one really has a lot of weird outputs(Param 2 & 3 are interchanged - I've seen a pattern), I'll study it tomorrow. Don't use these macros folks except for the original one on the first thread. These are still on the testing phase.

I'm sleepy!!! :o I think I need some shut eye :alright:
Posted on 2002-06-21 02:16:57 by stryker
The following from my Masm.inc file allows immediate strings in the call ie:

invok MessageBox, "My Caption", "Mytext", 0, 0, 0

@str macro _str:vararg

local @@1
if @InStr(1, <_str>, <!">)
.data
@@1 db _str
.code
exitm <offset @@1>
else
exitm <_str>
endif
endm

invok macro _func:req, _args:vararg
ifb <_args>
invoke _func
else
$invok equ <>
irp $v, <_args>
$invok catstr $invok, <,>, @str(<$v>)
endm
invoke _func $invok
endif
endm

Posted on 2002-06-21 05:27:45 by gfalen
Wow! I'm really impressed with your macro skills! Good job gfalen :alright:

edit: Oops..it looks like the strings aren't zero terminated. Solved it by changing "@@1 db _str" to "@@1 db _str,0h"

/Delight
Posted on 2002-06-21 05:33:30 by Delight
Right you are! I copied and pasted from my file. In it @str() calls yet another function to declare the string. In trying to move this functionality to the @str() macro i forgot the trailing ", 0".

Here's the updated version:

@str macro _str:vararg

local @@1
if @InStr(1, <_str>, <!">)
.data
@@1 db _str, 0
.code
exitm <o @@1>
else
exitm <_str>
endif
endm




P.S. Here's the link to the thread with my file(s)

http://www.asmcommunity.net/board/index.php?topic=6073&highlight=static
Posted on 2002-06-21 06:02:18 by gfalen
stryker, very nice work. Might want to take a look at this thread to get more advanced stuff happening between caller and callee. You could easily add stack alignment, too.
Posted on 2002-06-21 07:09:33 by bitRAKE
This is the version from the macros in MASM32.


; --------------------------------------------------
; macro for making STDCALL procedure and API calls.
; --------------------------------------------------

Scall MACRO name:REQ,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12, \
p13,p14,p15,p16,p17,p18,p19,p20,p21,p22

;; ---------------------------------------
;; loop through arguments backwards, push
;; NON blank ones and call the function.
;; ---------------------------------------

FOR arg,<p22,p21,p20,p19,p18,p17,p16,p15,p14,p13,\
p12,p11,p10,p9,p8,p7,p6,p5,p4,p3,p2,p1>
IFNB <arg> ;; If not blank
push arg ;; push parameter
ENDIF
ENDM

call name ;; call the procedure

ENDM

It works much like the old TASM CALL syntax.

Regards,

hutch@movsd.com
Posted on 2002-06-21 07:16:57 by hutch--
What about using VARARG there, hutch? :)
Posted on 2002-06-21 07:19:38 by bazik
gfalen,

I just infused my macro and your @str and it works perfectly


@str macro _str:vararg
local @@1
if @InStr(1, <_str>, <!"> )
.data
@@1 db _str, 0
.code
exitm <offset @@1>
else
exitm <_str>
endif
endm

xcall MACRO function:REQ, parameters:VARARG
LOCAL psize, paddr, plen
IFNB <parameters>
psize = 0
FOR param, <parameters>
psize = psize + 4
ENDM
sub esp, psize
psize = 0
FOR param, <parameters>
IF @SizeStr(<param>) GT 4
paddr SUBSTR <param>, 1, 5
IFIDNI paddr, <ADDR >
paddr SUBSTR <param>, 6, @SizeStr(<param>) - 5
lea eax, paddr
mov DWORD PTR [esp+psize*4], eax
ELSE
mov DWORD PTR [esp+psize*4], @str(<param>)
ENDIF
ELSE
mov DWORD PTR [esp+psize*4], @str(<param>)
ENDIF
psize = psize + 1
ENDM
ENDIF
call function
ENDM

xcall MessageBox, NULL, "Hello Cruel World", "Testing xcall macro", MB_YESNO
Nice work, thanks for sharing.

bitRAKE,

I'll check out that profiling macro. Thanks!!!

bAZiK && hutch--,

If I'll find ParReverse I'll post a modified version of your macros.
Posted on 2002-06-21 09:54:44 by stryker
For bitRAKE: :(

I'm not sure if I did it correctly.
[size=9]@str macro _str:vararg

local @@1
if @InStr(1, <_str>, <!"> )
.data
@@1 db _str, 0
.code
exitm <offset @@1>
else
exitm <_str>
endif
endm

xcall MACRO function:REQ, parameters:VARARG
LOCAL psize, paddr, plen
IFNB <parameters>
psize = 0
FOR param, <parameters>
psize = psize + 4
ENDM

[color=#3366FF];Is this right? or should this be 16/32? or did I get the
;whole thing wrong. I'm such a newb :)

align 4[/color]

sub esp, psize
psize = 0
FOR param, <parameters>
IF @SizeStr(<param>) GT 4
paddr SUBSTR <param>, 1, 5
IFIDNI paddr, <ADDR >
paddr SUBSTR <param>, 6, @SizeStr(<param>) - 5
lea eax, paddr
mov DWORD PTR [esp+psize*4], eax
ELSE
mov DWORD PTR [esp+psize*4], @str(<param>)
ENDIF
ELSE
mov DWORD PTR [esp+psize*4], @str(<param>)
ENDIF
psize = psize + 1
ENDM
ENDIF
call function
ENDM[/size]
For bAZiK:
[size=9]preverse MACRO ParList:REQ

LOCAL Value, arg
Value TEXTEQU <>
% FOR arg, <ParList>
Value CATSTR <arg>, <,>, Value
ENDM
Value SUBSTR Value, 1, @SizeStr( %Value ) - 1
Value CATSTR <!<>, Value, <!>>
EXITM Value
ENDM

bcall MACRO function:REQ, parameters:VARARG
IFNB <parameters>
% FOR param, preverse(<parameters>)
sub esp, 4
mov DWORD PTR [esp], param
ENDM
ENDIF
call function
ENDM[/size]
for Hutch--:

Use this together with the preverse macro.
[size=9]scall MACRO function:REQ, parameters:VARARG

IFNB <parameters>
% FOR param, preverse(<parameters>)
push param
ENDM
ENDIF
call function
ENDM[/size]
:)
Posted on 2002-06-21 11:46:55 by stryker
stryker, I meant to align the address of stack for the proceedure being called:
; Assuming stack is aligned at time of macro execution and

; add 4 bytes for the return address pushed onto the stack:
psize = MyALIGN((psize+4), __STACK_ALIGN__)
psize = psize - 4 ; return address adjustment
MyALIGN macro val:REQ, sz:REQ

EXITM %(((val+sz-1)/sz)*sz)
ENDM
sorry, I'm at work and fixed a little bug - most likely are others... :grin:
hopefully, you can understand what I mean. When the called PROC is reached the stack is aligned, and then the called PROC grabs chunks of the stack that are also aligned - therefor, the stack is always aligned! :)
Posted on 2002-06-21 13:05:34 by bitRAKE
To tell you the truth I really have no idea what you're talking about! I apologize, I'm still reading some intel docs.
[size=9]

FOR param, <parameters>
IF @SizeStr(<param>) GT 4
paddr SUBSTR <param>, 1, 5
IFIDNI paddr, <ADDR >
paddr SUBSTR <param>, 6, @SizeStr(<param>) - 5
lea eax, paddr
mov DWORD PTR [esp-psize*4], eax
ELSE
mov DWORD PTR [esp-psize*4], @str(<param>)
ENDIF
ELSE
mov DWORD PTR [esp+psize*4], @str(<param>)
ENDIF
psize = @align((psize+4), 4)
psize = psize - 4
ENDM[/size]
I have a feeling this isn't right. This is the best I could come up. I think I need to read some more docs about stack alignment :)

@align is the same macro you just posted. I'll be back and try some more. :grin:
Posted on 2002-06-21 13:50:35 by stryker
[b]        psize = @align((psize+4), 32)

psize = psize - 4[/b]

sub esp, psize
psize = 0
FOR param, <parameters>
IF @SizeStr(<param> ) GT 4
paddr SUBSTR <param>, 1, 5
IFIDNI paddr, <ADDR >
paddr SUBSTR <param>, 6, @SizeStr(<param> ) - 5
lea eax, paddr
mov DWORD PTR [esp+psize*4], eax
ELSE
mov DWORD PTR [esp+psize*4], @str(<param> )
ENDIF
ELSE
mov DWORD PTR [esp+psize*4], @str(<param> )
ENDIF
psize = psize + 1
ENDM
:eek: :grin:
Posted on 2002-06-21 14:09:12 by bitRAKE
I did that before but I don't know what happened because it crashed??? :) I'll check it back again
Posted on 2002-06-21 14:11:44 by stryker