为什么包含在函数中的GAS内联汇编为调用者生成与纯汇编函数不同的指令

时间:2016-03-30 16:03:01

标签: c++ gcc assembly sse gas

我一直在使用GCC long编写一些基本函数来练习实际应用。

我的函数asmprettywrap生成相同的指令,将64位整数解包为128位向量。分别调用pureadd1的{​​{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

1 个答案:

答案 0 :(得分:2)

GCC不理解汇编语言。

由于pure是一个外部函数,它无法确定它改变哪些寄存器,因此根据ABI必须假设所有xmm寄存器都被更改。

wrap具有未定义的行为,因为asm语句符号xmm0[rsp-0x10]未列为符号或输出(对于可能依赖或不依赖的值) b),函数没有return语句。

编辑:ABI不适用于内联汇编,如果从命令行中删除-fno-inline,我希望您的程序不起作用。