assembly x64调用约定中前4个参数的阴影空间的用法是什么

yi0zb3m4  于 2022-11-13  发布在  其他
关注(0)|答案(1)|浏览(118)

根据https://learn.microsoft.com/en-us/cpp/build/stack-usage?view=msvc-170,调用方必须始终为4个寄存器参数分配足够的空间,即使被调用方没有那么多的参数。始终为寄存器参数分配空间,即使参数本身从未驻留在堆栈中。
4个寄存器参数的影子空间有什么用?
我对VS和G++编译的一些程序进行了反汇编,发现被调用方在一开始就把寄存器参数保存在影子空间中,比如WinMain(HINSTANCE *hInstance, HINSTANCE *hPrevInstance, char *lpCmdLine, int nCmdShow)函数在一开始就做了如下的push:

mov     [rsp+arg_18], r9d
mov     [rsp+arg_10], r8
mov     [rsp+arg_8], rdx
mov     [rsp+arg_0], rcx

为什么被调用方将寄存器参数保存在影子空间中?
如果被调用方必须将寄存器参数保存在堆栈中,为什么要使用寄存器传递参数,而不是直接通过堆栈传递所有参数?

t9aqgxwy

t9aqgxwy1#

被调用者可能需要保存它们,也可能不需要保存,这完全取决于具体情况。例如,一个函数只返回参数的和,可能不需要保存它们。在这种情况下,使用寄存器保存了一个存储和一个加载,而在另一种情况下,它不会产生任何开销(存储只是从调用者移动到被调用者)。
如果在调用方中与局部变量一起分配影子空间,则实际上是免费的,并且其优点是,如果被调用方需要保存参数,则结果块将与堆栈上已经存在的其余参数相邻。

相关问题