1

我是 asm x86 的新手,我一直在寻找为什么在 x86/visual C++ 2010 上会出现这样的函数调用:

void test()
{
    vector2f vec;
    vec.x = 1.f;
    vec.y = 1.f;
    vec = something_on_vector2f(vec);
}

给定:

struct vector2f 
{
    vector2f() {}
    float x;
    float y;
}; 

vector2f something_on_vector2f(vector2f vec)
{
    return vec;
}

生成具有如此大的堆栈分配(224 字节)和 3 个“推送”而不是预期的 2 个(推送“x”+推送“y”)的汇编代码

...
00FBB780 55                   push        ebp  
00FBB781 8B EC                mov         ebp,esp  
00FBB783 81 EC E0 00 00 00    sub         esp,0E0h  (???)
...
002DB7B0 8B 45 F8             mov         eax,dword ptr [ebp-8]  (push 'x')
002DB7B3 50                   push        eax  
002DB7B4 8B 4D F4             mov         ecx,dword ptr [vec]    (push 'y')
002DB7B7 51                   push        ecx  
002DB7B8 8D 95 24 FF FF FF    lea         edx,[ebp-0DCh]         (push '???')
002DB7BE 52                   push        edx  
002DB7BF E8 4B E7 FF FF       call        normalize_vector2f (2D9F0Fh)  
...

什么是额外的推送和额外的堆栈分配?

我正在使用 libjit 并且只生成了 2 个 push =>,这会在从 JIT 代码调用函数时创建一个错误,因为本机代码不期望堆栈中的参数具有相同的 EBP 偏移量。

4

2 回答 2

2

基本问题是您正在查看在 Debug 构建中生成的代码。这与您的客户将要运行的代码几乎没有关系。

/Zi 选项生成了大量额外的堆栈分配。它支持编辑+继续,您可以编辑函数并添加额外的局部变量,而无需重新构建程序。这很好,但它确实需要编译器允许您选择。如果没有空间,则不能添加额外的变量。

其他代码是自动生成的,如果您不遵循三规则,那么编译器将自动生成复制构造函数和赋值运算符。你看到它被使用了。RVO(返回值优化)是标准 C++ 优化器功能。但是只有当优化器打开时你才能得到它。它不在调试版本中。

功能,而不是错误。代码看起来很糟糕,因为你要求编译器让它很糟糕。所以你可以调试它。如果您想查看它的真实外观,请调试 Release 构建代码。它不会那么漂亮。嗯,可调试。

于 2013-07-29T23:20:48.543 回答
0

我猜测可能的 SSE 或 SSE2 使用(不,那是 16 字节)或缓存效率或可能需要 256 字节对齐的 CUDA 使用的 256 字节对齐。不过,我同意这很愚蠢。查看您的编译器默认值以确保结构对齐。

于 2013-07-29T21:56:24.897 回答