如何使用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 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
