function Call stack

Source: Internet
Author: User
Tags intel pentium

These days suddenly want to understand the use of the stack when the C function call, the Internet to check the information, self has also studied a bit, this blog on my income recorded it. This blog attempts to explain how a stack frame is created and how it is eliminated when a C function is called. These details are related to the implementation of the operating system platform and compiler, and the following description is for the GCC compiler running on the Intel Pentium Chip Linux. The C language standard does not describe the way the implementation is implemented, so different compilers, processors, and operating systems may have their own way of building stack frames. A typical stack frameesp==>| :             |
|             . |
+-------------------------+
| Callee-Saved Registers Live |
| Ebx,esi and EDI (as needed) |
+-------------------------+
| Temporary Space |
+-------------------------+
| Local Variables # | [EBP-8]
+-------------------------+
| Local Variable # # | [EBP-4]
+-------------------------+
ebp==>| EBP of the caller |
+-------------------------+
| Return Address |
+-------------------------+
| Actual parameter # | [EBP + 8]
+-------------------------+
| Actual parameter # | [EBP + 12]
+-------------------------+
| Actual parameter # # | [EBP + 16]
+-------------------------+
| Caller-Saved Register field |
| Eax,ecx and edx (on request) |
+-------------------------+
| :            |
|            . |

Figure 11 A typical stack frame, in the diagram, the top of the stack, the address space grows downward this is the contents of the stack when a function call is:
int foo (int arg1, int arg2, int arg3), and Foo has two local int variables (4 bytes). In this simplified scenario, main calls Foo, and the program control is still in Foo. Here, main is the caller (caller), and Foo is the callee (callee).
ESP is used by Foo to indicate the top of the stack. EBP is equivalent to a "benchmark pointer". The arguments passed from main to Foo and the local variables of Foo itself can be found using this reference pointer, plus the offset.
Because the callee is allowed to use the EAX,ECX and edx registers, if the caller wants to save the values of these registers, they must explicitly save them in the stack before calling the sub-functions. On the other hand, if, in addition to the registers mentioned above, the callee would like to use other registers, such as Ebx,esi and EDI, the callee would have to save these extra registers in the stack and reply to them before the call returned. That is, if the callee only uses the agreed eax,ecx and edx registers, they are the caller's responsibility to save and reply, but if called this also uses additional registers, then they have to save and reply to the values of those registers themselves.
The arguments passed to Foo are pressed onto the stack, and the last parameter is the advanced stack, so the first parameter is at the top of the stack. The local variables declared in Foo and some temporary variables that need to be used during function execution are also present in the stack.
A return value of less than or equal to 4 bytes is saved to eax, and if it is greater than 4 bytes and less than 8 bytes, edx is also used to hold the return value. If the return value takes up more space, the caller passes an extra argument to the callee, which points to the address where the return value will be saved. In C, it is a function call:
x = foo (A, B, c);
be converted to:
Foo (&x, A, b, c);
Note that this occurs only if the return value occupies more than 8 bytes. Some compilers do not use edx to save the return value, so this conversion is used when the return value is greater than 4 bytes.
Of course, not all function calls are assigned directly to a variable, or they may be directly involved in the calculation of an expression, such as:
m = foo (A, B, c) + foo (d, E, f);
Or as a parameter of another function, such as:
Fooo (foo (A, B, c), 3);
In these cases, the return value of Foo is saved in a temporary variable to participate in subsequent operations, so Foo (a, B, C) can be converted to Foo (&tmp, A, B, c). Let's take a step-by-step look at how a stack frame is built and eliminated during a C function call. the action of the caller before the function callIn our example, the caller is main and it is ready to invoke the function foo. Before the function call, main is using the ESP and EBP registers to indicate its own stack frame.
First, main pushes EAX,ECX and edx to stack. This is an optional step that is performed only when the three register contents need to be preserved.
Next, main puts the arguments passed to Foo into the stack, and the last parameter is the most advanced stack. For example, our function calls are:
A = foo (12, 15, 18);
The corresponding assembly language instructions are:
Push DWORD 18
Push DWORD 15
Push DWORD 12
Finally, main invokes the child function with the call Directive:
Call Foo
When the call command executes, the contents of the EIP instruction pointer register are pressed into the stack. Since the EIP register is pointing to the next instruction in main, the return address is now at the top of the stack. After the call command finishes executing, the next execution cycle starts at the mark named Foo.
Figure 2 shows the contents of the stack after the call command completes. The thick lines in Figure 2 and subsequent graphs indicate the position of the top of the stack before the function call. We will see that when the entire function call process is finished, the top of the stack is back to this position.| |
+-------------------------+
esp==>| Return Address |
+-------------------------+
| Actual parameter # # = 12 |
+-------------------------+
| Actual parameter # = 15 |
+-------------------------+
| Actual parameter # = 18 |
+-------------------------+
| Caller-Saved Register field |
| Eax,ecx and edx (on request) |
+=========================+
| :            |
ebp==>|            . |

Figure 2

the action of the callee after the function callWhen the function foo, that is, the callee takes control of the program, it must do 3 things: Build its own stack frame, allocate space for local variables, and finally, if necessary, save the register Ebx,esi and EDI values.
First Foo must build its own stack frame. The EBP register is now pointing to a position in the stack frame of main, and this value must be preserved, so the EBP is in the stack. The contents of the ESP are then assigned to EBP. This allows the function's parameters to be obtained by attaching an offset to EBP, while the stack register ESP can be vacated to do other things. As a result, almost all C functions start with the following two instructions:
Push EBP
MOV EBP, esp
The stack in this case is shown in Figure 3. In this scenario, the address of the first parameter is EBP plus 8, because main's EBP and return address each account for 4 bytes in the stack.
| |
+-------------------------+
esp=ebp==>| EBP of Main |
+-------------------------+
| Return Address |
+-------------------------+
| Actual parameter # # = 12 | [EBP + 8]
+-------------------------+
| Actual parameter # = 15 | [EBP + 12]
+-------------------------+
| Actual parameter # = 18 | [EBP + 16]
+-------------------------+
| Caller-Saved Register field |
| Eax,ecx and edx (on request) |
+=========================+
| :            |

Figure 3 Next, Foo must allocate space for its local variables, and it must allocate space for some of the temporary variables it might use. For example, some C statements in Foo may include complex expressions, and the intermediate values of their sub-expressions must be stored somewhere. The places where the intermediate values are stored are called temporary because they can be reused for the next complex expression. For illustrative convenience, we assume that our Foo has two local variables of type int (4 bytes each) and requires an additional 12 bytes of temporary storage space. Simply subtract the stack pointer by 20 and allocate space for these 20 bytes:
Sub ESP, 20
Both local variables and temporary storage can now be found through the datum pointer ebp plus offset.
Finally, if Foo is used with the Ebx,esi and EDI registers, then it must save them in the stack. As a result, this is now shown in stack 4.| : |
+-------------------------+
esp==>| saved by the caller of the Register Live |
| Ebx,esi and EDI (as needed) |
+-------------------------+
| Temporary Space | [EBP-20]
| |
+-------------------------+
| Local Variables # | [EBP-8]
+-------------------------+
| Local Variable # # | [EBP-4]
+-------------------------+
ebp==>| EBP of Main |
+-------------------------+
| Return Address |
+-------------------------+
| Actual parameter # | [EBP + 8]
+-------------------------+
| Actual parameter # | [EBP + 12]
+-------------------------+
| Actual parameter # # | [EBP + 16]
+-------------------------+
| Caller-Saved Register field |
| Eax,ecx and edx (on request) |
+=========================+
| :            |Figure 4 The function of Foo is reflected in the ability to execute. There may be stacks and stacks, and the stack pointer, ESP, will move up and down, but EBP stays the same. This means that we can always use [ebp+8] to find the first parameter, regardless of how many moves in and out of the stack in the function.
The execution of the function Foo may also invoke other functions and even invoke Foo itself recursively. However, as long as the EBP registers are restored upon return of these sub-invocations, the actual parameters, local variables and temporary storage can continue to be accessed using EBP plus offsets. action before the callee returnsBefore the program control is returned to the caller, the callee foo must first store the return value in the EAX register. As we have discussed earlier, when the return value occupies more than 4 or 8 bytes, the address of the variable that receives the return value is passed to the function as an additional pointer parameter, and the function itself does not need to return a value. In this case, it is called this directly copies the return value directly to the receiving address via a memory copy, thereby eliminating the transfer of a pass through the stack.
Second, Foo must restore the values of the Ebx,esi and EDI registers. If these registers are modified, as we said earlier, we will press their original values into the stack at the start of Foo execution. If the ESP register points to the correct location shown in 4, the original value of the register can be stacked and restored. It can be seen how important it is to keep track of ESP correctly during the execution of the Foo function ———— that is, the number of times the stack and stack operations must be balanced.
After these two steps, we no longer need the local variables and temporary storage of Foo, we can eliminate the stack frame by the following instruction:
mov esp, EBP
Pop EBP
The result is that the contents of the stack are exactly the same as in the stack shown in Figure 2. You can now execute the return instruction. The return address is ejected from the stack and assigned to the EIP register. As shown in stack 5:| |
+-------------------------+
esp==>| Actual parameter # |
+-------------------------+
| Actual parameter # |
+-------------------------+
| Actual parameter # # |
+-------------------------+
| Caller-Saved Register field |
| Eax,ecx and edx (on request) |
+=========================+
| :            |
ebp==>|            . |

Figure 5

The i386 instruction set has a "leave" directive that is identical to the actions of the Mov and pop instructions mentioned above. Therefore, the C function usually ends with such an instruction:
Leave
Ret

the action of the caller after the returnAfter the control of the program is returned to the caller (the main in our example), it is shown in stack 5. At this point, the arguments passed to Foo are usually no longer needed. We can eject the stack with 3 parameters, which can be achieved by adding a stack pointer of 12 (= 3 4 bytes):
Add ESP, 12
If the values of the EAX,ECX and edx registers are stored in the stack before the function call, the caller main function can now eject them.   After this action, the top of the stack goes back to where we started the entire function call process, which is the position of the thick line in Figure 2-5. Forwarding Address: http://hubeihuyanwei.blog.163.com/blog/static/28205284200821873911607/+++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

function call stack (GO)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.