我正在研究一个需要与QNX-Momentics(基于eclipse,g ++ 4.6.1工具链)和Visual Studio 2010编译的项目。对于一些例程,我决定去实现手动装配,因为即使内在函数也没有很好的优化。第一个编译器具有ATt & T语法,可以使用-masm = intel标志进行“智能化”,第二种是intel方言。不是很好,但工作 - -双重asm方言项目的问题intel/AT&T
使用Intel标志,我可以用超越记法方面定义绝招:现在
#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 &牛逼未定义的引用,所以我决定用裸栈处理,如
_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,其正常工作与英特尔,但使用不会导致成功intel标记AT & T asm编译器。其次,我担心额外的O2-Flag可能会优化其他变量,因此不能保证在不同的编译中构建相同的堆栈。
我需要内联,但是看不到解决双重方言问题的任何方法。
问候并感谢您的回复。我知道at&t/gcc程序集中的列表和clobber列表,但是我可以如何访问代码块中间的变量?使用列表中的内容,将其分配给某些内存,然后再访问它?而且,最重要的是,如何将变量分配给sse寄存器?我到目前为止失败了...... – gilgamash
这是一个巨大的秘密;但变量只是一种幻觉 - 它们不存在。存在的是地址和这些地址的内存内容;并注册。您可能想要告诉GCC,组件的输入是某个地址(例如“变量”),以便内联程序集可以将该地址处的数据加载到SSE寄存器中。你可能想告诉GCC SSE寄存器也是一个输入(虽然我不确定GCC是否以这种方式正确支持SSE)。 – Brendan