在内联GCC组件中使用C数组

时间:2011-05-17 13:00:48

标签: gcc assembly arm

我想使用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) );

    // ...
}

1 个答案:

答案 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) );

fldfst指令需要内存操作数。此外,您需要指定是否要加载float(flds),double(fldl)或long double(fldt)。至于输出操作数,我只使用约束=t,它只是告诉编译器结果位于寄存器堆栈的顶部,即ST(0)。

算术运算要么没有操作数(fmulp),要么有单个内存操作数(但是你必须再次指定大小,fmuls,fadds等。)

您可以详细了解inline assemblerGNU 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