Several concepts of functions call:

xiaoxiao2021-03-06  15

Several concepts of function calls: _stdcall, _cdecl ....

1, _stdcall is the default call mode of the Pascal program. It is usually used in the Win32 API. The function uses the stacking method from the right to left, and the stack is cleared when you exit. The VC compiles the function before adding a downline prefix in front of the function name, plus the number of bytes of "@" and parameters after the function name.

2, c call convention (ie, using __cdecl keyword description) Press the parameter from right to left, and populates the argument by the caller. For the memory stack of the transfer parameters, it is maintained by the caller (for this, the function that implements variable parameters can only use the call convention). In addition, there is also different in terms of function name modification.

_CDECL is the default call mode of the C and C programs. Each function that calls it contains the code that clears the stack, so the resulting executable size is larger than the call _stdcall function. The function uses the stack of right to left. VC compiles the function and adds a downline prefix in front of the function name. It is an MFC default call convention.

3, __ fastCall call agreement is "person", such as its name, its main feature is fast, because it passes the parameter through the register (actually, it uses ECX and EDX to transfer the first two double words (DWORD) or smaller The parameters, the remaining parameters are still transmitted to the left stack, the called function is returned to the internal memory stack of the transfer parameters before returning), and in terms of the function name modification, it is different from the top.

_fastCall mode functions use register pass parameters, and VC compiles the function after the "@" prefix in front of the function name, add the number of bytes of "@" and parameters after the function name.

4. ThisCall is only applied to the "C " member function. The THIS pointer is stored in the CX register, the parameter is left from right to left. Thiscall is not a keyword, so it cannot be designated by the programmer.

5, Naked Call When using 1-4 call conventions, if necessary, the compiler generates code to save the ESI, EDI, EBX, EBP registers, generate code recovery of these registers when entering the function. Naked Call does not produce such a code. Naked Call is not a type modifier, so you must use the _declspec.

Keywords __cdecl and __fastcall can be selected before the functionality to be output, can also be selected in the compiler. When the keyword before the output function is not in the compilation environment, the keyword before the output function is added directly before the output function is valid. The corresponding command line parameters are / Gz, / GD, and / GR, respectively. The default state is / gd, ie __cdecl.

To fully imitate the Pascal call, you must first use the __stdcall call convention, as for the function name modification, can be imitated by other methods. There is also a WINAPI macro, Windows.h supports this macro, which can translate the function into an appropriate call agreement, in Win32, it is defined as __stdcall. Use WinAPI macros to create your own APIS.

2) Name modification agreement

1, Decoration Name

"C" or "C " function is identified by a modified name inside (compiled and link). The modisle name is a string generated when the compiler is generated when the compile function is defined or the prototype. Some cases are necessary to use the modifier of the function, such as the output "C " overload function, constructor, the structure, the destructor, and call "C" or "C " function in the assembly code. Wait.

The modified name, class name, call agreement, return type, parameter, etc.

2, the name modification will change with the adjustment agreement and the compilation species (C or C ). The function name modification is different from the compilation species and the call agreement, and below will be explained.

A, C compile time function name modification agreement rules:

__stdcall call agreed to add a downline prefix before the output function name, and then a "@" symbol and its parameters of the number of bytes, the format is _functionName @ number.

__cdecl call conventions only add a downline prefix before the output function name, format is _functionName. __Fastcall call agreed to add a "@" symbol before the output function name, the later is also a "@" symbol and its parameters, the format is @ functionName @ number.

They do not change the case sensitive in the output function name, which is different from the PASCAL call, and the function name of the Pascal agreed output without any modification and all uppercase.

B, C compile function name modification agreement rules:

__stdcall call convention: 1, with "?" identification function name, then follow the function name; 2. After the function name is labeled with the "@@ YG" identifier, the parameter table; --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 - represents a pointer, the subsequent code indicates the pointer type, if the same type of pointer continuously appears, instead of "0", a "0" represents a repetition; 4, parameter table The first item is the return value type of the function, thereafter, the data type of the parameter, the pointer identifies the end of its index; 5, after the parameter table identifies the end of the entire name, if the function No parameters, the end is ended in the "Z" identity.

The format is "? Functionname @@ yg ***** @ z" or "functionname @@ yg * xz", such as int test1 (char * var1, unsigned long) ----- "Test1 @@ yghpadk @Z "void test2 () -----"? Test2 @@ ygxxz "

__cdecl call agreement: Rule the above _stdcall call convention, just the start identification of the parameter table is changed from the "@@ YG" above "@@ ya".

__fastcall call convention: Rule the above _stdcall call convention, just the start identification of the parameter table changes from the "@@ yg" above "@@ yi".

The province of VC to the function is "__CEDCL", which will only be called by C / C .

CB uses four modified symbols // __ cdeclcb's default values ​​when the output function declaration is used, which will be preceded in the output function name, and retain this function name is constant, and the parameters are transmitted in the order from the right to left. Write a _cDecl and CDECL form. // __ fastCall The parameters of her modified function will use the register to use the register, and the function name is preceding @, the parameters are stacked from left to right; // __ pascal it illustrates the name of the function name using Pascal format Agree. At this time, the function is all capitalized. The parameter is stacked from left to right; // __ stdcall In Turbo C, the function of modifier CDECL instructions or does not mention the parameters into the stack in the order from the right left, ie a give call function ( After A, B, C), a first in the stack, then B and C. When the function is being called, there are several call methods to be classified into C, PASCAL. C-type C is default unless special declarations. The two are different. Here we use examples:

1. __cdecl: C and C Default call mode example: Void INPUT (INT & M, INT & N); / * Equivalent to void __cdecl INPUT (INT & M, INT & N); * / The following is the corresponding assembly code: 00401068 Lea Eax , [EBP-8]; Take the [EBP-8] address (EBP-8), save the EAX 0040106B Push Eax; then press the 0040106C LEA ECX, [EBP-4]; take the [EBP-4] address (EBP- 4), save the ECX 0040106F PUSH ECX; then press the address (0040100A); then call the input function 00401075 Add ESP, 8; recovery stack From the process of calling the input function from the above: Before calling this function, press EBP-8, then press EBP-4, then call function input, and finally the Input function call is completed, use the ESP 8 recovery stack. It can be seen that the default function modification _cdecl in the C language is called, and the parameter stack is performed by the main call function and the stack is restored. Let's take a look at: What is address EBP-8 and EBP-4? In the VIEW of the VC, select Rebug Windows, then select Registers, display register variable, and then enter the value of EBP-8 and EBP-4 value (or directly input EBP-8 and -4) below the Memory below. Look at what the value is actually stored in these two addresses, it is actually the address of the variable N (EBP-8), M's address (EBP-4), which can be seen: in the main call function The stack and the order is from right to left. In addition, since the argument is a reference to the corresponding variable, it is also proved that the address (similar to pointer) is actually referenced. Summary: In C or C language calls, the default function modification _cdecl is made by the main call function, and the stack is restored. The stack order of the arguments is from right to left, and finally the stack recovery is made by the master function. Since the main adjustment function management stack, the changeable function can be implemented. In addition, the naming modification method is to add an underline (_) before the function.

2. WinAPi (actually PASCAL, CALLBACK, _STDCALL) example: Void WinAPI INPUT (INT & M, INT & N); Look at the assembly code of the corresponding call: 00401068 Lea Eax, [EBP-8] 0040106B Push EAX0040106C Lea ECX, [ EBP-4] 0040106F PUSH ECX00401070 Call @ ilt 5 (0040100A) From the above-described process of calling the input function: Before calling this function, first press the EBP-8, then press EBP-4, then Call the function input, after calling the function input, there is no corresponding stack recovery (for other function calls, so I have not listed) The following is listed below the assembly code of the input function itself: (actually this function is not big, but compiling The example is still bigger, everyone can only look at the front and after, the middle code has nothing to do with this example)

39: void WINAPI Input (int & m, int & n) 40: {00401110 push ebp00401111 mov ebp, esp00401113 sub esp, 48h00401116 push ebx00401117 push esi00401118 push edi00401119 lea edi, [ebp-48h] 0040111C mov ecx, 12h00401121 mov eax, 0CCCCCCCCh00401126 rep Stos DWORD PTR [EDI] 41: Int S, I; 42: 43: While (1) 00401128 MOV Eax, 10040112D Test Eax, EAX0040112F JE Input 0C1H (004011D1) 44: {45: Printf ("/ NPLEase Input The first Number M: "); 00401135 Push Offset String" / NPLEASE INPUT The First Number M "... (004260B8) 0040113A Call Printf (00401530) 0040113F Add ESP, 446: Scanf ("% D ", & M); 00401142 MOV ECX , dword ptr [ebp 8] 00401145 push ecx00401146 push offset string "% d" (004260b4) 0040114B call scanf (004015f0) 00401150 add esp, 847: 48: if (m <1) continue; 00401153 mov edx, dword ptr [ EBP 8 ] 00401156 cmp dword ptr [edx], 100401159 jge Input 4Dh (0040115d) 0040115B jmp Input 18h (00401128) 49: printf ( "/ nPlease input the first number n:"); 0040115D push offset string "/ nPlease input the first number n "... (0042608c) 00401162 call printf (00401530) 00401167 add esp, 450: scanf ("% d ", & n); 0040116A mov eax, dword ptr [ebp 0Ch] 0040116D push eax0040116E push offset string" % D "(004260B4) 00401173 Call scanf (004015f0) 00401178 Add ESP, 851: 52: IF (n <1) Continue; 0040117B MOV ECX, DWORD PTR [EBP

0ch] 0040117E CMP DWORD PTR [ECX], 100401181 JGE INPUT 75H (00401185) 00401183 JMP INPUT 18H (00401128) 53:54: for (i = 1, s = 0; i <= n; i ) 00401185 MOV DWORD PTR [EBP-8], 10040118c MOV DWORD PTR [EBP-4], 000401193 JMP Input 8EH (0040119E) 00401195 MOV EDX, DWORD PTR [EBP-8] 00401198 Add EDX, 10040119B MOV DWORD PTR [EBP-8], EDX0040119E 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], EDX004011B1 JMP INPUT 85H (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; 00401 1BD JMP INPUT 0C1H (004011d1) 58: Else59: Printf ("M

Obviously, the stack is restored. Due to the 32-bit C , the variable address is 4 bytes (INT is also 4 bytes), so two addresses are 8 bytes. It can be seen that the stack is responsible for the stack in the main modulation function, and is responsible for restoring the stack in the called function. Therefore, the changeable function cannot be achieved because the called function cannot know the number of stacks in advance, but can be done in the main adjustment function, because the number of parameters is determined by the main adjustment function. Let's take another look, the two addresses of EBP-8 and EBP-4 actually store what values, the EBP-8 address is N, and EBP-4 is stored at the value of M. The description is also from right to left stack, perform parameter delivery. Summary: Responsible in the main adjustment function, responsible for popping the parameters in the stack in the called function and is responsible for restoring the stack. Therefore, the variable-gate function cannot be realized, and the parameter transmission is from right to left. In addition, the naming modification method is to add a downline (_) before the function, there is a symbol (@) after the function name, and the number of items accounting in the parameter in the parameter list (10), such as: Void INPUT (INT & M, INT & N), is modified: _input @ 8 For most API functions, the window message handler is used in callback, so before calling, the Motor will press the stack first, then the API function restores the stack. Such as: Push Edx Push EDI PUSH EAX PUSH EBX CALL GETDLGITEMTEXTA You can think about what these registers are stored?

转载请注明原文地址:https://www.9cbs.com/read-48348.html

New Post(0)