asm ( "movdqa %1,%%xmm1;" "movdqa %0,%%xmm0;" "pxor %%xmm1,%%xmm0;" "movdqa %%xmm0,%0;" :"=x"(buff) /* output operand */ :"x"(bu),"x"(buff) :"%xmm0","%xmm1" );
movq -0x80(%rbp),%xmm2 movq -0x88(%rbp),%xmm3 movdqa %xmm2,%xmm1 movdqa %xmm2,%xmm0 pxor %xmm1,%xmm0 movdqa %xmm0,%xmm2 movq %xmm2,-0x78(%rbp)
解决方法
您声明的C变量(堆栈,全局)或在堆上分配通常不会与16字节边界对齐,但偶尔您可能会偶然获得一个对齐的.您可以通过使用__m128或__m128i数据类型来指示编译器确保正确对齐.每个都声明一个正确对齐的128位值.
此外,读取objdump,看起来编译器使用代码将asm序列包装,以使用MOVQ指令将操作数从堆栈复制到xmm2和xmm3寄存器,只有使您的asm代码将值复制到xmm0和xmm1.在xore0进入xmm0之后,包装器将结果复制到xmm2,然后将其复制回堆栈.总体而言,效率并不高. MOVQ每次复制8个字节,and expects (under some circumstances),an 8-byte aligned address.获取未对齐的地址,它可能会失败,就像MOVDQA一样.然而,包装器代码向BP寄存器添加了一个对齐的偏移量(-0x80,-0x88和更高的-0x78),这可能包含或可能不包含一个对齐的值.总而言之,生成的代码中没有对齐的保证.
以下确保参数和结果存储在正确对齐的内存位置,并且似乎工作正常:
#include <stdio.h> #include <emmintrin.h> void print128(__m128i value) { int64_t *v64 = (int64_t*) &value; printf("%.16llx %.16llx\n",v64[1],v64[0]); } void main() { __m128i a = _mm_setr_epi32(0x00ffff00,0x00ffff00,0x10ffff00),/* low dword first! */ b = _mm_setr_epi32(0x0000ffff,0x0000ffff,0x0000ffff),x; asm ( "movdqa %1,%%xmm0;" /* xmm0 <- a */ "movdqa %2,%%xmm1;" /* xmm1 <- b */ "pxor %%xmm1,%%xmm0;" /* xmm0 <- xmm0 xor xmm1 */ "movdqa %%xmm0,%0;" /* x <- xmm0 */ :"=x"(x) /* output operand,%0 */ :"x"(a),"x"(b) /* input operands,%1,%2 */ :"%xmm0","%xmm1" /* clobbered registers */ ); /* printf the arguments and result as 2 64-bit hex values */ print128(a); print128(b); print128(x); }
编译(gcc,ubuntu 32位)
gcc -msse2 -o app app.c
输出:
10ffff0000ffff00 00ffff0000ffff00 0000ffff0000ffff 0000ffff0000ffff 10ff00ff00ff00ff 00ff00ff00ff00ff
在上面的代码中,_mm_setr_epi32用于初始化a和b与128位值,因为编译器可能不支持128个整数文字.
print128写出128位整数的十六进制表示,因为printf可能无法这样做.
以下是较短的,并避免了一些重复的复制.编译器添加隐藏的包装movdqa来使pxor%2,%0神奇地工作,而不必自己加载寄存器:
#include <stdio.h> #include <emmintrin.h> void print128(__m128i value) { int64_t *px = (int64_t*) &value; printf("%.16llx %.16llx\n",px[1],px[0]); } void main() { __m128i a = _mm_setr_epi32(0x00ffff00,b = _mm_setr_epi32(0x0000ffff,0x0000ffff); asm ( "pxor %2,%0;" /* a <- b xor a */ :"=x"(a) /* output operand,%2 */ ); print128(a); }
如前所述:
gcc -msse2 -o app app.c
输出:
10ff00ff00ff00ff 00ff00ff00ff00ff
或者,如果您想避免内联汇编,可以使用SSE intrinsics instead(PDF).那些内嵌函数/宏封装了类似C语法的MMX / SSE指令. _mm_xor_si128将您的任务减少到一个通话:
#include <stdio.h> #include <emmintrin.h> void print128(__m128i value) { int64_t *v64 = (int64_t*) &value; printf("%.16llx %.16llx\n",v64[0]); } void main() { __m128i x = _mm_xor_si128( _mm_setr_epi32(0x00ffff00,/* low dword first !*/ _mm_setr_epi32(0x0000ffff,0x0000ffff)); print128(x); }
编译:
gcc -msse2 -o app app.c
输出:
10ff00ff00ff00ff 00ff00ff00ff00ff