When a function is called, the parameter is always pushed to the stack first, and then transferred to the called function through the call command. After the call is completed, the stack is cleared. there are two problems: (1) which parameter first enters the stack (2) who will clean the stack. these two problems are called the "Calling Conventions" problem.
Here we will only discuss the _ stdcall and _ cdecl call conventions. The former is a common call Convention for Windows API functions, and the latter is the C call convention.
_ Stcall: the parameters are pushed to the stack from right to left, and the called function clears the stack.
_ Cdecl: the parameters are pushed to the stack in the order from right to left, and the call function cleans the stack.
To prevent function name conflicts or to overload (c ++ Program), the compiler usually modifies the User-Defined Function Name.
This may be too abstract. Let's take a look at the specific examples (usually the code can best illustrate the problem and clarify the problem ).
Let's look at a simple piece of code:
Code
Void swap (int * x, int * y)
{
Int temp;
Temp = * x;
* X = * y;
* Y = temp;
}
It is very simple, that is, to achieve two numbers exchange, people who have learned C language should be very familiar with this code.
Add a test code:
Code
Int main (int argc, char * argv [])
{
Int a = 4, B = 5;
Swap (& a, & B );
Printf ("a = % d, B = % d \ n", a, B );
Return 0;
}
The following tests are based on the VC ++ 6.0.
(1) The swap function is not modified (in the simplest case)
Let's take a look at their corresponding assembly code:
// Main calls the swap assembly code
Swap (& a, & B );
00401096 8D 45 F8 lea eax, [ebp-8]
00401099 50 push eax
0040109A 8D 4D FC lea ecx, [ebp-4]
00401_d 51 push ecx
0040366e E8 62 FF call @ ILT + 0 (swap) (00401005)
004010A3 83 C4 08 add esp, 8
// Swap assembly code
Void swap (int * x, int * y)
{
00401020 55 push ebp
00401021 8B EC mov ebp, esp
00401023 83 EC 44 sub esp, 44 h
00401026 53 push ebx
00401027 56 push esi
00401028 57 push edi
00401029 8D 7D BC lea edi, [ebp-44h]
0040102C B9 11 00 00 00 mov ecx, 11 h
00401031 B8 CC mov eax, 0 CCCCCCCCh
00401036 F3 AB rep stos dword ptr [edi]
Int temp;
Temp = * x;
00401038 8B 45 08 mov eax, dword ptr [ebp + 8]
0040103B 8B 08 mov ecx, dword ptr [eax]
0040103D 89 4D FC mov dword ptr [ebp-4], ecx
* X = * y;
00401040 8B 55 08 mov edx, dword ptr [ebp + 8]
00401043 8B 45 0C mov eax, dword ptr [ebp + 0Ch]
00401046 8B 08 mov ecx, dword ptr [eax]
00401048 89 0A mov dword ptr [edx], ecx
* Y = temp;
0040104A 8B 55 0C mov edx, dword ptr [ebp + 0Ch]
0040104D 8B 45 FC mov eax, dword ptr [ebp-4]
00401050 89 02 mov dword ptr [edx], eax
}
00401052 5F pop edi
00401053 5E pop esi
00401054 5B pop ebx
00401055 8B E5 mov esp, ebp
00401057 5D pop ebp
00401058 C3 ret
@ ILT + 0 (? Swap @ YAXPAH0 @ Z ):
00401005 E9 16 00 00 00 jmp swap (00401020)
Swap is changed to:? By the compiler :? Swap @ YAXPAH0 @ Z, which is a c ++ conversion method.
(2) _ stdcall
Swap (& a, & B );
004010E6 8D 45 F8 lea eax, [ebp-8]
004010E9 50 push eax
004010EA 8D 4D FC lea ecx, [ebp-4]
004010ED 51 push ecx
004010EE E8 12 FF call @ ILT + 0 (swap) (00401005)
Void _ stdcall swap (int * x, int * y)
{
00401030 55 push ebp
00401031 8B EC mov ebp, esp
00401033 83 EC 44 sub esp, 44 h
00401036 53 push ebx
00401037 56 push esi
00401038 57 push edi
00401039 8D 7D BC lea edi, [ebp-44h]
0040103C B9 11 00 00 00 mov ecx, 11 h
00401041 B8 CC mov eax, 0 CCCCCCCCh
00401046 F3 AB rep stos dword ptr [edi]
Int temp;
Temp = * x;
00401048 8B 45 08 mov eax, dword ptr [ebp + 8]
0040104B 8B 08 mov ecx, dword ptr [eax]
0040104D 89 4D FC mov dword ptr [ebp-4], ecx
* X = * y;
00401050 8B 55 08 mov edx, dword ptr [ebp + 8]
00401053 8B 45 0C mov eax, dword ptr [ebp + 0Ch]
00401056 8B 08 mov ecx, dword ptr [eax]
00401058 89 0A mov dword ptr [edx], ecx
* Y = temp;
0040105A 8B 55 0C mov edx, dword ptr [ebp + 0Ch]
0040105D 8B 45 FC mov eax, dword ptr [ebp-4]
00401060 89 02 mov dword ptr [edx], eax
}
00401062 5F pop edi
00401063 5E pop esi
00401064 5B pop ebx
00401065 8B E5 mov esp, ebp
00401067 5D pop ebp
00401068 C2 08 00 ret 8
@ ILT + 0 (? Swap @ YGXPAH0 @ Z ):
00401005 E9 16 00 00 00 jmp swap (00401020)
(3) _ cdecl
Void _ cdecl swap (int * x, int * y)
This is the same as the first case, that is, the default mode of vc ++.
(4) extern "C" _ cdecl
Void extern "C" _ cdecl swap (int * x, int * y)
Swap (& a, & B );
00401096 8D 45 F8 lea eax, [ebp-8]
00401099 50 push eax
0040109A 8D 4D FC lea ecx, [ebp-4]
00401_d 51 push ecx
0040366e E8 67 FF call @ ILT + 5 (_ swap) (0040100a)
004010A3 83 C4 08 add esp, 8
@ ILT + 5 (_ swap ):
0040100A E9 11 00 00 00 jmp swap (00401020)
The swap is changed to _ swap by the compiler, that is, an underscore (C language conversion method) is added, and the rest are the same as the third case.
(5) extern "C" _ stdcall
Void extern "C" _ stdcall swap (int * x, int * y)
Swap (& a, & B );
00401096 8D 45 F8 lea eax, [ebp-8]
00401099 50 push eax
0040109A 8D 4D FC lea ecx, [ebp-4]
00401_d 51 push ecx
0040366e E8 62 FF call @ ILT + 0 (_ swap @ 8) (00401005)
Swap is changed to _ swap @ 8, that is, an underline is added, followed by the number of bytes occupied by the parameter in the stack (C language conversion mode), and the rest are the same as the second case.