ARM编程中运用的C言语是规范C言语,ARM的开发环境实际上便是嵌入了一个C言语的集成开发环境,只不过这个开发环境与ARM的硬件严密相关。 在运用C言语时,要用到和汇编言语的混合编程。若汇编代码较为简练,则可运用直接内嵌汇编的办法;不然要将汇编程序以文件的方式加入到项目中,依照ATPCS(ARM/Thumb进程调用规范,ARM/Thumb Procedure Call Standard)的规矩与C程序彼此调用与拜访。 在C程序和ARM汇编程序之间彼此调用时有必要恪守ATPCS规矩。ATPCS规矩了一些子程序间调用的根本规矩,哪寄存器的运用规矩,仓库的运用规矩和参数的传递规矩等。
1)寄存器的运用规矩 子程序之间经过寄存器r0~r3来传递参数,当参数个数多于4个时,运用仓库来传递参数。此刻r0~r3可记作A1~A4。 在子程序中,运用寄存器r4~r11保存局部变量。因而当进行子程序调用时要注意对这些寄存器的保存和康复。此刻r4~r11可记作V1~V8。 寄存器r12用于保存仓库指针SP,当子程序回来时运用该寄存器出栈,记作IP。 寄存器r13用作仓库指针,记作SP。寄存器r14称为链接寄存器,记作LR。该寄存器用于保存子程序的回来地址。 寄存器r15称为程序计数器,记作PC。
2)仓库的运用规矩 ATPCS规矩仓库选用满递减类型(FD,Full Descending),即仓库经过减小存储器地址而向下增加,仓库指针指向内含有用数据项的最低地址。
3)参数的传递规矩 整数参数的前4个运用r0~r3传递,其他参数运用仓库传递;浮点参数运用编号最小且能够满足需求的一组接连的FP寄存器传递参数。 子程序的回来成果为一个32位整数时,经过r0回来;回来成果为一个64位整数时,经过r0和r1回来;依此类推。成果为浮点数时,经过浮点运算部件的寄存器F0、D0或许S0回来。
2、汇编程序调用C程序的办法 汇编程序的书写要遵从ATPCS规矩,以确保程序调用时参数正确传递。在汇编程序中调用C程序的办法为:首先在汇编程序中运用IMPORT伪指令事前声明即将调用的C言语函数;然后经过BL指令来调用C函数。 例如在一个C源文件中界说了如下求和函数: int add(int x,int y){ return(x+y); } 调用add()函数的汇编程序结构如下: IMPORT add ;声明要调用的C函数 …… MOV r0,1 MOV r1,2 BL add ;调用C函数add …… 当进行函数调用时,运用r0和r1完成参数传递,回来成果由r0带回。函数调用完毕后,r0的值变成3。 3、C程序调用汇编程序的办法 C程序调用汇编程序时,汇编程序的书写也要遵从ATPCS规矩,以确保程序调用时参数正确传递。在C程序中调用汇编子程序的办法为:首先在汇编程序中运用EXPORT伪指令声明被调用的子程序,表明该子程序将在其他文件中被调用;然后在C程序中运用extern关键字声明要调用的汇编子程序为外部函数。 例如在一个汇编源文件中界说了如下求和函数: EXPORT add ;声明add子程序将被外部函数调用 …… add ;求和子程序add ADD r0,r0,r1 MOV pc,lr …… 在一个C程序的main()函数中对add汇编子程序进行了调用: extern int add (int x,int y); //声明add为外部函数 void main(){ int a=1,b=2,c; c=add(a,b); //调用add子程序 …… } 当main()函数调用add汇编子程序时,变量a、b的值会给了r0和r1,回来成果由r0带回,并赋值给变量c。函数调用完毕后,变量c的值变成3。
4、C程序中内嵌汇编句子 在C言语中内嵌汇编句子能够完成一些高档言语不能完成或许不容易完成的功用。关于时刻急迫的功用也能够经过在C言语中内嵌汇编句子来完成。内嵌的汇编器支撑大部分ARM指令和Thumb指令,可是不支撑比如直接修正PC完成跳转的底层功用,也不能直接引证C言语中的变量。 嵌入式汇编句子在方式上独立界说的函数体,其语法格局为: __asm { 指令[;指令] …… [指令] } 其间“__asm”为内嵌汇编句子的关键字,需求特别注意的是前面有两个下划线。指令之间用分号分隔,假如一条指令占有多行,除最终一行外都要运用连字符“\”。
5、根据ARM的C言语与汇编言语混合编程举例 下面给出了一个向串口不断发送0x55的比如: 该工程的发动代码运用汇编言语编写,向串口发送数据运用C言语完成,下面是发动代码的全体结构: …… IMPORT Main AREA Init,CODE,READONLY; ENTRY …… BL Main ;跳转到Main()函数处的C/C++程序 …… END ;标识汇编程序完毕 下面是运用C言语编写的主函数: #include “..\inc\config.h” //将有关硬件界说的头文件包括进来 unsigned char data; //界说全局变量 void main(void){ Target_Init(); //对方针板的硬件初始化 Delay(10); //延时 data=0x55; //给全局变量赋值 while(1) { Uart_Printf(“%x”,data); //向串口送数 Delay(10); } }