Re: calling convention stdcalll and cdecl call
* Igor Tandetnik:
"George" <George@discussions.microsoft.com> wrote in message
news:2CC27965-06FB-4E77-B4A9-D73B1D8D1942@microsoft.com
Both stdcall and cdecl calling convention could support variable input
parameters? Is that correct?
No. Variadic functions must use cdecl calling convention.
(I think stdcall is using RET N and cdecl is using ESP - N, so both
are capable to handle variable number of input parameter, like
printf?)
I have no idea what "RET N" or "ESP - N" is supposed to mean.
With stdcall, the function is responsible for removing its parameters
from the stack. To do this, it must know how many parameters there are,
and thus cannot take variable number of parameters.
I'm sorry, that's incorrect (counter-example below).
It's only a tool and library limitation.
With cdecl, the caller is responsible for removing parameters after the
called function returns. The caller of course knows how many parameters
it has just pushed on the stack, so there's no problem removing them.
I now see that I remembered incorrectly about pushing order in my reply earlier
in this thread. Happily, as I recall I wrote a disclaimer "as I recall". ;-)
<code file="x.cpp">
#include <iostream>
#include <stdarg.h>
extern "C" void __stdcall display( int x )
{
std::cout << x << std::endl;
}
void _stdcall knurre( int );
void _stdcall knurre( int, int );
void _stdcall knurre( int, int, int );
void _stdcall knurre( int, int, int, int );
int main()
{
knurre( 1, 101 );
knurre( 2, 201, 202 );
knurre( 3, 301, 302, 303 );
}
</code>
<code file="hackity.asm">
.386P
.model FLAT
_TEXT SEGMENT
EXTRN _display@4:NEAR
display EQU _display@4
PUBLIC ?knurre@@YGXH@Z ; (int)
PUBLIC ?knurre@@YGXHH@Z ; (int, int)
PUBLIC ?knurre@@YGXHHH@Z ; (int, int, int)
PUBLIC ?knurre@@YGXHHHH@Z ; (int, int, int, int)
?knurre@@YGXH@Z:
?knurre@@YGXHH@Z:
?knurre@@YGXHHH@Z:
?knurre@@YGXHHHH@Z:
_knurre PROC NEAR
push ebp
mov ebp, esp
mov ecx, [esp+8]
and ecx, ecx
jz finito
displayLoop:
mov eax, [esp+4*ecx+8]
push ecx
push eax
call _display@4
pop ecx
dec ecx
jnz displayLoop
finito:
mov eax, 1234
mov esp, ebp
pop ebp
pop ebx ; Return address
pop ecx
shl ecx, 2
add esp, ecx
jmp ebx
_knurre ENDP
_TEXT ENDS
END
</code>
<output>
101
202
201
303
302
301
</output>
As you can see at the assembly language level (apologies for novice style code,
it's been a long time!) there's no problem. The main problem with the above was
to get Visual C++ to accept the stdcall vararg routine, not changing the calling
convention to cdecl, which it does when it sees "...". For that, had to declare
the function with all actually used signatures -- so it's just a tool problem,
and for that matter, also library problem, that there's no support.
Cheers, & hth.,
- Alf
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?