对编译器的考虑事项

在编写需要与C代码结合的汇编代码时,汇编编程人员必须了解编译器的约定和假设。汇编编程人员还必须了解编译器的寄存器使用约定。通常,寄存器使用约定将硬件寄存器分成被调用方保存(或调用方使用)和被调用方使用(或调用方保存)寄存器。图2给出了从CEVA-X1641 DSP内核FFT实现中摘取的汇编代码例子。左边第二行的add指令符合CEVA-X1641编译器传递r0地址寄存器中指针参数的调用约定。右边的pushd指令用于备份后面函数会用到的被调用方保存寄存器。

C和汇编代码结合 是实现DSP软件设计的最好方式

图2:从CEVA-X1641 DSP内核的FFT实现中摘取的一段汇编代码。

除了调用约定和寄存器使用约定外,一些编译器在人工编写的汇编代码方面可能还会有一些额外的假设。这些假设通常是专门针对某个编译器的,因此编译器提供商会提供完善的资料和说明。

用于C和汇编连接的常用C语言扩展

用于嵌入式平台的大多数编译器,特别是用于DSP编程的编译器,都具有丰富的C语言和汇编语言连接功能。其中绝大部分功能不属于标准C语言,因此被称为C语言扩展。下面列出的是其中有益于DSP编程的一些功能。

内联汇编(inline assembly):该功能可以帮助编程人员将汇编指令插入C代码。

硬件寄存器绑定C变量:该功能经常与汇编指令内联功能结合在一起,帮助内联汇编代码访问C语言级的变量(见图3)。

C和汇编代码结合 是实现DSP软件设计的最好方式

图3:结合内联汇编和硬件寄存器绑定功能的代码示例。

存储区属性:该功能允许编程人员将上述变量和函数分配到独特的用户定义存储区,可以让编程人员将C语言级单元分配到实际的存储器位置,这对DSP应用来说非常关键。

用户定义的调用约定:在某些情况下,汇编函数可以通过用户定义的调用约定取得更好的优化效果。编译器内部函数(Compiler intrinsics):是指能够使用专门的宏或函数调用触发的内建编译器功能总称。没有内部函数支持的编译器必须调用用户定义的函数,这样做可能会令用户定义函数可能会在一个环路里产生函数调用和返回(见图4),从而产生巨大的开销。

C和汇编代码结合 是实现DSP软件设计的最好方式