如何通过调用和ret在程序中更改堆栈指针 [英] How is the stack pointer changed in this program with call and ret
问题描述
我的问题与上下文更改时似乎发生在行之间的动作有关,尤其是与RSP
和RBP
有关.
My questions pertain to the actions that seem to happen between the line when context is changed especially concerning RSP
and RBP
.
给出这个非常简单的程序:
Given this very simple program:
Reading symbols from ./function_call...done.
(gdb) disass main
Dump of assembler code for function main:
0x00000000004004d6 <+0>: push rbp
0x00000000004004d7 <+1>: mov rbp,rsp
0x00000000004004da <+4>: mov esi,0x2
0x00000000004004df <+9>: mov edi,0x1
0x00000000004004e4 <+14>: call 0x4004b6 <add_and_7>
0x00000000004004e9 <+19>: mov eax,0x0
0x00000000004004ee <+24>: pop rbp
0x00000000004004ef <+25>: ret
End of assembler dump.
(gdb) disass add_and_7
Dump of assembler code for function add_and_7:
0x00000000004004b6 <+0>: push rbp
0x00000000004004b7 <+1>: mov rbp,rsp
0x00000000004004ba <+4>: mov DWORD PTR [rbp-0x14],edi
0x00000000004004bd <+7>: mov DWORD PTR [rbp-0x18],esi
0x00000000004004c0 <+10>: mov DWORD PTR [rbp-0x4],0x7
0x00000000004004c7 <+17>: mov edx,DWORD PTR [rbp-0x14]
0x00000000004004ca <+20>: mov eax,DWORD PTR [rbp-0x18]
0x00000000004004cd <+23>: add edx,eax
0x00000000004004cf <+25>: mov eax,DWORD PTR [rbp-0x4]
0x00000000004004d2 <+28>: add eax,edx
0x00000000004004d4 <+30>: pop rbp
0x00000000004004d5 <+31>: ret
End of assembler dump.
(gdb) list
1 int add_and_7( int num1, int num2 ) {
2 int seven = 7;
3 return num1 + num2 + seven;
4 }
5
6 int main() {
7 add_and_7( 1, 2 );
8 return 0;
9 }
所有功能都以push rbp
开始,据我所知,它会将父上下文保存到堆栈中.父函数如何知道如何重建自身? call
和ret
是否已内置必要的步骤?
All functions start off with push rbp
which I as I understand it is preserving the parent context onto the stack. How does the parent function know how to rebuild itself? Are the necessary steps built into call
and ret
?
然后,rsp
始终移至rbp
.如我所读,这会将新的堆栈基设置为在当前函数的上下文中.我似乎无法弄清楚是什么时候或如何将堆栈指针设置到该位置的.我最好的猜测是汇编函数调用会执行此操作,这是怎么回事?
Then the rsp
is always moved to rbp
. As I have read this sets the new stack base to be in the context of the current function. What I can't seem to figure out is when or how stack pointer was set to that point in the first place. My best guess is the assembly function call does this, is that whats happening?
最后,当方法返回时,似乎eax
是用于父函数利用其子函数返回的寄存器. eax
是否明确用于此目的?或者这仅仅是我的编译器和体系结构的约定?
Lastly when a method returns it seems like eax
is the register that is used for the parent function to utilize the return of its child function. Is eax
explicitly used for this or is this just a convention with my compiler and architecture?
推荐答案
父函数如何知道如何重建自身?呼叫和退回中是否已内置必要的步骤?
How does the parent function know how to rebuild itself ? Are the necessary steps built into call and ret?
在调用函数之前,将保存寄存器的当前状态以及返回地址. call
指令跳转到被调用函数开始的特定地址.返回地址被压入堆栈.当被调用的函数返回时,ret
指令会弹出先前推送的返回地址并转到该位置.
Before calling a function, current status of registers are saved, as well as the return address. call
instruction jumps to particular address, where the called function begins. The return address is pushed onto stack. When called function returns, ret
instruction pops previously pushed return address and goes to that location.
然后将rsp始终移至rbp
Then the rsp is always moved to rbp
rbp先前已被压入堆栈,以便能够从调用者的函数中恢复rbp的值.然后,将rsp移至rbp,以为被调用者函数创建一个新的堆栈框架.新的基本指针已设置.因此,当前,rbp和rsp指向相同的地址.如果还有其他push
指令,则会自动调整esp.完成功能后,pop ebp
指令将恢复先前压入的堆栈基指针地址.
rbp is previously pushed onto stack to be able to restore rbp's value from caller's function. Then, rsp is moved to rbp to create a new stack frame for callee function. The new base pointer has been set up. So currently, rbp and rsp points to the same addresses. If there are other push
instructions, esp is automatically adjusted. When function is done, the pop ebp
instruction restores previously pushed stack base pointer address.
这篇关于如何通过调用和ret在程序中更改堆栈指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!