Assembly 使用call和ret在该程序中如何更改堆栈指针

Assembly 使用call和ret在该程序中如何更改堆栈指针,assembly,x86,calling-convention,Assembly,X86,Calling Convention,我的问题与上下文发生变化时在两行之间似乎发生的行为有关,特别是关于RSP和RBP 考虑到这个非常简单的程序: 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
RBP

考虑到这个非常简单的程序:

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   }
从./function\u调用读取符号…完成。
(gdb)disass main
主功能的汇编程序代码转储:
0x0000000000404D6:推送rbp
0x0000000000404D7:mov rbp,rsp
0x0000000000404DA:mov esi,0x2
0x0000000000404DF:mov edi,0x1
0x0000000000404E4:调用0x4004b6
0x00000000004004e9:mov eax,0x0
0x0000000000404EE:pop rbp
0x00000000004004ef:ret
汇编程序转储结束。
(gdb)disass add_和_7
函数add_和_7的汇编程序代码转储:
0x0000000000404B6:推送rbp
0x0000000000404B7:mov rbp,rsp
0x0000000000404BA:mov DWORD PTR[rbp-0x14],edi
0x0000000000404BD:mov DWORD PTR[rbp-0x18],esi
0x0000000000404C0:mov DWORD PTR[rbp-0x4],0x7
0x0000000000404C7:mov edx,DWORD PTR[rbp-0x14]
0x0000000000404CA:mov eax,DWORD PTR[rbp-0x18]
0x00000000004004cd:添加edx、eax
0x000000000004004CF:mov eax,DWORD PTR[rbp-0x4]
0x0000000000404D2:添加eax、edx
0x0000000000404044:pop rbp
0x0000000000404D5:ret
汇编程序转储结束。
(gdb)清单
1整数加上整数和整数7(整数m1,整数m2){
2.7=7;
3返回num1+num2+7;
4   }
5.
6 int main(){
7添加_和_7(1,2);
8返回0;
9   }
所有函数都以push
rbp
开始,据我所知,它将父上下文保存到堆栈上。父函数如何知道如何重建自身?
call
ret
中是否内置了必要的步骤

然后,
rsp
始终移动到
rbp
。正如我所读到的,它将新的堆栈基设置为当前函数的上下文中。我似乎不知道堆栈指针最初是何时或如何设置到该点的。我最好的猜测是汇编函数调用会这样做,这是怎么回事


最后,当一个方法返回时,
eax
似乎是父函数用来利用其子函数返回的寄存器。
eax
是否明确用于此目的,或者这只是我的编译器和体系结构的惯例?

按下并弹出修改堆栈指针-
SP

调用推送标志-状态寄存器以及RA-返回地址。 Ret弹出标志弹出并跳转到返回地址

正如rkhb所说,保持某些寄存器原样的需要来自调用约定

父函数如何知道如何重建自身?call和ret中是否内置了必要的步骤

在调用函数之前,将保存寄存器的当前状态以及返回地址<代码>调用指令跳转到被调用函数开始的特定地址。返回地址被推送到堆栈上。当被调用的函数返回时,
ret
指令弹出先前推送的返回地址并转到该位置

然后rsp始终移动到rbp


rbp之前被推到堆栈上,以便能够从调用方的函数恢复rbp的值。然后,rsp被移动到rbp,为被调用函数创建一个新的堆栈帧。已设置新的基指针。所以目前,rbp和rsp指向相同的地址。如果有其他
push
指令,esp将自动调整。函数完成后,
pop ebp
指令将恢复以前推送的堆栈基指针地址。

Google表示“调用约定”。程序员或编译器必须知道函数将改变什么,并相应地编写程序。非常感谢您的帮助!最需要的是正确的搜索词。不过,如果有人想阐述更多的知识,那就越有趣。我认为你的拼写错误
RBP
永远不会移动到
RSP
。call/ret请勿触摸标志。也许您正在考虑
int0x80
/
iret