// This article is transferred from the Internet
Several Concepts of function calling: _ stdcall, _ cdecl ....
1. _ stdcall is the default calling method of the PASCAL program. It is usually used in Win32 API. The function uses the stack pressure method from right to left and clears the stack when it exits. After compiling a function, VC adds an underline prefix to the function name, and adds "@" and the number of bytes of the parameter to the function name.
2. c call conventions (which are described by the _ cdecl keyword) are pushed to the stack in sequence from right to left. The caller pushes the parameters to the stack. The memory stack of the transfer parameter is maintained by the caller (because of this, the function that implements the variable parameter can only use this call Convention ). In addition, the function name modification conventions are also different.
_ Cdecl is the default call Method for C and C ++ programs. Every function that calls it contains the code to clear the stack. Therefore, the size of the executable file generated is larger than that of the call to the _ stdcall function. The function uses the stack pressure mode from right to left. After compiling a function, VC adds an underline prefix to the function name. Is the default MFC call convention.
3. The _ fastcall call convention is "person" as its name. Its main feature is fast because it transmits parameters through registers (in fact, it uses ECx and EDX to transmit the first two DWORD or smaller parameters, and the remaining parameters are still transmitted from the right to the left pressure stack, the called function clears the memory stack of the transfer parameter before returning). In terms of the function name modification conventions, it is different from the previous two.
_ Fastcall functions use registers to pass parameters. After compiling a function, VC adds the "@" prefix to the function name, and adds "@" and the number of parameters after the function name.
4. thiscall is only applied to "C ++" member functions. This pointer is stored in the Cx register and the parameter is pressed from right to left. Thiscall is not a keyword and cannot be specified by programmers.
5. Naked call uses 1-4 call timing. If necessary, the compiler will generate code to save the ESI, EDI, EBX, and EBP registers when entering the function, when you exit the function, the code is generated to restore the content of these registers. Naked call does not generate such code. The naked call is not a type modifier, so it must be used together with _ declspec.
The keywords _ cdecl and _ fastcall can be directly added to the function to be output, or selected from the setting... \ C/C ++ \ code generation item in the compilation environment. When the keywords added before the output function are different from those selected in the compiling environment, the keywords directly added before the output function are valid. Their corresponding command line parameters are/GZ,/GD, And/GR. The default status is/GD, Which is _ cdecl.
To fully imitate Pascal's call convention, you must first use the _ stdcall call Convention. As for the function name Modification Convention, you can use other methods to imitate it. Another thing worth mentioning is winapi macro, windows. h supports this macro. It can translate the function into an appropriate call convention. In Win32, it is defined as _ stdcall. You can use the winapi macro to create your own APIs.
2) Name modification conventions
1. decoration name)
The "C" or "C ++" functions are identified by modifier internally (Compilation and link. Modifier is a string generated by the compiler when compiling a function definition or prototype. In some cases, modifying the name of a function is necessary, for example, specifying the output "C ++" overload function, constructor, and destructor in the module definition file, for example, call the "C" or "C ++" function in the assembly code.
Modifier names are jointly determined by function names, class names, call conventions, return types, parameters, and so on.
2. The name Modification Convention varies with the call convention and the compilation type (C or C ++. The function name modification conventions vary with the compilation type and call conventions.
Rules for modifying function names during a and c Compilation:
The _ stdcall call Convention adds an underline prefix before the output function name, followed by the "@" symbol and the number of bytes of the parameter. The format is _ functionname @ number.
The _ cdecl call Convention only adds an underline prefix before the output function name in the format of _ functionname.
_ Fastcall: add the "@" symbol before the output function name, followed by the "@" symbol and the number of bytes of the parameter. The format is @ functionname @ number.
They do not change the case sensitivity of the output function name. This is different from Pascal's call conventions. Pascal's output function names are not modified and all are capitalized.
B. Conventions for function name modification during C ++ Compilation:
_ Stdcall call conventions:
1. Take "?" Start of the function name, followed by the function name;
2. The function name starts with the parameter table marked by mailto: â @ YG, followed by the parameter table;
3. The parameter table is represented in code:
X -- void,
D -- char,
E -- unsigned char,
F -- short,
H -- int,
I -- unsigned int,
J -- long,
K -- unsigned long,
M -- float,
N -- double,
_ N -- bool,
....
Pa -- indicates the pointer. The code behind the pointer indicates the pointer type. If a pointer of the same type appears consecutively, it is replaced by "0". A "0" indicates a repetition;
4. the first item of the parameter table is the type of the return value of the function, followed by the Data Type of the parameter. the pointer ID is prior to the Data Type indicated by the parameter;
5. The end of the name is marked by mailto: â @ Z after the parameter table. If the function has no parameter, it ends with the "Z" mark.
The format is mailto: â? Functionname @ YG ***** @ Z "or mailto: â? Functionname @ YG * xz ", for example
Int test1 (char * var1, unsigned long) mailto: ----- â? Test1 @ yghpadk @ Z"
Void Test2 () mailto: ----- â? Test2 @ ygxxz"
_ Cdecl:
The rules are the same as the _ stdcall call Convention above, except that the start identifier of the parameter table is changed from mailto: @ YG to mailto: @ ya ".
_ Fastcall:
The rules are the same as the _ stdcall call Convention above, except that the start identifier of the parameter table is changed from mailto: @ YG to mailto: @ Yi ".
The "_ cedcl" Declaration for the function can only be called by C/C ++.
CB uses four modifiers for output function declaration.
// _ Cdecl
The default value of CB. It will add _ before the output function name and keep this function name unchanged. parameters are passed to the stack in sequence from right to left, it can also be written as _ cdecl and cdecl.
// _ Fastcall
The parameters of the function modified by her will be processed by registers with the intention of adding @ before the function name, and the parameters will be pushed to the stack in the order from left to right;
// _ Pascal
It indicates that the function name uses the naming convention in Pascal format. In this case, all function names are capitalized. The parameters are pressed from left to right;
// _ Stdcall
In Turbo C, the parameter is pushed to the stack in the order from right to left using the modifier cdecl or unspecified function, that is, a function (a, B, c) is called) after that, a is the most advanced stack, followed by B and C.
There are several Calling methods for function calling, which can be C and Pascal. In C and C ++, C-type calls are default unless otherwise stated. There is a difference between the two. Here we use an example to describe:
1. _ cdecl: Default call methods for C and C ++
Example:
Void input (Int & M, Int & N);/* equivalent to void _ cdecl input (Int & M, Int & N );*/
The following is the compilation code:
00401068 Lea eax, [ebp-8]; get [ebp-8] address (ebp-8), save to eax
0040106b push eax; then press the stack
00401_c Lea ECx, [ebp-4]; take [ebp-4] address (ebp-4), save to ECx
0040366f push ECx; then press the stack
00401070 call @ ILT + 5 (input) (0040100a); then call the Input Function
00401075 add ESP, 8; restore Stack
From the process of calling the input function can be seen: Before calling this function, first press the stack ebp-8, and then press the stack ebp-4, then call the function input, finally input function call after the end, use ESP + 8 to restore the stack. It can be seen that in C language calls, the default function modifier _ cdecl is used for parameter pressure stack and stack restoration by the main function call.
What is the address ebp-8 and ebp-4?
Select debug windows under VC view, and then select registers to display the register variable value. Then, select memory under debug windows, enter the value of the ebp-8 and the value of the ebp-4 (or directly enter the ebp-8 and-4) to see what the two addresses actually store, which is actually the address of the Variable N (ebp-8 ), M address (ebp-4), it can be seen that in the main call function for real parameters of the Pressure stack and the order is from right to left. In addition, because the real parameter is a reference to the corresponding variable, it also proves that the reference actually passes the address of the variable (similar to a pointer ).
Conclusion: In C or C ++ language calls, the default function modifier _ cdecl is used. The primary function calls the function to perform parameter pressure stack and resume stack, the pressure stack sequence of real parameters is from right to left, and the stack is restored by the main function. Because the main call function manages the stack, variable parameters can be implemented. In addition, the naming modification method is to add an underscore (_) before the function (_).
2. winapi (actually Pascal, callback, _ stdcall)
Example:
Void winapi input (Int & M, Int & N );
Let's take a look at the calling assembly code:
00401068 Lea eax, [ebp-8]
0040106b push eax
00401_c Lea ECx, [ebp-4]
0040366f push ECx
00401070 call @ ILT + 5 (input) (0040100a)
From the process of calling the input function can be seen: Before calling this function, first press the stack ebp-8, then press the stack ebp-4, then call the function input, after calling the function input, no corresponding stack recovery work (for other function calls, so I am not listed)
Next we will list the assembly code of the input function itself: (the actual function is not big, but the Assembly example is a little bigger. You can check the intermediate code before and after it is irrelevant to this example)
39: void winapi input (Int & M, Int & N)
40 :{
00401110 push EBP
00401111 mov EBP, ESP
00401113 sub ESP, 48 h
00401116 push EBX
00401117 push ESI
00401118 push EDI
00401119 Lea EDI, [ebp-48h]
0040111c mov ECx, 12 h
00401121 mov eax, 0 cccccccch
00401126 rep STOs dword ptr [EDI]
41: int S, I;
42:
43: While (1)
00401128 mov eax, 1
0040112d test eax, eax
0040112f je input + 0c1h (004011d1)
44 :{
45: printf ("\ nplease input the first number M :");
00401135 push offset string "\ nplease input the first number M"... (0020.b8)
0040113a call printf (00401530)
0040113f add ESP, 4
46: scanf ("% d", & M );
00401142 mov ECx, dword ptr [EBP + 8]
00401145 push ECx
00401146 push offset string "% d" (000000b4)
0040114b call scanf (004015f0)
00401150 add ESP, 8
47:
48: If (M <1) continue;
00401153 mov edX, dword ptr [EBP + 8]
00401156 cmp dword ptr [edX], 1
00401159 jge input + 4dh (0040115d)
0040115b JMP input + 18 h (00401128)
49: printf ("\ nplease input the first number N :");
0040115d push offset string "\ nplease input the first number N"... (0000008c)
00401162 call printf (00401530)
00401167 add ESP, 4
50: scanf ("% d", & N );
004020.a mov eax, dword ptr [EBP + 0ch]
0040116d push eax
0040e e push offset string "% d" (000000b4)
00401173 call scanf (004015f0)
00401178 add ESP, 8
51:
52: If (n <1) continue;
0040117b mov ECx, dword ptr [EBP + 0ch]
0040117e cmp dword ptr [ECx], 1
00401181 jge input + 75 h (00401185)
00401183 JMP input + 18 h (00401128)
53:
54: for (I = 1, s = 0; I <= N; I ++)
00401185 mov dword ptr [ebp-8], 1
0040118c mov dword ptr [ebp-4], 0
00401193 JMP input + 8eh (0040119e)
00401195 mov edX, dword ptr [ebp-8]
00401198 add edX, 1
0040119b mov dword ptr [ebp-8], EDX
0040119e mov eax, dword ptr [EBP + 0ch]
004011a1 mov ECx, dword ptr [ebp-8]
004011a4 CMP ECx, dword ptr [eax]
004011a6 JG input + 0a3h (004011b3)
55: S = S + I;
004011a8 mov edX, dword ptr [ebp-4]
004011ab add edX, dword ptr [ebp-8]
004011ae mov dword ptr [ebp-4], EDX
004011b1 JMP input + 85 H (00401195)
56: If (M> = s)
004011b3 mov eax, dword ptr [EBP + 8]
004011b6 mov ECx, dword ptr [eax]
004011b8 CMP ECx, dword ptr [ebp-4]
004011bb JL input + 0afh (004011bf)
57: break;
004011bd JMP input + 0c1h (004011d1)
58: else
59: printf ("m <n * (n + 1)/2, please input again! \ N ");
004011bf push offset string "m <n * (n + 1)/2, please input agai"... (00426060)
004011c4 call printf (00401530)
004011c9 add ESP, 4
60 :}
004011cc JMP input + 18 h (00401128)
61:
62 :}
004011d1 pop EDI
004011d2 pop ESI
004011d3 pop EBX
004011d4 add ESP, 48 h
004011d7 cmp ebp, ESP
004011d9 call _ chkesp (004015b0)
004011de mov ESP, EBP
004011e0 pop EBP
004011e1 RET 8
Finally, we can see that at the end of the function, there is RET 8, which is obviously the restoration stack, because in 32-bit C ++, the variable address is 4 bytes (Int Is also 4 bytes), so the two addresses on the stack are 8 bytes.
From this we can see that the main call function is responsible for the stack pressure, and the called function is responsible for restoring the stack. Therefore, variable parameter functions cannot be implemented, because the called function cannot know the number of bullet stacks in advance, but this can be done in the main function, because the number of parameters is determined by the main function.
Next let's take a look at what the ebp-8 and ebp-4 addresses actually store, the ebp-8 address stores the N value, and EBP-4 stores the m value. It also applies parameter transfer from right to left.
Conclusion: The main call function is responsible for pushing the stack, the parameters in the stack Are popped up in the called function, and the stack is recovered. Therefore, the variable parameter function cannot be implemented. The parameter is passed from right to left. In addition, the naming modification method is to add an underscore (_) to the front of the function, and there is a symbol (@) after the function name (@), the number of bytes occupied by the parameter following @ followed by the parameter list (10 hexadecimal), for example, void input (Int & M, Int & N), is modified to: _ INPUT @ 8
Callback is used for most API functions and window message processing functions. Therefore, before calling the function, the main function will first press the stack, and then the API function restores the stack by itself.
For example:
Push edX
Push EDI
Push eax
Push EBX
Call getdlgitemtexta
You can think about what are stored in these registers?
The following is a summary:
For C/C ++ users, the two most common call conventions are _ cdecl and _ stdcall (winapi, callback, Pascal). They are different in the following aspects:
1. Supported by default: VC uses _ cdecl by default. Therefore, if you need to use _ stdcall, you can use two methods: (1) You can manually add it before the function name, which is only valid for a single function (2) directly modify project properties (C/C ++> advanced> calling convention) to configure all functions at a time.
2. Different functions: _ cdecl can implement a variable length parameter list.
3. code size: _ stdcall smaller
4. Different speeds: _ cdecl is faster (more code means faster running, a bit like an inline function)
5. Who is responsible for restoring the stack:
_ Cdecl the master calls the function to perform parameter pressure stack and restore the stack;
_ Stdcall: the master calls the function to implement parameter pressure stack, and the called function restores the stack;
This is precisely because
1. Cause of different code sizes: If the _ cdecl function is used to call the same function multiple times, multiple recovery codes will be generated.
2. Reasons for different functions: implement the variable length parameter list. One copy of the recovery code can only return one length of the parameter table to the stack. Therefore, to restore the parameter table stack with different lengths, you must have multiple copies of the Code, therefore, the variable length parameter must be restored by the main function (so it is _ cdecl ).
6. The name of the generated function is different: For details, refer to the above discussion (note that this is different from the name of the C ++ generated modifier)
7. Scope of use:
_ Stdcall: it is usually used to create DLL (to support multi-language calls). Besides, Win32 API functions use _ stdcall (such as MessageBox). Therefore, custom functions in Win32 programs also use _ stdcall.
_ Cdecl: A non-DLL console program.