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
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
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;
Hi Randy,
Following your example I wrote this wrapper for wsprintf function:
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
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
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