如何使用128位C变量和xmm 128位asm?
在
gcc中,我想通过asm代码做一个128位xor与2 C变量,如何?
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) 解决方法
如果变量不是16字节对齐,您将看到segfault问题.
The CPU can’t MOVDQA to/from unaligned memory addresses,并将产生一个处理器级别的“GP异常”,提示操作系统删除您的应用程序.
您声明的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 %.16llxn",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 %.16llxn",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 %.16llxn",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 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |