The C language function is as follows
int bar (int c, int d)
{
int e = c + D;
return e;
}
int foo (int a, int b)
{return
bar (A, b);
}
int main (void)
{
foo (2, 5);
return 0;
}
Let's trace the execution of the function from the assembly's angle, main's corresponding assembler function is as follows:
Dump of assembler code for function main: {
0x0000000000400529 <+0>: push % RBP
0x000000000040052a <+1>: e5 mov %rsp,%rbp foo (2, 5);
=> 0x000000000040052d <+4>: $0x5,%esi mov
0x0000000000400532 <+9>:< C30/>BF mov $0x2,%edi
0x0000000000400537 <+14>: e8 CE ff FF FF CALLQ 0x40050a <foo>
return 0;
0x000000000040053c <+19>: b8 mov $0x0,%eax }
0x0000000000400541 <+24>: 5d pop %rbp
0x0000000000400542 <+25>: c3 Retq
end of Assembler dump.
Just entered the main function, and when the call stack is established, the corresponding register state is:
(GDB) Info registers RBP RSP
RBP 0x7fffffffdc80 0x7fffffffdc80
RSP 0x7fffffffdc80 0x7fffffffdc80
After executing three instructions (SI 3), after entering the Foo function, the assembly instructions are as follows:
dump of assembler code for function foo:8 {=> 0x000000000040050a <+0>: 55 Push%RBP 0x000000000040050b <+1>: e5 mov%rsp,%rbp 0x000000000040050e; $0X8,%RSP EC-sub-0x0000000000400512 <+8>: 7d FC mov%edi,-0x4 (%RBP) 0x00000
00000400515 <+11>: F8 mov%esi,-0x8 (%RBP) 9 return bar (A, b); 0x0000000000400518 <+14>: 8b F8 mov-0x8 (%RBP),%edx 0x000000000040051b <+17>: 8b FC mov-0x4 (%RBP),%eax 0x000000000040051e <+20>: d6 mov%edx,%esi 0x0000000000400520 GT: C7 mov%eax,%edi 0x0000000000400522 <+24>: E8 c9 FF FF FF CALLQ 0x4004f0 <bar> 10 0x0000000000400527 <+29>: C9 leaveq 0x0000000000400528 <+30>: C3 Retq End of Assemb Ler dump.
The function stack at this point is as follows: At this point, the stack base address has not been switched, but the top address of the stack has changed (because call will put the return address in main in the stack)
(GDB) Info registers RBP RSP
RBP 0x7fffffffdc80 0x7fffffffdc80
RSP 0x7fffffffdc78 0x7fffffffdc78
In the next two sentences, a stack of new functions is established; The 50e~515 is the process of obtaining a function argument, which is equivalent to push EDI, push esi. The instruction executes to 0518 lines, the state of the Register
(GDB) Info registers RBP RSP
RBP 0x7fffffffdc70 0x7fffffffdc70
RSP 0x7fffffffdc68 0x7fffffffdc68
Enter the command Si 9, into the new function call stack.
(gdb) disassemble/rm
Dump of assembler code for function bar:
3 {
=> 0x00000000004004f0 <+0>:< c4/>55 push %rbp
0x00000000004004f1 <+1>: e5 mov
%rsp,%rbp 0x00000000004004f4 <+4>: 7d EC mov %edi,-0x14 (%RBP)
0x00000000004004f7 <+7>: E8 mov %esi,-0x18 (%RBP)
4 int e = c + D;
0X00000000004004FA <+10>: 8b E8 mov -0x18 (%RBP),%eax 0x00000000004004fd
;: 8b EC mov -0x14 (%RBP),%edx
0x0000000000400500 <+16>: d0 Add %edx,% EAX
0x0000000000400502 <+18>: The FC mov %eax,-0x4 (%RBP) 5 return e;
0x0000000000400505 <+21>: 8b FC mov -0x4 (%RBP),%eax
6 }
0x0000000000400508 <+24>: 5d pop %rbp
0x0000000000400509 <+25>: c3 Retq
end of Assembler dump.
The stack state at this point is:
(GDB) Info registers RBP RSP
RBP 0x7fffffffdc70 0x7fffffffdc70
RSP 0X7FFFFFFFDC60 0X7FFFFFFFDC60
At this point f0~f1 is still creating a new function call stack. Note that the next few lines do not extend the function stack because there is no deeper function to call. (In addition, and the call to the fun function, here are more than 508 corresponding pop operations, in fact, in the fun function, is the leave operation, which is equivalent to MOV esp,ebp; pop ebp.) Why not pass the value of EBP to ESP? Because EBP and ESP are the same)
The function of enter is quite ==push EBP and mov ebp,esp
We are familiar with the following two sentences. The beginning of the function is usually these two sentences
Leave function is quite ==mov esp,ebp and pop Ebp