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 }
所有函数都以pushrbp
开始,据我所知,它将父上下文保存到堆栈上。父函数如何知道如何重建自身?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
?