[C language] Creation and destruction of function stack frames

Hello everyone, I am deep fish~

Table of contents

1. Register

2. Stack area

 3. Creation of function stack frame

1. Open up a stack frame for the main function 

2. Create variables in the main function

3. Preparations before calling the Add function

 4. Create a stack frame for the Add function

 5. Create variables and operate in the Add function

Fourth, the destruction of the function stack frame

6. Destruction of Add function stack frame

7. Return to the main function stack frame


[Preface] During the early study, we may have a lot of confusion

for example:

How are local variables created?

· Why are the values ​​of local variables random?

How does the function pass parameters? What is the order of passing parameters?

What is the relationship between formal parameters and actual parameters?

· How is the function call done?

How to return after the function call ends ?

Knowing the creation and destruction of function stack frames can solve these problems. Learning this knowledge is actually practicing your own internal skills, and you can also understand more knowledge in the later stage

 【Into the title】:

The environment used in this part is vs2013, because the more advanced the compiler, the harder it is to learn and observe.

At the same time, under different compilers, the creation of stack frames during function calls is slightly different, and the details depend on the implementation of the compiler.

1. Register

Any instruction in the computer is run on the CPU, but the CPU itself is only responsible for calculation and not for storage. Data is generally stored in memory and registers ( storage of the most common data )

Registers include eax, ebx, ecx, edx, and the key points of this article, ebp and esp

The ebp (stack bottom pointer), esp (stack top pointer) store addresses in these two registers, and these two addresses are used to maintain the function stack frame

2. Stack area

Every function call must create a space in the stack area

So what is the stack area?

Memory four-zone model:

Stack area stack: automatically allocated and released by the compiler , storing function parameter values ​​(formal parameters and return values), and local variable values

The habit of using the stack area is to use the high address first, and then use the low address . The space is continuously consumed upwards. If the space is used again, the data (stack top) needs to be placed on the top. When the function is called, esp maintains the stack top , ebp What is maintained is the bottom of the stack

[Reminder]: Here is just an example of the space opened by the main function, esp, ebp not only maintain the main function, but also other functions

[Q] : So what is a stack frame? 

 [Stack frame]: Use registers to access local variables, function parameter values, etc., to represent the function call record of the program

[Supplement]: What are push and pop?

push: push the stack: put elements from the top of the stack

pop: out of the stack: delete elements from the top of the stack 

 3. Creation of function stack frame

Code: In order to demonstrate this process more clearly, the code is written in sufficient detail

#include<stdio.h>
int Add(int x, int y)
{
	int z = 0;
	z = x + y;
	return z;
}
int main()
{
	int a = 10;
	int b = 20;
	int c = 0;

	c = Add(a, b);

	printf("%d\n", c);
	return 0;
}

Press F10 for step-by-step debugging, press F11 for the next step, and then open Debug-Window-Call Stack, as we press F11 step by step to debug statement by statement, and finally find that jumping from return 0 to another interface is actually the main function the calling function

 In fact, the main() function is called by the _tmainCRTStartup function , and the _tmainCRTStartup function is called by the mainCRTStartup function

Next, the process of creating and destroying the function stack frame will be demonstrated step by step

1. Open up a stack frame for the main function 

<0> Before calling the main function : esp and ebp maintain the _tmainCRTStartup function at the top and bottom of the stack respectively

<1> : Push the value of ebp onto the stack , and the value of esp decreases to the lower address, pointing to the upper end of esp

<2> : Assign the value of esp to ebp, and both point to esp at the same time                         

<3> : Subtract 0E4h from esp and save it in esp, that is, esp moves 0E4h bytes to the lower address (that is, start to open up space for the main function) 

<4> : Push the values ​​of ebx, esi, and edi into the stack respectively . Note that after each stack push, esp will move to the lower address, and finally sep will reach the top of edi

<5> : put the address of ebp minus 0E4h into edi (lea: load effective address)

                      Put 39h into ecx

                      Put 0CCCCCCCCh into eax

<6> : Assign 0CCCCCCCCh to the memory starting from edi (ebp-0E4h) repeatedly 39h times downwards (high address direction), each time assigning a double character (dword: double word) that is a four-byte space ( That is, the space opened up for the main function is all initialized to 0CCCCCCCCh)

Open up a stack frame for the main() function

                                                                                                                              

2. Create variables in the main function

Assign the initialized value to the double-character space in the memory address [ ]

eg: int a=10: put 0Ah (that is, the initialized value 10) into the space where ebp-8 is the memory address

main3

 As a result, we can see that the variables are put into the three positions and initialized. From here, we can know why the variable is a random value if it is not initialized. Because of the initialization, the variable is 0CCCCCCCCh, and this value is uncertain. 

3. Preparations before calling the Add function

<1> pass parameter b:

(1) Assign the data in the address ebp-14h (the address of b) (that is, the value of b ) to eax

(2) Push the value of eax (which is the value of b 20) onto the stack, and esp moves up (lower address)

<2>Pass parameter a:

(1) Assign the data in the address ebp-8 (the address of a) (that is, the value of a ) to ecx

(2) Push the value of ecx (which is the value of a 10) onto the stack, and esp moves upward (low address)

[Note] The parameters are passed from right to left

<3> Prepare to call the Add function:

(1) Push the address of the next instruction of the call instruction onto the stack (this step is to return to the main function according to this address after calling the custom function, and execute it downward from this address), esp up (low address )move

[Note] The stack frame range of the main function at this time: the esp at the top of the stack has reached this address, and the ebp at the bottom of the stack is still below

(2) The program enters the Add function

main5

 4. Create a stack frame for the Add function

 This step is the same as opening up a stack frame for the main function

<1>: Push the value of ebp onto the stack, esp moves up (low address)

<2>: Assign the value of esp to ebp, and both point to esp at the same time   

<3> : Subtract 0CCh from esp and save it in esp, that is, esp moves 0CCh bytes to the lower address (that is, start to open up space for the Add function) 

<4> : Push the values ​​of ebx, esi, and edi into the stack respectively. After each stack push, esp will move up (lower address), and finally sep will reach the top of edi

<5> : Put the address of ebp minus 0CCh into edi

                      Put 33h into ecx

                      Put 0CCCCCCCCh into eax

<6> : Assign 0CCCCCCCCh to the memory starting from edi (ebp-0CCh) repeatedly 33h times downwards (high address direction), each time assigning a double-character (four-byte) space (that is, opening up for the Add function The space is all initialized to 0CCCCCCCCh)

 5. Create variables and operate in the Add function

<1> Create variable z: Put 0 (the value initialized by z) into the space where ebp-8 is the memory address

<2> Perform operations:

(1) Put the data (that is, a) whose address is ebp+8 into eax

(2) Add the data in the address ebp+12 (that is, b) to eax (10 last time + 20 this time=30)

(3) Put eax into the address ebp-8 (that is, z, let z=30)

[Note] The formal parameters are not created in the custom function, but go back to find the address of the value pushed into the stack before calling the function

<3> Return z: put the data in ebp-8 (that is, 30) into eax (let eax read the value of z, so as to prevent the value of z from being lost after the function is destroyed)

Add2

Fourth, the destruction of the function stack frame

6. Destruction of Add function stack frame

<1> Pop out: edi, esi, ebx pop up the stack area respectively, and each time the stack is popped, esp moves downward (high address)

<2> Add function recycling: assign the value of ebp to esp, and the stack of the add function will be gone

<3> Pop the ebp of the main function at the top of the stack, ebp returns directly to the ebp of the main function, and at the same time esp moves down (high address) by 4 bytes

<4> Return to ret, the program automatically returns to the next line of the call instruction just now, after reading the address, esp moves down (high address) by 4 bytes

7. Return to the main function stack frame

 <1> Formal parameter x, y space is destroyed: esp+8 means esp moves down (high address) 8 bytes, and the formal parameter x, y space is also returned to the operating system

<2> Give the calculation result to c: put the value of eax (the result of Add summation) into the space whose address is ebp-20h (the address of c)

 The destruction of the main function is similar to the Add function, so I won’t elaborate too much below

【Summarize】

The above is the creation and destruction of the function stack frame. You can see that this process is very rigorous and very wonderful.

Seeing this, I believe that everyone has already answered the questions raised above. Some places are still quite difficult to understand. If you have any questions, please welcome the comment area or private message to communicate. I think the author’s writing is okay, or I have gained a little. Let's move our little hands and give me a one-click three-link, thank you very much 

Guess you like

Origin blog.csdn.net/qq_73017178/article/details/131912654