When high-level language functions are compiled into machine code, there is a problem that must be resolved: Because the CPU has no way of knowing how many parameters a function call requires. That is, the computer does not know how to pass parameters to this function, the work of passing parameters must be coordinated by the function caller and the function itself . To do this, the computer provides a data structure called a stack to support parameter passing. When the function is called, the caller pushes the argument in sequence, then calls the function, the function is called, the data is obtained in the stack, and the calculation is made. After the function calculation is finished, either the caller or the function itself modifies the stack to restore the stack to the original. In parameter passing, there are two important questions that must be explicitly stated: 1) When the number of arguments is more than one, in what order the parameters are pressed into the stack; 2) After the function call, who will restore the stack to original.
3) where the return value of the function is placed
In high-level languages, these two problems are illustrated by the function invocation specification (calling conventions) . The common invocation specifications are: stdcall cdecl Fastcall ThisCall Naked Call stdcall Invocation SpecificationStdCall is often called the Pascal invocation specification, because Pascal is a very common teaching computer programming language, its syntax is rigorous, and the function calling convention used is stdcall. In the Microsoft C + + series, the C + + compiler often uses Pascal macros to declare this calling convention, and similar macros have WINAPI and callback. The syntax for the StdCall invocation specification declaration is: int __stdcall function (int A,int b) The calling convention of StdCall means: 1) The parameters are pressed from right to left onto the stack, 2) The function itself modifies the stack, 3) The letter name automatically adds a leading underscore followed by an @ symbol followed by the dimension of the parameter. Taking this function as an example, the parameter B is first compressed, then the parameter a, the function call functions (at the end of the call) is translated into assembly language will be:Push 2 The second parameter into the stack push 1 The first parameter into the stack call function invocation parameter, note that at this time automatically put Cs:eip into the stack For the function itself, it can be translated as: The push EBP saves the EBP register, which will be used to hold the stack-top pointer on the heap, which can be restored when the function exits mov ebp,esp save stack pointer mov EAX,[EBP + 8H] The stack in which ebp points to the position is saved with EBP,CS:EIP,A,B,EBP +8 pointing to a add EAX,[EBP + 0CH] stack in EBP + 12 saved b mov esp,ebp recovery ESP pop< C11/>EBP RET 8
And at compile time, the name of this function is translated into [email protected] Note that different compilers insert their own assembly code to provide the commonality of compilation, but the general code does so. Where the function is kept at the beginning of the ESP into EBP, at the end of the function recovery is a common method of the compiler. From a function call, 2 and 1 are then push into the stack in turn, and in the function, the parameters are accessed by an offset relative to the EBP (that is, the stack pointer when the function is just entered). After the function ends, ret 8 cleans up the 8-byte stack, and the function recovers the stack itself. cdecl Invocation SpecificationThe cdecl calling convention, also known as the C calling convention, is the C language default calling convention, and its definition syntax is: int function (int A,int b) //Not decorated is the C calling convention int __cdecl function ( int A,int b) //explicitly indicate C calling convention
The parameters of the cdecl calling convention are stacked in the same order as stdcall, and the parameters are first pushed to the left by the stack. The difference is that the function itself does not clean up the stack, and the caller is responsible for cleaning up the stack. Because of this change, the C calling convention allows the number of parameters of the function is not fixed, which is a major feature of C language. For the preceding function functions, the assembly code after using CDECL becomes: Call Place push 1 push 2 call function add esp,8 Note: Here the caller is called in the recovery stack at the function _function The push EBP is saved The EBP register, which will be used to hold the stack top pointer on the heap, can be restored when the function exits the Mov ebp,esp save stack pointer mov EAX,[EBP + 8H] in the stack before the EBP points to the position to save the EBP, CS:EIP,A,B,EBP +8 points to a add EAX,[EBP + 0CH] stack in EBP + 12 saved b mov esp,ebp recovery esp pop EBP ret Note that the stack is not modified here
MSDN says the adornment automatically preceded the function name with a leading underscore, so the function name is recorded as _function in the symbol table. Since the parameters are stacked in the right-to-left order, the first parameter is closest to the top of the stack, so when the variable number of parameters is used, the position in the stack must be known, as long as the indefinite number of parameters can be determined according to the first subsequent explicit parameters, you can use the indefinite parameter, For example, the sprintf function is defined as: int sprintf (char* buffer,constchar* format,...) Since all the indeterminate parameters can be determined by format, it is no problem to use an indefinite number of parameters.fastcall Invocation SpecificationThe fastcall calling convention is similar to stdcall, which means: 1) The first and second DWORD parameters of the function (or smaller size) are passed through ECX and edx, other parameters are pushed through the right-to-left order, 2) are called function cleanup stacks, 3) function names modify the rules with stdcall. Its declaration syntax is: int __fastcall function (int a,int b)thiscall Invocation SpecificationThisCall is the only function decoration that cannot be explicitly specified, because thiscall is not a keyword. It is the default calling convention for C + + class member functions. Because a member function call has a this pointer, it must be handled specially, and thiscall means: 1) parameters from right to left into the stack; 2) If the number of arguments is determined, the this pointer is passed through ECX to the callee; If the parameter number is indeterminate, the this pointer is pressed onto the stack after all arguments are pressed, 3) The caller cleans up the stack if the number of arguments is variable, or the function cleans up the stack itself. To illustrate this calling convention, define the following classes and use code:classa{ Public:intFunction1 (intAintb);intFunction2 (inta,...);};intA::function1 (intAintb) {returnA+b;}intA::function2 (intA,...) {va_listAp Va_start (Ap,a);intIintresult =0; for(i =0; i < A; i + +) {result + = Va_arg (AP,int); }returnResult;}voidCallee () {a A; A.function1 (1,2); A.function2 (3,1,2,3);} When the callee function is translated into a compilation, it becomes:function Function1 call 0401c1d push 2 00401c1f push 1 00401c21 Lea ecx,[ebp-8] 00401C24 call< C8/>function1 Note that here this is not in the stack//function function2 call 00401c29 push 3 00401c2b push 2 00401c2d Push 1 00401c2f push 3 00401c31 Lea Eax,[ebp-8] Here introduce this pointer 00401c34 push eax 00401c35 call function2 00401c3a add esp,14h It can be seen that, for a fixed number of parameters, it is similar to stdcall, and is similar to cdecl when uncertain .Naked Call Invocation specificationThis is a very rare calling convention that general program designers do not recommend to use. The compiler does not add initialization and cleanup code to this function, and, more specifically, cannot return the return value with return, only the result is returned with the Insert assembly. This is generally used for real-mode driver programming, assuming that a summation of the addition program is defined, which can be defined as:int Add (int A,int b) {__asm mov eax,a __asm add eax,b __asm ret} Note that this function does not have an explicit return value, which is returned by modifying the EAX register implementation, and the RET instruction that even exits the function must be explicitly inserted. The above code is translated into a compilation later into:mov eax,[ebp+8] Add eax,[ebp+12] ret 8 Note that this modification is used in conjunction with __stdcall and Cdecl, which is preceded by code that is used in conjunction with CDECL, and the code that is combined with stdcall becomes:int __stdcall function (int A,int8//Note the following 8 } As for this function being called, it is consistent with the normal cdecl and stdcall call functions.common problems caused by function calling conventionsIf the defined conventions and the conventions used are inconsistent, it will cause the stack to be corrupted, causing serious problems, and the following are two common problems:1) function prototype declaration and function body Definition inconsistent 2) DLL Import function declares different function conventions
|