目录
一、ATPCS中寄存器的使用规则
二、ARM程序设计
2.1 创建一个新工程
2.2 编写C语言代码和汇编代码
2.2.1 建立C语言文件
2.2.2 添加汇编文件
三、C语言调用汇编语言
3.1 无参数调用
3.2 有参数调用
四、汇编语言调用C语言
五、总结
R0——R3用于子程序间参数的传递,可以记作A1——A4 |
R4——R11用于保存子程序中的局部变量,可记作V1——V8 |
R12用作子程序间的scratch寄存器(用于保存SP,在函数返回时使用该寄存器出栈),可记作IP |
R13用作数据栈指针,可记作SP,进入与退出子程序时,SP必须相等 |
R14用作链接寄存器(保存子程序的返回地址),可记作LR |
R15用作程序计数器,可记作PC,不能用于其他用途 |
此时我们创建完毕。
在main2.c中加入C语言代码:
#include<stdio.h> extern void Init_1(void); int main(){ Init_1(); return 0; }
在fun1.s文件中加入下面的代码
AREA My_Function,CODE,READONLY EXPORT Init_1 Init_1 MOV R1,#0 MOV R2,#0 LOOP CMP R1,#10 BHS LOOP_END ADD R2,#1 ADD R1,#1 B LOOP LOOP_END NOP END
开始安插断点
编译后调试
出现这样的视图,然后我们开始按F5来不断调试观察。
……
可以观察到每按一次F5调试,R1和R2的值从0一直加1,直到加到A为止。
说明了我们循环加1的调用成功了。
首先我们改掉main2.c和fun1.s中的代码,如下:
# include<stdio.h> extern void Init_1(void); int get5(void); int main(){ printf("Begin...\n"); Init_1(); return 0; } int get5(){ return 5; }
AREA MY_Function,CODE,READONLY EXPORT Init_1 Init_1 ADD R0,#100 MOV PC,LR LOOP CMP R1,#10 BHS LOOP_END ADD R2,#1 ADD R1,#1 B LOOP LOOP_END NOP END
接下来设置断点
开始调试
可以看到多次调试后,我们得到xx的值为0x6E,为110,所以参数调用成功。
我们再次更改main2.c和fun1.s的代码。
#include<stdio.h> extern void Init_1(void); int get5(void); int main(){ printf("Begin...\n"); Init_1(); return 0; } int get5(){ return 5; }
AREA MY_Function,CODE,READONLY EXPORT Init_1 IMPORT get5 Init_1 MOV R1,#0 MOV R2,#0 LOOP CMP R1,#10 BHS LOOP_END ADD R2,#1 ADD R1,#1 BL get5 B LOOP LOOP_END NOP END
重新设置断点
开始编译并调试
多次调试调用后,R0成功变成了5,所以成功调用了。
本次实验是第一次尝试两种语言一起混编,一开始没有注意到断点的重要性,在老师给的资料下理解并学会了断点的运用,然后就成功完成了实验,也通过寄存器的观察,实际感受到了两种语言之间的互相调用。