APTCS(arm/thumb程序调用规范),PCS规定了应用程序的函数可以如何分开地写,分开地编译,最后将它们连接在一起,所以它实际上定义了一套有关过程(函数)调用者与被调用者之间的协议。协议规定:调用函数如何传递参数(即压栈方法,以何种方式存放参数),被调用函数如何获取参数,以何种方式传递函数返回值。
1. APTCS使用规则
最主要的一条:子程序通过寄存器R0~R3来传递参数. 这时寄存器可以记作:A1~A4 , 被调用的子程序在返回前无需恢复寄存器R0~R3的内容.如果需要更多的参数,将使用堆栈。
2. 汇编调用c语言,流程如下:
3)如果要传参,r0 --->给main()的第1个参数,依次类推
2)c文件要extern intmystrcpy(char *,char*);
示例代码:
C文件代码:
extern void mystrcopy(char *d,const char *s);
int main(void)
{
Mystrcpy(desr,src);
}
S文件代码:
.global mystrcopy
.text
mystrcopy:
LDRBr2, [r1], #1
STRBr2, [r0], #1
CMPr2, #0
BNEmystrcopy
MOVpc, lr
END
4. GCC 内联汇编
1)gcc通过关键字“asm”来声明内联汇编
2)允许使用一些不能由编译器自动生成的指令:
MSR / MRS
新的指令
协处理器指令
3)通常在关联的内嵌函数中使用
4)使用C变量代替寄存器
5)内嵌汇编语法格式:
内嵌汇编语法如下:
__asm__(汇编语句模板: 输出部分: 输入部分: 破坏描述部分)
共四个部分:汇编语句模板,输出部分,输入部分,破坏描述部分,各部分使用“:”格开,汇编语句模板必不可少,其他三部分可选,如果使用了后面的部分,而前面部分为空,也需要用“:”格开,相应部分内容为空。例如:
__asm__ __volatile__("cli": : :"memory")
1、汇编语句模板
汇编语句模板由汇编语句序列组成,语句之间使用“;”、“/n”或“/n/t”分开。指令中的操作数可以使用占位符引用C语言变量,操作数占位符最多10个,名称如下:%0、 %1 ...... %9。
2、输出部分
输出部分描述输出操作数,不同的操作数描述符之间用逗号格开,每个操作数描述符由限定字符串和C 语言变量组成。每个输出操作数的限定字符串必须包含“=”表示他是一个输出操作数。
3、输入部分
输入部分描述输入操作数,它的语法跟输出部分一样,只不过不需带“=”。
4、限制字符
具体来看一下示例代码学习:
int sum,a,b;
a = 1;
b = 2;
asmvolatile(
"add%0,%1,%2\n\t"
:"=r"(sum)
:"r"(a),"r"(b)
:"memory"
);
printf("sum =%d\n",sum);
打印结果为3。
注1:volatile用于告诉编译器,这里严禁优化。
注2:sum对应%0,a 对应%1,b对应%2
注3: memory 强制 gcc 编译器假设RAM 所有内存单元均被汇编指令修改,这样 cpu 中的 registers 和 cache 中已缓存的内存单元中的数据将作废。cpu 将不得不在需要的时候重新读取内存中的数据。这就阻止了 cpu 又将 registers, cache 中的数据用于去优化指令,而避免去访问内存。