#include "stdafx.h"
#pragma inline_depth(0);
#pragma inline_recursion(off);
int test1(const int a, const int b, const int c, const int d, const int e)
{
int result = (((a*b) + c) * d) - e;
return result;
}
int __cdecl test2(const int a, const int b, const int c, const int d, const int e)
{
int result = (((a*b) + c) * d) - e;
return result;
}
int __stdcall test3(const int a, const int b, const int c, const int d, const int e)
{
int result = (((a*b) + c) * d) - e;
return result;
}
int __fastcall test4(const int a, const int b, const int c, const int d, const int e)
{
int result = (((a*b) + c) * d) - e;
return result;
}
__declspec(dllexport) int test5(const int a, const int b, const int c, const int d, const int e)
{
int result = (((a*b) + c) * d) - e;
return result;
}
class test6
{
public:
test6() {};
~test6() {};
int exec_test(const const int a, int b, const int c, const int d, const int e)
{
int result = (((a*b) + c) * d) - e;
return result;
}
int __fastcall exec_test2(const const int a, int b, const int c, const int d, const int e)
{
int result = (((a*b) + c) * d) - e;
return result;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
int a;
int b;
int c;
int d;
int e;
test6 ctest6;
scanf("%d",a);
scanf("%d",b);
scanf("%d",c);
scanf("%d",d);
scanf("%d",e);
int r1,r2,r3,r4,r5,r6, r7;
r1 = test1(a,b,c,d,e);
r2 = test2(a,b,c,d,e);
r3 = test3(a,b,c,d,e);
r4 = test4(a,b,c,d,e);
r5 = test5(a,b,c,d,e);
r6 = ctest6.exec_test(a,b,c,d,e);
r7 = ctest6.exec_test2(a,b,c,d,e);
printf("%d\n",r1);
printf("%d\n",r2);
printf("%d\n",r3);
printf("%d\n",r4);
printf("%d\n",r5);
printf("%d\n",r6);
printf("%d\n",r7);
char ch;
scanf("%c",ch);
return 0;
}
Release Assembly Output:
; 80 :
; 81 : int r1,r2,r3,r4,r5,r6, r7;
; 82 :
; 83 : r1 = test1(a,b,c,d,e);
mov edx, DWORD PTR _e$[ebp]
mov eax, DWORD PTR _d$[ebp]
push edx
push eax
push ebx
push edi
mov eax, esi
call ?test1@@YAHHHHHH@Z ; test1
; 84 : r2 = test2(a,b,c,d,e);
; 85 : r3 = test3(a,b,c,d,e);
; 86 : r4 = test4(a,b,c,d,e);
; 87 : r5 = test5(a,b,c,d,e);
; 88 : r6 = ctest6.exec_test(a,b,c,d,e);
; 89 : r7 = ctest6.exec_test2(a,b,c,d,e);
; 90 :
; 91 : printf("%d\n",r1);
push eax
push OFFSET ??_C@_03PMGGPEJJ@?$CFd?6?$AA@
call DWORD PTR __imp__printf
mov ecx, DWORD PTR _e$[ebp]
mov edx, DWORD PTR _d$[ebp]
add esp, 64 ; 00000040H
push ecx
push edx
push ebx
push edi
mov eax, esi
call ?test2@@YAHHHHHH@Z ; test2
; 92 : printf("%d\n",r2);
push eax
push OFFSET ??_C@_03PMGGPEJJ@?$CFd?6?$AA@
call DWORD PTR __imp__printf
mov eax, DWORD PTR _e$[ebp]
mov ecx, DWORD PTR _d$[ebp]
add esp, 24 ; 00000018H
push eax
push ecx
push ebx
push edi
mov eax, esi
call ?test3@@YGHHHHHH@Z ; test3
; 93 : printf("%d\n",r3);
push eax
push OFFSET ??_C@_03PMGGPEJJ@?$CFd?6?$AA@
call DWORD PTR __imp__printf
mov edx, DWORD PTR _e$[ebp]
mov eax, DWORD PTR _d$[ebp]
add esp, 8
push edx
push eax
push ebx
push edi
mov eax, esi
call ?test4@@YIHHHHHH@Z ; test4
; 94 : printf("%d\n",r4);
push eax
push OFFSET ??_C@_03PMGGPEJJ@?$CFd?6?$AA@
call DWORD PTR __imp__printf
mov ecx, DWORD PTR _e$[ebp]
mov edx, DWORD PTR _d$[ebp]
push ecx
push edx
push ebx
push edi
push esi
call ?test5@@YAHHHHHH@Z ; test5
; 95 : printf("%d\n",r5);
push eax
push OFFSET ??_C@_03PMGGPEJJ@?$CFd?6?$AA@
call DWORD PTR __imp__printf
mov eax, DWORD PTR _e$[ebp]
mov ecx, DWORD PTR _d$[ebp]
add esp, 36 ; 00000024H
push eax
push ecx
push ebx
push edi
mov eax, esi
call ?exec_test@test6@@QAEHHHHHH@Z ; test6::exec_test
; 96 : printf("%d\n",r6);
push eax
push OFFSET ??_C@_03PMGGPEJJ@?$CFd?6?$AA@
call DWORD PTR __imp__printf
mov edx, DWORD PTR _e$[ebp]
mov eax, DWORD PTR _d$[ebp]
add esp, 8
push edx
push eax
push ebx
push edi
mov eax, esi
call ?exec_test2@test6@@QAIHHHHHH@Z ; test6::exec_test2
...
As you can see __cdecl and __stdcall generate same code, all params pass right to left so evaulation is left to right (last push will be the first to be popped).
In this test case the compiler wasn't be able to optimize __fastcall and it was ignored (__fastcall works like inline keyword).
By the way __fastcall will try to pass 3 arguments into registers if he can't do it, it will try with 2 otherwise all into the stack.
But if you generate a dll, every function that will be marked as __declspec(dllexport) will use __stdcall = __cdecl, __fastcall will be ignored.
The only difference beetwen Embarcadero C++ Builder and Microsoft Visual C++ is that embarcadero for __fastcall 3 arguments onto the registers or nothing and everythig goes into the stack. But this will create problem only if you create a library and try a statical linking but it's impossible by default they use two different object format, and also gcc use another object format.
So using a DLL in another language will usually never cause a problem.
I think that the MSDN documentation is not updated for calling convections.
I used Visual C++ 2010.











