Function call process - function stack frame

function stack frame

  • The function is an indispensable part of the program. The operation of the entire program is almost completed by calling each other between functions. Our main function, the printf function, and the functions we write ourselves during programming. Our program profile is efficient.

So how exactly is a function called in memory? How to realize the various functions of the function?

In-depth analysis

Look at this piece of code

#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 ret = Add(a, b); 
    printf("ret = %d\n", ret); 
    return 0;
}

This simple code implements addition, where the Add function implements the addition, the parameters are two integer variables, and the Add function is called by the main function.

bedding

1.
Make such a foreshadowing before parsing:
our main function is actually called by other functions

Taking vs2008 as an example, after the code is written, press F10 to start the process step by step, you can see that there is a stack frame above it and click it, as shown in the figure
write picture description here
- the main function is called by the __tmainCRTStartup(void) function, and this function is called by the mainCRTStartup(void) function. ) function call. Click to view the source code.

2.
The addresses in memory are maintained by registers. The main registers are

  • eax , ebx , ecx , edx and the main ones used this time ebp(low address for espopening up space), (high address for opening up space).
  • After creating a space for a function in memory, ebp stores the high address of this space, and esp stores the low address of this space.
  • Functions and local variables are opened in the stack space, and the stack holes are used from high addresses to low addresses.

write picture description here

Disassembly Analysis

Now we start to study the calling process of the function, that is, after pressing F10 just now, we stay in the main function step by step, as shown in the first picture.

Right-click next to the main function to go to disassembly, then find in the main toolbar -> Debug - Window - click on Monitoring and Memory.

Find the addresses of ebp and esp in the monitoring bar, and also find them in memory for later observation.

  • experience

write picture description here

Continue to step through by pressing F10

  • push pushes an address to the top of the stack, mov moves, and sub opens up space.
  • Press F10 to execute down, and these steps are analyzed by the figure.

write picture description here

  • Continue to press three registers three times in a row
  • lea finds a valid address
  • The rep is repeated, and the opened space is all initialized ascc cc cc cc
    write picture description here

  • The address here has changed uniformly, because the debugging was interrupted just now, but the effect is the same, everyone pay attention

write picture description here

  • Then it is initialized for a and b
    write picture description here

- The two pushes before the call are to push the a and b parameters into the stack
- Continue down, when you encounter a call, press F11, and the call is to call the call function
- Then you can see that ebp is pushed to the top of the stack, The ebp here is the starting address of main, which is used to return to main after the function is called.

write picture description here

write picture description here

  • This is similar to the previous main process

write picture description here

  • After the addition is completed, put the value of z into eax to bring it back to the main function ret
  • The space of the Add function will be released
    - the subsequent pop is popped into the corresponding register

  • Finally, pop ebp is to return the address of the previous main function to ebp so that the area maintained by the register returns to the main function

Then execute the printf function and finally end the main function. The program ends, and the calling process of the function in the memory is like this

effect

After understanding the calling process of functions in memory, does a program appear very transparent in front of our eyes?
Then what is the role of understanding these, and where is his importance?
We experience it through such a piece of code.

void fun()
{
int tmp = 10;
int *p = (int *)(*(&tmp+1)); 
*(p-1) = 20;
}
int main() {
int a =0;
fun();
printf("a = %d\n",a); return 0;
}
  • Try to determine what the output is?
  • The answer is 20 (guessable) but we need to know his principle

Please refer to the third last picture to understand

int *p = (int *)(*(&tmp+1));  
//tmp的地址加一指向了压入的ebp(main的地址),将这个地址给指针p,p就指向了main的开始。
*(p-1) = 20;
//p的地址减1,指向了为a开辟的空间从而改变了a的值。

Thus we can see the importance of the function stack frame

Thank you for reading the welcome message~

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326832022&siteId=291194637