The function works with the help of stacks.
The stack is a special storage space in memory, its storage principle is "advanced out", the first stored data is finally released.
ESP is called the stack-top pointer, and EBP is called the stack-bottom pointer, which holds the start and end addresses of the current stack through these two pointer registers.
The space formed between the ESP and the EBP becomes a stack frame. Usually, in VC + +, the data that can be addressed in the stack frame are local variables, function return address, function parameters, etc. Different two function calls, the resulting stack frame is also different. When a function is entered into another function, the required stack space is formed for the function being called, and the stack frame of this function is formed. When this function ends the call, it needs to clear out the stack space it uses and close the stack frame, a process known as stack balancing.
int main () {return 0;}
The assembly code explains the int main () {00c81380 push EBP ; the first thing after entering the function, save the stack-bottom pointer ebp00c81381 mov ebp,esp ; Adjust the bottom pointer to the top of the stack 00c81383 sub esp,0c0h ; Raise the new stack top, open the stack space c0h, as a local variable storage space, forming this main function of the stack frame 00c81389 push EBX 00c8138a push esi 00c8138b push EDI 00c8138c Lea edi,[ EBP-0C0H] 00c81392 mov ecx,30h 00c81397 mov eax,0cccccccch 00c8139c Rep STOs dword ptr Es:[edi] return 0;00c8139e xor eax,eax } ; When exiting, restore the original stack frame, The value of EBP is the original ESP, then pops out ebp00c813a0 pop edi 00c813a1 pop esi 00c813a2 pop EBX 00c813a3 mov esp,ebp ; restore esp00c813a5 pop ebp ; restore EBP00C813A6 ret
The above code does not detect stack balance when exiting, as follows
00c813a0 pop edi 00c813a1 pop esi 00c813a2 pop ebx More of this section detection addesp,40h; Lower the stack top ESP, at which time the local variable space is released CMPEBP,ESP, the detection stack balance, such as EBP and ESP unequal, then unbalanced call_chkesp; Enter stack balance error check function 00c813a3 mov esp,ebp ; restore Esp00c813a5 pop ebp ; restore EBP00C813A6 ret
In VC + + environment There are three kinds of function calling conventions: _cdecl, _stdcall, Fastcall.
_cdecl:c/c++ default call method, caller balance stack, variable parameter function can be used.
_stdcall: The callee balanced stack, the variable parameter function is not available.
_fastcall: The Register method, the callee balanced stack, the function of the indefinite parameter can not be used.
#include <stdio.h>void _stdcall showstd (int number) {printf ("%d\r\n", number);} void _cdecl SHOWCDE (int number) {printf ("%d\r\n", number);} void Main () {SHOWSTD (5); SHOWCDE (6);} void _stdcall showstd (int number) {00391C60 push ebp 00391c61 mov ebp,esp 00391c63 Sub esp,0c0h 00391C69 push ebx 00391c6a push esi 00391c6b push EDI 00391c6c Lea edi,[ebp-0c0h] 0 0391C72 mov ecx,30h 00391c77 mov eax,0cccccccch 00391c7c rep stos dword ptr Es:[edi] printf ("%d\r \ n ", number); 00391c7e mov esi,esp 00391c80 mov eax,dword ptr [number] 00391c83 push eax 00391 C84 Push 3958a8h 00391c89 call DWORD ptr ds:[399114h] 00391c8f add esp,8 00391c92 cmp Esi,esp 00391c94 call __rtc_checkesp (03911DBh)}00391c99 pop edi 00391c9a pop esi 00391c9b Pop ebx 00391c9c add esp,0c0h 00391CA2 cmp ebp,esp 00391CA4Call __rtc_checkesp (03911DBh)}00391ca9 mov esp,ebp 00391CAB pop ebp 00391CAC ret 4 After this end balance stack top 4, equivalent to esp+4void _cdecl showcde (int number) {00391780 push ebp 00391781 MOV ebp,esp 00391783 sub esp,0c0h 00391789 push ebx 0039178A push esi 0039178B push EDI 0039178C Lea edi,[ebp-0c0h] 00391792 mov ecx,30h 00391797 mov eax,0cccccccch 003 9179C Rep STOs dword ptr Es:[edi] printf ("%d\r\n", number); 0039179E mov esi,esp 003917a0 mov eax,d Word ptr [number] 003917A3 push eax 003917a4 push 3958a8h 003917a9 call DWORD ptr ds:[399114h] 003917AF add esp,8 003917b2 cmp esi,esp 003917b4 call __RTC_CHECKESP (03911DBh)}003917b9 p Op edi 003917BA pop esi 003917BB pop ebx 003917BC add esp,0c0h 003917c2 cmp Ebp,esp 003917c4 CalL __RTC_CHECKESP (03911DBh)}003917c9 mov esp,ebp 003917CB pop ebp 003917CC ret Here, the direct return does not have its own balance, when the execution right to the caller balance Avoid main () {00392520 push ebp 00392521 mov ebp,esp 00 392523 Sub esp,0c0h 00392529 push ebx 0039252A push esi 0039252B push EDI 0039252C l EA edi,[ebp-0c0h] 00392532 mov ecx,30h 00392537 mov eax,0cccccccch 0039253C rep stos Dwor D ptr Es:[edi] SHOWSTD (5), 0039253E push 5 00392540 call SHOWSTD (03911d1h) SHOWCDE (6); 00392545 push 6 00392547 Call SHOWCDE (03911CCh) 0039254C add esp,4; There is no balance at the top of the stack, now balanced}0039254f XOR Eax,eax; The following stack frame Close is the main function of the 00392551 pop EDI 00392552 pop esi 00392553 pop ebx 00392554 add esp,0c0h 0039255A cmp ebp,esp 00392 55C Call __rtc_checkesp (03911DBh) 00392561 mov esp,ebp 00392563 pop ebp}00392564 ret
why balance the top of the stack? I've never been able to understand, I always think when I call the function execution, the function formed its own stack frame, save it can use the local variables and so on, when it ends, directly restored to the original stack top can be, that is, MOV esp,ebp this sentence can be, But why would you want to make changes to the ESP when you return. Now figure out that the reason is that the function has parameters, before calling the function, the argument is pressed into the stack, so at the end of the function, the stack frame of the function is closed, but the caller's stack frame also holds the parameters needed for the function just now, it becomes useless data, of course, to kick it out.
When the SHOWCDE function call is finished, the data of the yellow area stack is useless, so the top of the stack is lowered.
Let's take a look at the Register mode, fastcall
#include <stdio.h>void _fastcall showfast (int one, int, int three, int four) {printf ("%d%d%d%d\r\n", One,two,thr Ee,four);} void Main () {showfast (1, 2, 3, 4);} void _fastcall showfast (int one, int, int three, int four) {00132f90 push ebp 00132f91 mov ebp,esp 0 0132f93 Sub esp,0d8h 00132f99 push ebx 00132f9a push esi 00132f9b push EDI 00132f9c Push ecx 00132f9d Lea edi,[ebp-0d8h] 00132FA3 mov ecx,36h 00132FA8 mov eax,0cccccccch 00132FAD Rep STOs dword ptr Es:[edi] 00132FAF pop ecx 00132fb0 mov dword ptr [Two],edx; The temporary variable stores the value 2 of the parameter two, displays the Mov DWORD ptr in Ida [EBP-8],EDX00132FB3 mov dword ptr [ONE],ECX;] stores the value of parameter one with a temporary variable 1,mov dword ptr [Ebp-4],ecxprintf ("%d%d%d%d\r\n", one,two,three,four) 00132FB6 mov esi,esp 00132FB8 mov eax,dword PT R [four]; MOV eax,dword ptr [ebp+0ch], get parameter 400132FBB push eax 00132FBC mov ecx,DWORD ptr [three]; MOV ecx,dword ptr [ebp+8], get parameter 300132FBF push ecx 00132FC0 mov edx,dword ptr [ ] 00132FC3 push edx 00132FC4 mov eax,dword ptr [one] 00132fc7 push eax 00132FC8 push 1358a8h 00132FCD call DWORD ptr ds:[139114h] 00132fd3 add esp,14h 00132fd6 cmp esi,esp 00132 FD8 call __rtc_checkesp (01311DBh)}00132fdd pop edi 00132FDE pop esi 00132FDF pop E BX 00132fe0 add esp,0d8h 00132fe6 cmp ebp,esp 00132fe8 call __RTC_CHECKESP (01311DBh) 00132F ED mov esp,ebp 00132FEF pop ebp 00132ff0 ret 8; Using a two register to aid in the parameter transfer, use the stack to pass the parameter Only two, so ret 8void main () {00131C60 push ebp 00131c61 mov ebp,esp 00131c63 sub esp,0c0h 00131c69 Push ebx 00131c6a push esi 00131c6b push EDI 00131c6c Lea edi,[ebp-0c0h] 00131c72 m OV ecx,30h 00131C77 mov eax,0cccccccch 00131c7c rep stos dword ptr Es:[edi] Showfast (1, 2, 3, 4); ; see here 00131c7e push 4; Pass parameters 3 and 400131c80 push with stack 3 00131C82 mov edx,2; pass the second parameter 200131c87 mov ecx,1 with edx ; Pass the first parameter with ECX 100131c8c call Showfast (01311e5h)}00131c91 xor eax , eax 00131c93 pop edi 00131c94 pop esi 00131c95 pop ebx 00131c96 add esp,0c0h 001 31C9C CMP ebp,esp 00131c9e call __RTC_CHECKESP (01311DBh) 00131CA3 mov esp,ebp 00131ca5 pop EBP}00131CA6 RET
The above notes are clear, and it is important to note thatWhen using EBP relative addressing to locate parameters 3 and 4 o'clock, why not start with ebp+4 because the address of the next instruction of the call is pressed into the stack when the function is called, so the position starts at ebp+8.
How the function works