我正在开发一个需要与 QNX-Momentics(基于 Eclipse,g++ 4.6.1 工具链)和 Visual Studio 2010 编译的项目。对于某些例程,我决定进行手动组装实现,因为即使内在函数也不好优化。第一个编译器具有 ATt&T 语法,可以使用 -masm=intel 标志“intelized”,第二个编译器仅是 intel 方言。
使用 intel-flag,我可以通过一个 - 不好但有效 - 定义的技巧来超越符号方面:
#ifdef _WIN32
#define _cmd(...) __VA_ARGS__
__asm {
#else
#define _cmd(...) #__VA_ARGS__
asm volatile (
#endif
// constants
// set loop counter
_cmd( xor eax, eax; )
:
:
#ifdef _WIN32
}
#else
);
#endif
现在,一个问题是,我无法使用内联 AT&T 按名称访问函数的局部变量或参数。我在另一个线程中得到的提示,使用类似的东西
register __m128i x asm("xmm6");
没有工作的局部变量,它被分配给xmm0。内部函数未定义的局部变量或参数导致 AT&T 中未定义的引用,因此我决定使用裸堆栈处理,例如
_cmd( movupd xmmword ptr [eax], xmm3; )
并遇到了一个新问题:
函数参数和局部变量在两种方言中的处理方式完全不同。考虑以下示例:
template<typename T>
void linearRegression2DAsm(unsigned int p_oNumPoints, T *p_pXcoords, T *p_pYcoords,
double *oX, double *oY, double *oXY,
double p_oAvgX, double p_oAvgY)
{
unsigned int p_rLoopsize = p_oNumPoints - (p_oNumPoints % 2);
double oAvgX[2];
以及上面给出的定义块之后的简单计算:
_cmd( xor eax, eax; )
// p_pXccoords
_cmd( mov ecx, dword ptr [ebp+12]; )
// p_pYcoords
_cmd( mov edx, dword ptr [ebp+16]; )
// p_oAvgX
_cmd( movhpd xmm6, qword ptr [ebp+20]; )
// p_oAvgY
_cmd( movhpd xmm7, qword ptr [ebp+28]; )
_cmd( movlpd xmm6, qword ptr [ebp+20]; )
_cmd( movlpd xmm7, qword ptr [ebp+20]; )
_cmd( addpd xmm7, xmm6; )
// result into oAvgX
_cmd( mov eax, [ebp-32]; )
_cmd( movupd xmmword ptr [ebp-32], xmm7; )
结果应该在 oAvgX 中,它适用于英特尔,但不会导致使用英特尔标记的 AT&T asm 编译器成功。其次,我担心额外的 O2-Flag 可能会优化其他变量,因此不能保证堆栈在不同编译上的构建相同。
我需要内联,但看不到解决双重方言问题的任何方法。