C++ C+中的SSE4内联装配问题+;

C++ C+中的SSE4内联装配问题+;,c++,gcc,assembly,inline-assembly,C++,Gcc,Assembly,Inline Assembly,大家好 我想执行以下形式的内联汇编指令 BLENDPD xmm1,xmm2/m128, imm8 我是内联汇编新手,所以我遇到了一些困难。 我的代码是: #include<iostream> using namespace std; int main() { long long y; __asm("blendpd %0,$0xabcd000000001111abcd000000001111,$0x1": "=r" (y): ); cout<<

大家好 我想执行以下形式的内联汇编指令

BLENDPD xmm1,xmm2/m128, imm8
我是内联汇编新手,所以我遇到了一些困难。 我的代码是:

#include<iostream>
using namespace std;
int main()
{
  long long y;
  __asm("blendpd %0,$0xabcd000000001111abcd000000001111,$0x1":
    "=r" (y):
    );
  cout<<y;
  return 0;
}
#包括
使用名称空间std;
int main()
{
长y;
__asm(“blendpd%0,$0xabcd000000001111abcd000000001111,$0x1”:
“=r”(y):
);

cout首先,对于这种情况,您很少需要使用内联汇编。GCC通常提供“编译器内部”函数,允许您使用C函数语法而不是汇编语法调用给定的特殊指令

在本例中,您需要的内在函数是_mm_blend_pd(),它具有此函数签名

#include <smmintrin.h>
__m128d _mm_blend_pd(__m128d v1, __m128d v2, const int mask);
要从向量中检索值以打印它们,可以将向量存储到双精度浮点数组中:

double a[2];
_mm_store_pd(a, v);

这一切都是基于英特尔内部的手册;虽然这是指英特尔C++编译器,GCC支持相同的语法。


编辑:将错误的
emmintrin.h
替换为正确的
smmintrin.h
。此外,请注意
掩码
值需要为2位(向量中每个值一位);除0、1、2或3之外的值会产生错误。当然,您需要使用
-msse4
GCC选项编译此选项。

作为我的另一个答案的替代答案,下面介绍如何使用内联程序集而不是内部程序集进行编译。(正如Thomas Pornin在我的另一个答案中指出的那样,本质语言通常更好,因为它们更便于携带,但有时您也需要类似的东西。)

首先,我作弊了——我用一个内在函数获取了这个版本,并用
-S
编译了它,然后查看了生成的汇编代码,它是:

    movsd   -64(%rbp), %xmm0
    movhpd  -56(%rbp), %xmm0
    movsd   -48(%rbp), %xmm1
    movhpd  -40(%rbp), %xmm1
    blendpd $3, %xmm1, %xmm0
    movlpd  %xmm0, -64(%rbp)
    movhpd  %xmm0, -56(%rbp)
您可以在这里看到一些与原始代码不同的地方。首先,请注意,这两个128位参数不是直接变量——它们是xmm0和xmm1寄存器。此外,您的操作数顺序错误——掩码在前,包含输出的寄存器在后。修复它们,代码将编译

这里的第二个问题是,您正在将通用寄存器的结果存储到
y
,而blendpd指令不涉及通用寄存器,因此这只是在存储垃圾。您需要
xmm0
寄存器,它是通过
=Yz
获得的(请参阅)。您不能将其存储到64位的
long
;您需要一个128位的向量变量。解决所有这些问题,正确的代码是:

#include<iostream>
#include<smmintrin.h>
using namespace std;
int main()
{
  __m128d y;
  __asm("blendpd $0x3,%%xmm1,%%xmm0":
    "=Yz" (y):
    );
  // cout<<y;
  return 0;
}
#包括
#包括
使用名称空间std;
int main()
{
__m128d-y;
__asm(“blendpd$0x3,%%xmm1,%%xmm0”:
“=Yz”(y):
);

//coutWell的一个问题是这里有奇数个引号。专业提示:您可以为任何主要编译器找到SSE扩展。不要为内联汇编程序操心。@falmari:copy-paste-error!谢谢:)@DeadMG:我想在一个循环中插入这个来检查它消耗了多少电能!这不是一个计算…但我想能够显示耶罗:为什么不使用探查器呢?语法错误:当你编辑一个问题来询问部分答案时,请不要覆盖原来的问题--记住堆栈溢出的目的是创建一些对将来阅读它的其他人也有用的东西,为此,他们需要理解问题和答案。(我在年编辑了原始代码版本,希望没问题。)值得注意的是,
实际上来自英特尔编译器,并将与GCC、英特尔C编译器ICC和Microsoft Visual C配合使用。这比内联汇编更具可移植性:完全相同的代码将在Linux上与GCC配合使用,在Windows上与Visual C配合使用。此外,它与GCC优化器配合使用效果更好,因为GCC了解intrinsic是关于,并且可以相应地分配XMM寄存器;而内联汇编是一个不透明的转储到GCC的汇编输出。我按照u的要求做了,得到了一个未定义的函数引用!请参考编辑的问题:)>thanksCorrected;请参阅“编辑”中的注释我补充道。不客气。不用担心编辑;每个人都有时间学习东西!:)
    movsd   -64(%rbp), %xmm0
    movhpd  -56(%rbp), %xmm0
    movsd   -48(%rbp), %xmm1
    movhpd  -40(%rbp), %xmm1
    blendpd $3, %xmm1, %xmm0
    movlpd  %xmm0, -64(%rbp)
    movhpd  %xmm0, -56(%rbp)
#include<iostream>
#include<smmintrin.h>
using namespace std;
int main()
{
  __m128d y;
  __asm("blendpd $0x3,%%xmm1,%%xmm0":
    "=Yz" (y):
    );
  // cout<<y;
  return 0;
}