我想使用GCC编译器(Mac上的Xcode)将两个数组传递给C函数,如下所示。自从我编写汇编以来已经很多年了,所以我确信这是一个很容易解决的问题。
这里的第一行很好。第二行失败了。我正在尝试执行以下操作,A [0] + = x [0] * x [0],我想对具有不同索引的数组中的许多元素执行此操作。我只在这里展示一个。如何在汇编块中使用读/写数组?
如果有更好的方法来做到这一点,我会张开耳朵。
inline void ArrayOperation(float A[36], const float x[8])
{
float tmp;
__asm__ ( "fld %1; fld %2; fmul; fstp %0;" : "=r" (tmp) : "r" (x[0]), "r" (x[0]) );
__asm__ ( "fld %1; fld %2; fadd; fstp %0;" : "=r" (A[0]) : "r" (A[0]), "r" (tmp) );
// ...
}
答案 0 :(得分:2)
代码失败的原因不是因为数组,而是因为fld和fst指令的工作方式。这是您想要的代码:
float tmp;
__asm__ ( "flds %1; fld %%st(0); fmulp; " : "=t" (tmp) : "m" (x[0]) );
__asm__ ( "flds %1; fadds %2;" : "=t" (A[0]) : "m" (A[0]), "m" (tmp) );
fld
和fst
指令需要内存操作数。此外,您需要指定是否要加载float(flds),double(fldl)或long double(fldt)。至于输出操作数,我只使用约束=t
,它只是告诉编译器结果位于寄存器堆栈的顶部,即ST(0)。
算术运算要么没有操作数(fmulp),要么有单个内存操作数(但是你必须再次指定大小,fmuls,fadds等。)
您可以详细了解inline assembler,GNU Assembler in general,并查看Intel® 64 and IA-32 Architectures Software Developer’s Manual。
当然,最好摆脱临时变量:
__asm__ ( "flds %1; fld %%st(0); fmulp; fadds %2;" : "=t" (A[0]) : "m" (x[0]), "m" (A[0]));
虽然如果性能提升是您所追求的,但您不需要使用汇编程序。 GCC完全有能力生成此代码。但您可以考虑使用向量SSE指令和其他简单的优化技术,例如打破计算中的依赖关系链,请参阅Agner Fog's optimization manuals