我是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次推送=>从JIT代码调用函数时会产生错误,因为本机代码不希望堆栈中的参数处于相同的EBP偏移量。
答案 0 :(得分:2)
基本问题是您正在查看在Debug构建中生成的代码。这与您的客户将要运行的代码几乎没有关系。
大量的额外堆栈分配由/ Zi选项生成。它支持编辑+继续,您可以编辑该功能并添加额外的局部变量,而无需重建您的程序。这非常好,但它确实需要编译器允许您选择。如果没有任何空间,则无法添加额外的变量。
其他代码是自动生成的,如果不遵循Rule Of Three,则编译器将自动生成复制构造函数和赋值运算符。你看到它被使用了。 RVO(返回值优化)是标准的C ++优化器功能。但是只有在打开优化器时才能获得它。它不在Debug构建中。
功能,而不是错误。代码看起来很糟糕,因为你要求编译器让它变得糟透了。所以你可以调试它。如果您想查看真正的外观,请调试Release构建代码。它不会那么漂亮。嗯,可调试。
答案 1 :(得分:0)
我猜测可能的SSE或SSE2使用的256字节对齐(nah即16字节)或者用于缓存效率,或者可能用于需要256字节对齐的CUDA使用。不过,我同意这很愚蠢。查看结构对齐的编译器默认值以确定。