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