type
status
date
slug
summary
tags
category
icon
password
栈帧
简言之,栈帧就是利用EBP(栈指针,请注意不是ESP)寄存器访问内局部变量、参数
函数返回地址等的手段。通过前面关于IA-32寄存器的学习我们知道,ESP寄存器承担着栈顶指针
进入main函数和main函数快要结束的时候rsp和rbp是怎么变化的
在进入
main
函数和快要结束 main
函数时,rsp
(栈指针寄存器)和rbp
(基指针寄存器)的变化情况如下:进入 main
函数时:
在
main
函数的开头,标准的函数序言会调整栈指针和基指针,以设置新的栈帧并保护旧的栈帧。这通常遵循以下步骤:保存旧的基指针:
◦
pushq %rbp
将当前的基指针 rbp
的值推入栈中,以便稍后恢复。设置新的基指针:
◦ movq %rsp, %rbp
将当前的栈指针 rsp
的值复制到 rbp
中。此时,rbp
的值成为新的栈帧的基地址。空间分配:
◦ subq $48, %rsp
调整栈指针 rsp
,为局部变量或其他用途分配48字节的空间。汇编代码示例:
进入 main
函数时 rsp
和 rbp
的变化:
进入之前:
◦ 假设
rsp = 0x7fffffffe0f0
◦ 假设 rbp = 0x7fffffffe100pushq %rbp
之后:
◦ rsp
会减少 8 字节(x86-64 平台),rsp = 0x7fffffffe0e8
◦ rbp
不变movq %rsp, %rbp
之后:
◦ rbp
现在指向新的栈帧基地址,rbp = 0x7fffffffe0e8subq $48, %rsp
之后:
◦ rsp
会减少 48 字节,rsp = 0x7fffffffe0b8
◦ rbp
不变快要结束 main
函数时:
在
main
函数结束前,标准的函数尾声会恢复旧的栈帧并返回调用函数。通常遵循以下步骤:恢复栈指针:
◦
addq $48, %rsp
将栈指针恢复到调用之前的位置。恢复旧的基指针:
◦ popq %rbp
从栈中弹出旧的基指针值,并恢复到 rbp
。汇编代码示例:
快要结束 main
函数时 rsp
和 rbp
的变化:
开始恢复前:
◦
rsp = 0x7fffffffe0b8
◦ rbp = 0x7fffffffe0e8addq $48, %rsp
之后:
◦ rsp
会增加 48 字节,rsp = 0x7fffffffe0e8
◦ rbp
不变popq %rbp
之后:
◦ rsp
会增加 8 字节,rsp = 0x7fffffffe0f0
◦ rbp
恢复到之前的值,假设恢复到 0x7fffffffe100
总结:
进入
main
函数时:rsp
从原位置减少 8 字节保存 rbp
,然后减少 48 字节为局部变量分配空间。rbp
从原位置设置成与 rsp
开头相同。快要结束
main
函数时:rsp
回升 48 字节,恢复到进入 main
函数时的状态。rbp
被恢复到调用者保存的旧值。这两个寄存器的变化展示了栈帧的创建和恢复过程,这是大多数函数调用遵循的标准协议。
删除栈帧&main()函数终止
- Author:Albert1x
- URL:https://albert-1x.top//article/%E6%A0%88%E5%B8%A7
- Copyright:All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!