这段代码(加倍4矢量)起作用:
__declspec(align(16)) struct vec4 { float a[4]; };
int main()
{
vec4 c;
c.a[0]=2;
c.a[1]=0;
c.a[2]=0;
c.a[3]=0;
__asm {
movaps xmm1, c
addps xmm1, xmm1
movaps c, xmm1
}
}
但是这篇文章(做同样但现在用指向对齐数据的指针)并没有:
__declspec(align(16)) struct vec4 { float a[4]; };
int main()
{
vec4* c = new vec4;
c->a[0]=2;
c->a[1]=0;
c->a[2]=0;
c->a[3]=0;
__asm {
movaps xmm1, c
addps xmm1, xmm1
movaps c, xmm1
}
}
为什么?
我需要它来处理指针,因为我不能将对齐的数据本身用作函数参数。
答案 0 :(得分:0)
ASM中的指针必须根据某些规则进行处理,您可以通过学习how "MOV" works来学习。
根据Assembler的规则,首先需要将指针复制到cpu寄存器。然后你可以用它来指向内存位置。
vec4 *d = ...;
__asm {
mov eax, d
movaps xmm1, [eax]
addps xmm1, xmm1
movaps [eax], xmm1
}
答案 1 :(得分:0)
问题是堆分配器(如new和malloc)创建的对象不遵循您指定的对齐方式。您只能使用堆栈分配对象(第一个示例)进行对齐。
C ++ 11支持使用alignas显式对齐通过堆分配的对象,但VC ++尚未实现。它适用于某些编译器,而不适用于其他编译器。
您有几个选择。
最简单的方法:像你一样创建堆分配对象,并在使用之前将其复制到堆栈分配对象:
vec4* c = new vec4;
c->a[0]=2;
c->a[1]=0;
c->a[2]=0;
c->a[3]=0;
vec4 d = *c;
// process with d
另一个选择是让你的vec4结构包含足够的额外内存,以确保在16字节对齐上有16个字节。我相信新的保证至少4字节对齐,所以28字节就可以做到。然后,您必须手动检查指针,以查看要与sse一起使用的数据存储位置。