content
Creation and destruction of function stack frames
First of all, we must understand that each function call needs to open up a space on the stack area
Addition is performed, but where are x, y?
The addition is complete, eax becomes 30
Do you have any doubts? When return z returns, isn't z destroyed? How can we bring the result back?
How is the return value brought back?
1. How are local variables created?
2. Why the uninitialized value of the local variable is a random value
3. How do functions pass parameters? What is the order in which the parameters are passed?
4. What is the relationship between formal parameters and actual parameters?
5. How is the function call done?
6. How is the result of the function call returned?
Note: The following environment is based on vs2013 for display
Creation and destruction of function stack frames
There should be many doubts in the process of learning, here are a few examples:
· How are local variables created?
Why is the uninitialized value of a local variable a random value?
How is the function passed 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 does the function return after the end of the call?
Next, I will take you through the problem
1. Register
The storage system of the computer, in which the registers are integrated into the cpu
The registers we will encounter below are: eax, ebx, ecx, edx
Two of the key registers: ebp, esp. These two registers store the address, which is used to maintain the function stack frame
First of all, we must understand that each function call needs to open up a space on the stack area
int Add(int x, int y)
{
return x + y;
}
int main()
{
int a = 10;
int b = 20;
int c = 0;
c = Add(a, b);
return 0;
}
Start calling the main function, allocate space for the main function, and which function is called, ebp and esp will maintain the function stack frame of that function.
I want to call the Add function, ebp and esp run to maintain the Add function, the space between ebp and esp is the space opened up for the Add function call, which is called the function stack frame
Since the usage of the stack area is to use the high address first, then use the low address, and when placing data, put the data from the top to the bottom, so esp can be understood as the top pointer of the stack, and ebp is understood as the low pointer of the stack.
Have you ever wondered, the main function is called, but who is calling the main function?
Go down and execute the code, you can see __tmainCRTStartup, this function calls the main function internally, indicating that the main function is also called by others, and __tmainCRTStartup is called by tmainCRTStartup
The space for these two functions should also be allocated before the main function
The outline is probably like this, how to call the next research
into disassembly
The main function is also called by others, and the __tmainCRTStartup that calls the main function has already created a space
Disassemble the first sentence (push: put an element on the top of the stack) (pop: delete an element from the top of the stack)
ebp stores the low address of the __tmainCRTStartup stack, push is called pushing the stack, putting elements in the stack
After push, the address of esp should also be changed
monitor
watch esp and ebp, this is the initial address
When we start to push, the address is decreased by 4
RAM
It can be seen that ebp is indeed pushed in by push
Disassemble the second sentence
The mov instruction is to assign the following value to the front, and esp to ebp
Disassemble the third sentence
sub is a subtraction, subtract 0E4h from esp, and convert 0E4h to 228 in decimal
Monitoring (esp address changes, opening up a large space for the main function)
Disassemble the fourth, fifth, and sixth sentences
Disassemble the seventh, eighth, ninth, and tenth sentences, lea =load effective address (load effective address)
Load the following valid address into edi, this sentence is not very easy to observe, after we display the symbol name, it becomes ebp-0E4h
mov puts 39h into ecx. Put the value of 0CCCCCCCCch into eax
Rep stos means that the data content of so many space dwords starting from the position of edi and going down 39h times should be changed to 0CCCCCCCCch.
A word is two bytes and a dword is four bytes
From edi to ebp stop, all the space contents are initialized to CCCCCCCC
memory monitoring
At this point, the main function stack frame has been opened, and the code execution is officially started below.
mov, put 0Ah (10 in decimal) in the position of ebp-8, we think that CCCCCCCC is four bytes, and the space opened up for a is the space from ebp to ebp-8
1. We assign values when creating variables. If the variables are created without assignment, the default is CCCCCCCC.
The reason why the printing is hot is because it is a random value CCCCCCCC, which is not initialized. Different compilers may put different values in it.
memory monitoring a
0a 00 00 00 is because this compiler is little endian
memory monitoringb
14h is hexadecimal, converted to decimal is 20, leaving two integer positions empty
memory monitor c
It's a difference of two positions
function call
Function calls need to pass parameters. Are the following two actions passing parameters?
mov, put ebp-14h (that is, b) in eax. push->eax, push the stack
mov, put ebp-8 (that is, a) in ecx. push->ecx, push the stack
The answer is indeed passing
The call instruction is to call the function, now we remember the address of the call instruction
After executing the call instruction, the address of AA8 is 00 c2 14 50
The next address of the call instruction is pushed on the stack, why should I remember this address? Do not worry
The Add function is called immediately after the call is called. After the Add function is called, it needs to return. I need to return to the next instruction of the call instruction (the call instruction is executed)
Enter inside the function (the order of operations in the first few steps is the same as the previous main function)
Prepare stack frame for Add function
First push ebp (at this time ebp is still maintaining the main function stack low), push the ebp value to the top
Memory monitoring (ebp is pushed on the stack at the address of the next instruction under the call instruction)
Give the value of esp to ebp
esp, 0CCh is allocating function stack frame space for this call to Add
function load address
lea loads the address [ebp+FFFFFF34h] into edi, mov puts 33h into ecx, and then puts the value of 0XCCCCCCCCh into eax
rep -> all positions from edi down to ebp are initialized to 0XCCCCCCCCh
perform computing tasks
put 0 in the position of ebp-8
Addition is performed, but where are x, y?
Put the value of ebp+8 into eax, ebp+8 finds ecx
ecx is pushed on the stack, we can call him a', and eax is b'
Put the value of ebp+8 into eax, and then add the value of ebp+0ch into eax
The addition is complete, eax becomes 30
How did the formal parameters come about? Are we actively creating parameters?
No, because we passed the parameters when we first called the function below
Passing parameters through the mov push mov push instruction
push pushes b first, then a. c=Add(a, b) The b passed first, the passed a, the parameters are passed from right to left
The formal parameters are not created inside the Add function, but come back to find the space data on the stack for calculation
We often say that a formal parameter is a zero-time copy of an actual parameter. This sentence is completely true. Changing the formal parameter does not affect the actual parameter.
function return
Do you have any doubts? When return z returns, isn't z destroyed? How can we bring the result back?
return z means to put the value of ebp-8 into eax, which is a register. Registers are not destroyed when the program exits
ebp-8 position is z
Pop three sentences, pop, pop the top element of the stack and put it in edi, every time esp is popped, ++ goes down
mov assigns ebp to esp, esp does not point to the top of the stack, but points to the location of ebp (recycling the stack frame of the Add function)
Pop it, the stack low address of the ebp-main function was stored before (in order to prevent the stack low pointer from being found after the function is destroyed), ebp returns to the main function stack low address
At this point, after pop pops up, ebp returns to the main function stack low
ret instruction, esp returns to the address of 00C21450, which is the address of the next instruction of the call instruction, and continues to execute from the next instruction of the call instruction (not only to go out, but also to come back)
Add 8 to esp, skip parameters a, b, and destroy parameters a and b
Put the value of eax into ebp-20h, the position of ebp-20h is the space of c, and the value of eax is sum: 30
How is the return value brought back?
is that we first put it in the eax register, when we return to the function and put it in the local variable c
The Add function is destroyed, and the main function is destroyed. This is the process of creating and destroying the function stack frame.
Back to the original question
1. How are local variables created?
First, allocate the stack frame space for the function. After the stack frame space has initialized a part of the space, allocate a little space for my local variables in the stack frame.
2. Why the uninitialized value of the local variable is a random value
Because the random value is put in by the compiler, such as CCCCCCCC, if it is initialized, the random value will be overwritten
3. How do functions pass parameters? What is the order in which the parameters are passed?
When we haven't called the function, we have already pushed the stack from right to left. When we enter the formal parameter function, in the Add function, we find our formal parameter through the offset of the pointer.
4. What is the relationship between formal parameters and actual parameters?
The space created by the formal parameter when it is pushed on the stack is the same as the actual parameter value, the space is independent, and the formal parameter is a zero-time copy of the actual parameter. This sentence is completely correct. Changing the formal parameter does not affect the actual parameter.
5. How is the function call done?
The above summarizes clearly
6. How is the result of the function call returned?
Before the call, remember the address of the next instruction of the call instruction, and store the stack frame of the previous function of the ebp calling function. When the function returns after the function call, pop up the ebp to find the ebp of the original previous function. The pointer goes down to find the esp address
The return value is brought back through a register
The static variables created inside the function are opened globally. Today, we draw on the stack area.