Reprinted from Address: http://blog.csdn.net/zsy2020314/article/details/9429707
Today suddenly want to analyze the function in the process of mutual invocation of the stack frame changes, or to try to use a clearer idea to describe the process, the C function call principle of understanding is very important.
1. About Stacks
First, it must be clear that a point is also very important, the stack is growing downward, the so-called downward growth refers to the memory high address-low address path extension, then it is obvious that the stack has a stack bottom and the top of the stack, then the top of the stack is lower than the bottom of the stack. For the CPU of the x86 system,
---> Register EBP (base pointer) can be called "frame pointer" or "base address pointer", in fact the semantics are the same.
---> Register ESP (stack pointer) can be called a "stack pointer".
To know is:
---> EBP always points to the beginning of the stack frame, which is the bottom of the stack, before being changed, so the purpose of EBP is to address it in the stack.
---> ESP moves with the data into and out of the stack, that is, esp always points to the top of the stack.
See, assuming function A calls function B, we call the A function "caller", and the B function as "callee" the function call procedure can be described as follows:
(1) The base address (EBP) of the stack of the caller (A) is first put into the stack to hold the information of the previous task.
(2) The value of the stack top pointer (ESP) of the caller (A) is then assigned to EBP as the new base address (that is, the bottom of the callee B's stack).
(3) Then at this base (the bottom of the stack of the callee b), the corresponding space is used as the stack space of the callee B (usually the sub instruction).
(4) After function B is returned, the EBP from the current stack frame reverts to the top of the stack (ESP) of the caller A, so that the top of the stack is restored before the function B is called, and then caller A then pops back from the top of the restored stack (this can be done because the value is pressed into the stack before the function call) In this way, both EBP and ESP revert to the position before function B is called, which is the state before the call to the stack recovery function B.
This process is done through two instructions in the T/T assembly, namely:
Leave
Ret
The more straightforward point of these two directives is the equivalent of:
mov%ebp,%ESP
Pop%EBP
2. For a simple example, see function calls from a compilation perspective
2.1 Create a simple program with the program file named Main.c
Developing the test environment:
Ubuntu 12.04
GCC version: 4.6.3 (Ubuntu/linaro 4.6.3-1ubuntu5) (Ubuntu comes with it)
[CPP]View PlainCopy
- <span style="FONT-SIZE:18PX;" >/*MAIN.C Code: */
- void swap (int *a,int *b)
- {
- int C;
- c = *a;
- *a = *b;
- *b = C;
- }
- int main (void)
- {
- int A;
- int b;
- int ret;
- A = 16;
- b = 64;
- ret = 0;
- Swap (&A,&B);
- ret = a-B;
- return ret;
- }</span>
2.2 Compiling
#gcc-G-O main main.c
#objdump-D main > Main.dump
#gcc-wall-s-o main.s main.c
So you can see MAIN.S can also see main.dump, here we choose to use Main.dump.
Intercept the key part, that is, _start, swap, Main, why there is _start, because the elf format of the entrance is actually _start instead of main (). The following figure shows the structure of the stack space before and after the main () function call Swap (). The number on the right represents the offset byte number of the relative frame pointer. After we use GDB debugging, we will find that the stack changes are consistent.
(!!! Note that because of the stack alignment, the compiler may have unused memory addresses when allocating stack space, and these unused memory addresses are not represented, so they can only be used to understand the function stack frame structure!! Specific stack memory content to the following GDB debugging information prevail!!! )
Here is the code comment for _start in Main.dump, which is more important than the stack alignment of the ESP, which is 16-byte aligned, noting that the number on the right side of the left line number is the instruction address of the 0x8048300 class.
The following is the assembly code for the Swap () function and the main () function in Main.dump, with detailed comments next to the code.
Here we use GDB to debug the MAIN.C code, using the main image just compiled.
# gdb Start (start gdb)
# (GDB) file main (load image file)
# (GDB) break main (set main () to a breakpoint, note that GDB does not set the breakpoint to the first instruction in main, but instead sets the adjustment stack pointer to the local variable reserve space)
# (GDB) run (Run program)
# (GDB) Stepi (single step, not familiar with GDB's children's shoes to note that the Stepi command after the execution of the source code line or instruction address, are going to execute the instructions, not just executed instructions! )
C Function Call procedure principle and function stack frame analysis