在 Visual Studio 2010 下为 x64 构建的本机 C 代码中无法解释的堆栈分配

问题描述 投票:0回答:2

我尝试使用 CL 16.0 for x64 (VS 2010) 生成一些可读的 64 位 ASM 代码作为示例,但 CL 坚持预先分配大量堆栈空间(28h 字节),并使用以下行:

sub rsp, 40 ; 00000028H (actual value depends on number of local vars of course)

问题是,如何禁用此行为?向全班同学解释很难,我喜欢向他们展示干净、可解释的代码...我的假设是“sub rsp,XXX”应该分配函数中局部变量所需的确切空间。

当然它不需要那么多额外的空间。在 x86 上,此行为似乎由编辑并继续开关(/Zi 与 /ZI)控制,但这些在 x64 情况下没有任何效果。知道如何让 x64 CL 只分配实际需要的堆栈吗?

visual-studio-2010 assembly stack 64-bit x86-64
2个回答
1
投票

如果你展示生成这个的源代码会更容易,但 40 字节对于 64 位机器来说并不算多。这只是五个

long
或指针。另一件需要考虑的事情是局部变量的对齐 - 编译器可能会填充它们以获得最佳访问。

编辑:

嗯,这确实有点令人费解。通过 GCC 运行它不会导致这样的堆栈抓取。我怀疑这是编译器特定的异常处理序言要求(您是否在生成的代码中的堆栈分配之前和之后看到一些看起来奇怪的标签?)。

以下是一些您可能会觉得有用的 MSDN 链接:

我没有 Windows 机器可供测试,但请尝试

/favor:???
看看是否稍微提高优化级别可以消除此问题。毕竟这是一个叶子函数。

此外,SO 上的注释格式很糟糕,请将代码放入问题本身中。


0
投票

它被称为阴影空间

Win64 中的每个函数都可以(尽管不是必须)存储 4 个寄存器的值。这样做至少有两个原因

  1. 在一个大函数中,为一个输入参数分配整个寄存器(更不用说4个寄存器)太浪费了,因此将通过堆栈来访问它;

  2. 调试器总是知道在中断时在哪里找到函数的参数。

因此,一些大型函数可能会将输入参数保存在“影子空间”中以供将来使用,而像我们这样的小型函数则可能不会。是调用者在堆栈中为“影子空间”分配空间。

© www.soinside.com 2019 - 2024. All rights reserved.