GCC ARM内联汇编介绍(一)

GNU C编译器支持ARM RISC处理器,使得我们可以在C/C++中进行 ARM汇编语句的编程,从而实现操作较为底层ARM行为。

下面首先介绍GCC ASM的语句格式;

对于汇编语句中所涉及C语句中所引用到的寄存器和常量,会已相应的特定形式进行描述;通常,汇编语句的形式如下:

asm(code:output list:input list:clobber list)

汇编语言和C语言之间的关联是通过汇编语句中code中的第二,三部分和output list、input list进行关联。他们之间是如何发生关联关系?下面我们就给出详细的实例进行介绍。

下面我们看一个bit rotation的实例,该函数的作用是将一个integer的每个bit进行右转操作,然后保存到第二个Integer中。

asm(“move %[result] %[value], ror $1”: [result] “=r”(y):[value] “r”(x))

从上面的语句中我们可以看到,其涉及了result, value, “=r” “r” (x) (y) 这些代码元素;那么这些代码元素的具体含义是什么? 从上面我们知道一条汇编语句分为四个部分:(1)asm指令部分;(2)output list部分;(3)input list部分;(4)clobber部分;其中的第一个部分:asm指令为必选项,即这部分必须出现在asm语句中,即使我们asm指令为空;例如:asm(“”)。 此外,另外三个部分为可选项,可以出现在asm语句中,也不不出现。

下面我们就以bit rotation为实例对这个四个部分进行说明。上述四个部分使用冒号 “:”进行分隔。

下面我们首先看第一个部分。

汇编指令部分,在这部分中,汇编指令被包含在一对双引号中 “”。就像一个字符串一样。例如:上述例子中汇编指令 “move %[result], %[value], ror #1″。

output list部分:该部分由三个成分构成。符合名字,约束说明,C语句中的表达式这三个成分构成。其中符合名字又是以:[符合名] 这样的形式进行描述;约束说明以 “约束说明” 这样的形式进行描述; C语句中的表达式以 (C语句表达式) 这样的形式进行描述;例如:对于上述的例子 [result],描述了一个符合名称为result的对象,该对象的约束条件为:“=r”, 该符合名字所表述的对象在C语句中的对应的变量描述是以(y)这些形式给出,即在该asm语句操作的结果会保存在C语言语句中的变量y中;

input list部分:该部分与output list部分相似,这里不再赘述;

Clobber list部分:在本例中,并未给出。职业Clobber list的具体作用在下面文章中介绍;

这里需要说明的是,如果中间的某个部分没有具体内容,那么用于分割的冒号不能省略; 例如:asm(“msr cpsr, %[ps]”:: [ps] “r”(status));

为了代码的可读性,我们可以在asm语句中使用空格,换行,或者是 c style的注释来提高代码的可读性。

asm(” move %[result], %[value], ror #1″

:[result] “=r” (y) /*roration result*/

:[value] “r” (x) /*rotation value*/

:/*clobber list*/

)

在ASM语句中的代码部分(code section),操作数具有如下的形式: %[符合名]。符合名与C语句中的变量的名字属于不同的名字空间,两者没有关联关系,互不受影响。但是对于ASM语句中的符号名需要满足不重复性。这些符合名将会出现在操作符列表中。例如在output list和input list中。

事实上,GCC早期的版本并不支持符号名这一写法,这一写法是直到3.1版本后才支持。例如:早期的写法如下:

asm(“mov %0, %1, ror #1”: “=r”(result): “r”(value));

在该种写法下,操作数以%N的形式给出,其中N为0-9的数字。例如本例中的%0描述了第一个操作数,%1描述了第二个操作数;该种方式下,对于代码的可读性将是一个噩梦。因此在3.1版本后,GNU使用了更加人性化的描述方式来给出哥哥操作数的形式化,从而提高了代码的可读性。