Hi Randy,

What *universal* prototype of function with variable number of parameters should be? For function like API's wsprintf.
Equivalent to MASM's VARARG.

Regards, GJ
Posted on 2003-05-09 17:26:08 by Green Joe

Hi Randy,

What *universal* prototype of function with variable number of parameters should be? For function like API's wsprintf.
Equivalent to MASM's VARARG.

Regards, GJ


You would use a macro for this purpose.


Here's a simple example I've whipped out for this purpose:



program t;
#include( "stdlib.hhf" )

procedure varparms_p( count:uns32 );
@nodisplay;
@noframe;
@nostackalign;
@cdecl;
begin varparms_p;

push( ebp );
mov( esp, ebp );
mov( count, ecx );
while( ecx > 0 ) do

mov( count[ ecx*4 ], eax );
stdout.put( "Parm #", (type uns32 ecx), "=", (type uns32 eax), nl );
dec( ecx );

endwhile;
mov( ebp, esp );
pop( ebp );
ret();

end varparms_p;

#macro varparms( cnt, parms[] ):_parmCnt;

#for( _parmCnt := @elements( parms )-1 downto 0 )

pushd( @text( parms[ _parmCnt ] ) );

#endfor
varparms_p( cnt );

#endmacro


begin t;


// Manual calls:

pushd( 1 );
pushd( 2 );
pushd( 3 );
varparms_p(3);
add( 16, esp );

pushd( 4 );
pushd( 5 );
varparms_p(2);
add( 12, esp );

// Calls supporting a variable # of arguments:

varparms( 1, 6 );
add( 8, esp );

varparms( 4, 7,8,9,10 );
add( 20, esp );

end t;

Posted on 2003-05-09 23:28:27 by rhyde
Hi Randy,

Following your example I wrote this wrapper for wsprintf function:



static
wsprintfA : procedure(p0:dword;p1:dword);
@cdecl;
external("__imp__wsprintfA");

#macro wsprintf( lpOut, lpFmt, parms[] ):_parmCnt;

?_parmCnt : int32 := @elements( parms ) - 1;
#while(_parmCnt >= 0)
pushd( @text( parms[ _parmCnt ] ) );
?_parmCnt := _parmCnt - 1;
#endwhile

pushd(lpFmt);
pushd(lpOut);

lea(eax,wsprintfA);
call([eax]);
add((@elements( parms )+8) * 4, esp);
#endmacro


I couldn't make for loop work as in your example above. I used while loop instead.
This macro seems to make his job fine, so I want to include it in user32.hhf and upload with Icz tutorial #28 that uses wsprintf. Maybe there is a better way to wrote this wrapper?

Reagards, GJ
Posted on 2003-05-12 16:24:06 by Green Joe

Hi Randy,

Following your example I wrote this wrapper for wsprintf function:



static
wsprintfA : procedure(p0:dword;p1:dword);
@cdecl;
external("__imp__wsprintfA");

#macro wsprintf( lpOut, lpFmt, parms[] ):_parmCnt;

?_parmCnt : int32 := @elements( parms ) - 1;
#while(_parmCnt >= 0)
pushd( @text( parms[ _parmCnt ] ) );
?_parmCnt := _parmCnt - 1;
#endwhile

pushd(lpFmt);
pushd(lpOut);

lea(eax,wsprintfA);
call([eax]);
add((@elements( parms )+8) * 4, esp);
#endmacro


I couldn't make for loop work as in your example above. I used while loop instead.
This macro seems to make his job fine, so I want to include it in user32.hhf and upload with Icz tutorial #28 that uses wsprintf. Maybe there is a better way to wrote this wrapper?

Reagards, GJ


About the only change I would make is to call the indirect pointer directly rather than
first loading it into EAX, e.g.,

call( wsprintfA );

Cheers,
Randy Hyde
Posted on 2003-05-12 23:09:48 by rhyde