大家好 我想执行一个以下形式的内联汇编指令
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;
}
我的第一个错误是得到一个128位操作数,所以我使用了长十六进制数,但我仍然需要输出为128位,因为我希望2能够在屏幕上打印y。而且最重要的是我知道我的__asm语法是错误的但是无法弄明白,加上我不确定使用英特尔或AT&amp; T语法进行编译会在使用__asm时产生影响。
欢迎任何帮助。干杯! =)
编辑:我现在有了这个版本,并且收到了未定义的函数错误。
#include<iostream>
#include<emmintrin.h>
using namespace std;
int main()
{
const int mask=5;
__m128d v2 = _mm_set_pd(1.0, 2.0);
__m128d v1;
v1=_mm_blend_pd(v1, v2, mask);
return 0;
}
答案 0 :(得分:5)
首先,对于这类事情,您很少需要使用内联汇编。 GCC通常提供“编译器内在”函数,允许您使用C函数语法而不是汇编语法调用给定的特殊指令。
在这种情况下,你想要的内在函数是_mm_blend_pd(),它有这个函数签名
#include <smmintrin.h>
__m128d _mm_blend_pd(__m128d v1, __m128d v2, const int mask);
编译器将用单blendpd
指令替换它;这实际上不是函数调用。
__m128d数据类型是一个包含两个双精度浮点值的向量;你可以从像这样的双打数组中创建一个:
__m128d v = _mm_set_pd(1.0, 2.0);
要从矢量中检索值以打印它们,可以将矢量存储到双精度浮点数组中:
double a[2];
_mm_store_pd(a, v);
所有这些都基于http://www.info.univ-angers.fr/~richer/ens/l3info/ao/intel_intrinsics.pdf上的英特尔内在函数手册;虽然这是指英特尔C ++编译器,但GCC支持相同的语法。
修改:使用正确的emmintrin.h
替换错误的smmintrin.h
。另请注意,mask
值必须为2位(向量中每个值一位); 0,1,2或3以外的值会产生错误。当然,您需要使用-msse4
GCC选项进行编译。
答案 1 :(得分:3)
作为我的另一个答案的替代答案,这里是如何使用内联汇编而不是内在汇编。 (正如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
(请参阅GCC's documentation here)。并且你不能将它存储到long long
,这是64位;你需要一个128位向量变量。解决所有这些问题,纠正的代码是:
#include<iostream>
#include<smmintrin.h>
using namespace std;
int main()
{
__m128d y;
__asm("blendpd $0x3,%%xmm1,%%xmm0":
"=Yz" (y):
);
// cout<<y;
return 0;
}
你会注意到我必须注释cout
行,因为它没有处理SSE向量的规定;您需要先使用_mm_store_pd
内在函数从y
中获取单个double值。 (或者您可以添加更多内联汇编来调用movhpd
和movhld
指令以直接从寄存器中获取double值,而不是使用约束将它们分配给y
。)
而且你有它 - 编译并运行良好。当然,输入值是未定义的(无论这些寄存器中是否随机出现),因此输出仍然是垃圾 - 如果您想获得有意义的结果,则需要先添加一些内容以将值加载到寄存器中。