我一直在使用GCC long
编写一些基本函数来练习实际应用。
我的函数asm
,pretty
和wrap
生成相同的指令,将64位整数解包为128位向量。分别调用pure
和add1
的{{1}}和add2
也会生成相同的指令。但是pretty
通过将其wrap
寄存器保存到堆栈而不是将其复制到另一个add3
寄存器来保存。这个我不明白,因为编译器可以看到xmm0
的详细信息,知道其他xmm
寄存器都不会被破坏。
这是C ++
pure
使用xmm
进行编译,并使用#include <immintrin.h>
__m128i pretty(long long b) { return (__m128i){b,b}; }
__m128i wrap(long long b) {
asm ("mov qword ptr [rsp-0x10], rdi\n"
"vmovddup xmm0, qword ptr [rsp-0x10]\n"
:
: "r"(b)
);
}
extern "C" __m128i pure(long long b);
asm (".text\n.global pure\n\t.type pure, @function\n"
"pure:\n\t"
"mov qword ptr [rsp-0x10], rdi\n\t"
"vmovddup xmm0, qword ptr [rsp-0x10]\n\t"
"ret\n\t"
);
__m128i add1(__m128i in, long long in2) { return in + pretty(in2);}
__m128i add2(__m128i in, long long in2) { return in + wrap(in2);}
__m128i add3(__m128i in, long long in2) { return in + pure(in2);}
进行反汇编。
g++ -c so.cpp -march=native -masm=intel -O3 -fno-inline
答案 0 :(得分:2)
GCC不理解汇编语言。
由于pure
是一个外部函数,它无法确定它改变哪些寄存器,因此根据ABI必须假设所有xmm
寄存器都被更改。
wrap
具有未定义的行为,因为asm
语句符号xmm0
和[rsp-0x10]
未列为符号或输出(对于可能依赖或不依赖的值) b
),函数没有return
语句。
编辑:ABI不适用于内联汇编,如果从命令行中删除-fno-inline
,我希望您的程序不起作用。