0

我正在尝试在 SSE 中使用对齐的操作,但遇到了问题(惊喜)。

typedef struct _declspec(align(16)) Vec4 {  
    float x;  
    float y;  
    float z;  
    float w;  
};

Vec4 SSE_Add(const Vec4 &a, const Vec4 &b) {  
    _declspec(align(16)) Vec4 return_val;  

    _asm { 
        MOV EAX, a                    // Load pointers into CPU regs
        MOV EBX, b

        MOVAPS XMM0, [EAX]            // Move unaligned vectors to SSE regs
        MOVAPS XMM1, [EBX]

        ADDPS XMM0, XMM1              // Add vector elements
        MOVAPS [return_val], XMM0     // Save the return vector
    }

    return return_val;
}

我在 处遇到访问冲突return return_val。这是对齐问题吗?我该如何纠正?

4

2 回答 2

2

我发现问题出在 EBX 寄存器上。如果您推送/弹出 EBX,那么它可以工作。我不知道为什么,所以如果有人可以解释这一点 - 请做。

编辑:我研究了反汇编,并在函数的开头将堆栈指针存储在 EBX 中:

mov ebx, esp

所以你最好确保不要丢失它。

于 2013-06-06T19:12:28.847 回答
0

这有点依赖于编译器......不是正确的写法:movaps return_val, xmm0

为什么不向我们展示生成的代码?

你写这个的方式比让编译器自己做要糟糕得多。

  • 这个函数应该是可内联的,并且在最好的情况下转换为一条指令,如果你这样写它就不能被内联。
  • 这个函数可以在 Intel 64 的寄存器中接收它的参数,并在寄存器中返回它的结果,如果你这样写,你会强制使用堆栈。
  • 这个函数可以使用返回值优化,这样写会迫使你将 xmm0 写入 return_val 变量,该变量必须被第二次复制。

所以...对齐与未对齐的 MOVPS 是您最不关心的问题。

为什么不直接在可移植代码中编写:

inline void add(const float *__restrict__ a, const float *__restrict__ b, float *__restrict__ r)
{
    for (int i = 0; i != 4; ++i) r[i] = a[i] + b[i];
}
于 2013-06-06T19:09:05.047 回答