assembly - 设置 RBP 有不同的方法吗?为什么 Windows x64 不将 RBP 指向返回地址正下方的已保存 RBP?

标签 assembly x86-64 masm calling-convention stack-frame

MSDN附上这张图来描述如何在x64 fastcall调用约定中使用堆栈: enter image description here

我的问题是: 为什么框架指针设置在箭头所示的位置?毕竟我们原本想要的after call:

push rbp
mov rbp, rsp
; allocate stack memory for local vars and for register and stack parameter area
; function's work
mov rsp, rbp
pop rbp
ret

我们通过以下方式访问 B 函数的参数区域:

mov [rbp + 10h], rcx
mov [rbp + 18h], rdx
mov [rbp + 20h], r8
mov [rbp + 28h], r9

本地变量:

mov [rbp - 8h], 1
mov [rbp - 10h],2
; etc

并通过以下方式访问参数区域以供将来使用:

; rcx rdx r8 r8 for 1-4
mov [rsp + 20h], 1 ; fifth arg, first stack arg
etc

是这样还是我搞砸了?

最佳答案

example on Godbolt MSVC19.14 -O2 似乎确认 MSVC 确实将帧指针放在那里,而不是相对于返回地址的固定位置。因此它必须依赖堆栈展开元数据,而不可能回退到传统的帧指针链表跟踪。

通常(没有命令行选项)MSVC 不使用 RBP 作为帧指针,甚至在调试版本中也不使用,至少对于简单的函数而言。仅在使用 alloca 的函数中,或者可能是其他原因。

x86-64 System V ABI(用于除 Windows 之外的所有系统)确实将 RBP 放在您期望的位置,即返回地址正下方的传统位置(如果您将其用作传统帧指针)。 (gcc/clang 仅在没有优化的情况下执行此操作,或者针对代码大小进行优化,或者在分配或过度对齐堆栈时执行此操作。

将 RBP 放置在更靠近您可能想要访问的空间中间的位置,可以增加使用 [rbp + disp8] 可以到达的空间量,它在寻址模式。 x86-64 System V 有一个 128 字节的红色区域(低于 RSP),因此选择了 128 字节;访问 RSP 及以上 128 字节的本地和 arg 空间,以及以下 128 字节。访问距离寄存器较远的位置需要 [reg+disp32],这是一个 4 字节偏移量,因此每条访问堆栈空间的指令需要 3 个额外字节。

(很少有很多字节的堆栈参数,特别是在 Windows x64 中,它通过引用传递大型结构,而不是通过堆栈上的值。因此每个参数恰好占用一个 8 字节堆栈槽,从而使可变参数函数变得简单。)

关于assembly - 设置 RBP 有不同的方法吗?为什么 Windows x64 不将 RBP 指向返回地址正下方的已保存 RBP?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75722486/

相关文章:

使用内联汇编 ia32 将指针更改为包含在结构体中的数组

performance - 我可以在 x86/x86_64 上自动递增 16 位计数器吗?

c - 如何从 malloc 区域执行一段代码

assembly - ASM 如何知道算术运算是有符号的还是无符号的?

assembly - 错误 A2008 : syntax error :

c - 函数 "main"的代码在目标文件中的哪里开始?

assembly - NEON ASM 代码运行速度比 C 代码慢很多?

c++ - 如何达到每个周期 4 FLOP 的理论最大值?

c++ - 用192/256位整数求和无符号64位整数 vector 的点积的最快方法?

C++函数调用汇编模块