I get the description of __stdcall as this: "does not generate underscores prefix of function name, preserve case, called function pops the stack, and caller pushes parameters right to left". And the description of __cdecl as: "__cdecl modifier to declare a variable or a function using the C-style naming conventions (case-sensitive, with a leading underscore appended), it affects how the parameters are passed (parameters are pushed right to left, and the caller cleans up the stack)".
I write a program to test how does gcc process __stdcall and __cdecl. The code is:
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
int defaultCall(int param);
int __cdecl cdeclCall(int param);
int __stdcall stdCall(int param);
int __attribute__((stdcall)) attrStdCall(int param);
#ifdef __cplusplus
}
#endif //__cplusplus
int main()
{
int value = 0x55aa;
value = stdCall(value);
value = cdeclCall(value);
value = defaultCall(value);
value = attrStdCall(value);
return value;
}
And I compile this file to generate the ASM code as followed:
_main:
pushl %ebp
movl %esp, %ebp
subl $24, %esp
andl $-16, %esp
movl $0, %eax
addl $15, %eax
addl $15, %eax
shrl $4, %eax
sall $4, %eax
movl %eax, -8(%ebp)
movl -8(%ebp), %eax
call __alloca
call ___main
movl $21930, -4(%ebp)
movl -4(%ebp), %eax
movl %eax, (%esp)
call _stdCall@4
subl $4, %esp ; delete the argument in stack ?
movl %eax, -4(%ebp)
movl -4(%ebp), %eax
movl %eax, (%esp)
call _cdeclCall ; caller doesn't cleans up the stack ?
movl %eax, -4(%ebp)
movl -4(%ebp), %eax
movl %eax, (%esp)
call _defaultCall ; default calling specification is C-Type ?
movl %eax, -4(%ebp)
movl -4(%ebp), %eax
movl %eax, (%esp)
call _attrStdCall@4
subl $4, %esp
movl %eax, -4(%ebp)
movl -4(%ebp), %eax
leave
ret
Please look at the comments in asm code. When calling a __stdcall modified function, gcc generate the code to clean up the arguments in stack. But when calling a __cdecl modified function, gcc doesn't generate the code to clean up the arguments in stack. Is't a bug of gcc for windows ?
BTW, my compiler is MinGW32 GCC 3.4.4.
[attachment deleted by admin]
Look at the assembly code for each function:
_cdeclCall:
movl 4(%esp), %eax
ret
_stdCall@4:
movl 4(%esp), %eax
ret $4
There is no doubt that both conform to the calling conventions so the calling code must conform or it would not work.
You are being confused by a compiler that produces code so good that it's hard to recognize what it's doing because you don't see the familiar constructs. Notice that the code you are calling "cleanup code" is subtracts, not adds as you would normally expect. This means that the compiler noticed that there were 4 calls in a row that all took the same parameters. Rather than wasting lots of time popping and pushing it decided to leave the parameter right there and fuss with the stack pointer to keep each function call correct. A cdecl call requires no fussing because the parameter is still where it was before. The stdcall function uses sub to undo what the "ret $4" did to get the parameter back in the right place.
Besides, most Win32 calls are stdcall. If stdcall didn't work right, MinGW wouldn't be any use for Win32 development. When in doubt, assume that the compiler is correct and you are not.
As always, I'm impressed by the quality of code that MinGW/GCC generates.
Perhaps the code from Pelles will look more familiar:
push ebx
mov ebx,21930
push dword ebx
call _stdCall@4
mov ebx,eax
push dword ebx
call _cdeclCall
pop ecx
mov ebx,eax
push dword ebx
call _defaultCall
pop ecx
mov ebx,eax
@4:
pop ebx
ret