为了使C语言程序和汇编程序之间能够互相调用,必须为子程序间的调用制定规则~~
然后呢,在ARM处理器中,这个规则被称为ATPCS:ARM程序和Thumb程序中子程序调用的规则(如果用过51单片机汇编和C的混合编程,那这个就So Easy了~~)。
这里只是说说基本的ATPCS规则包括寄存器使用规则、数据栈使用规则、参数传递规则。
1、寄存器使用规则:
ARM处理器中有r0-r15共16个寄存器,它们的用途是有一些约定的习惯的!
并依据这些用途定义了别名。
如图:
1)子程序间通过寄存器r0-r3来传递参数,这时可以使用它们的别名a0-a3,被调用的子程序返回前无需回复r0-r3的内容。
2)在子程序中,使用r4-r11来保存局部变量,这时可以使用它们的别名v1-v8,如果在子程序中使用了它们的某些寄存器,子程序进入时要保存这些寄存器的值,返回时再次恢复它们;
对于子程序中没有使用到的寄存器,则不必进行这些操作,在Thumb指令中,通常只能使用寄存器r4-r7来保存局部变量。
3)寄存器r12用作子程序间scratch寄存器,别名为ip。
4)寄存器r13用作数据栈指针,别名为sp,在子程序中寄存器r13不能用作它用,它的值在进入、退出子程序时必须相等。
5)寄存器r14称为连接寄存器,别名为lr,它用于保存子程序的返回地址。
如果在子程序中保存了返回地址(比如将lr值保存到数据栈中),r14可用作它用。
6)寄存器r15是程序计数器,别名pc,没有别的用途~~
2、数据栈使用规则
数据栈有两个增长方向;向内存地址减小的方向增长时,称为DESCENDING栈;
向内存地址增加的方向增长时,称为ASCENDING栈。
所谓数据栈的增长就是移动栈指针。当栈指针指向栈顶元素(最后一个入栈的数据)时,称为FULL栈;
当栈指针指向栈顶元素相邻的一个空的数据单元时,称为EMPTY栈。
综合这两个特点,数据栈可以分为以下4种:
1)FD: Full Descending,满递减。
2)ED:Empty Descending,空递减。
3)FA:Full Ascending,满递增。
4)EA:Empty Ascending,满递增。
ATPCS规定数据栈为FD类型,并且对数据栈的操作是8字节对齐的。使用stmdb/ldmia批量内存访问指令来操作FD数据栈。
使用stmdb命令往数据栈中保存内容时,先递减sp指针,再保存数据,
使用ldmia命令从数据栈中恢复命令时,先获得数据,再递增sp指针,sp指针总是指向栈顶元素,这刚好是FD栈的定义。
3、参数传递规则
一般来说,当参数个数不超过4个时,使用r0-r3这4个寄存器来传递参数;如果参数个数超过4个,剩余的参数通过数据栈来传递。
同样,对于一般的返回结果,通产使用a0-a3来传递。
例程:
假设CopyCode2SDRAM函数使用C语言实现的,数据原型为:
int CopyCode2SDRAM(unsigned char *buf,unsigned long StartAddr,int size)
在汇编代码中,使用下面的代码调用,同时判断返回值:
ldr r0,=0x30000000
mov r1,#0
mov r2,#16*1024
bl
cmp a0,#0