一. C语言调用汇编函数
目录
原汇编语言 Init_1函数的类型改为 int Init_1(init)
1.KILL创建项目
芯片选择:
STM32F103VE
2. 添加main.c和Func.s
main.c:
Func.s:
查看添加的文件:
添加成功!可以开始编写代码了。
3. 编写代码
main.c:
# include<stdio.h>
extern void Init_1(void);
int main(){
Init_1();
return 0;
}
注:用extern声明Init_1函数,再在main里调用
Func.s:
AREA MY_FUNCTION,CODE,READONLY ; 这一行必有的,除了MY_FUNCTION可以自己取名,其它都是模板
EXPORT Init_1 ; 与在c文件中定义的Init_1函数关联起来
; 高级语言中的声明和使用变量其实是对板子寄存器的使用,所以我们只需要直接使用寄存器即可
Init_1
MOV R1,#0 ; 设R1寄存器为i
MOV R2,#0 ; 设R2寄存器为j
LOOP ; 写在最左边的是程序段的段名,执行跳转程序时用到
CMP R1,#10 ; 比较R1和10的大小
BHS LOOP_END ; 如果R1大于等于10,则跳转到LOOP_END程序段,反之忽略该语句,直接执行下面的语句
ADD R2,#1 ; j++
ADD R1,#1 ; i++
B LOOP ; 循环
LOOP_END
NOP
END ; 必须空格后再写END,不然会被认为是段名,表示程序结束
二. 无参数调用汇编
编译 :
编译结果:
调试:
出错了,原因是因为没有装芯片,所以模拟调试
选择魔法棒,选择Debug
,勾选Use Simulator
,将左下角的Dialog DLL
中的内容改为DARMSTM.DLL
,将Parameter
的内容改为-pSTM32F103C8
重新调试:
调试出来结果了。
设置断点,方便我们观察变化:
运行:
R1和R2数据开始变化:
最后R1和R2都变成了0x0000000A,也就是十进制的10:
三. 有参数调用汇编
原汇编语言 Init_1函数的类型改为 int Init_1(init)
1. 代码修改
func.s:
AREA MY_FUNCTION,CODE,READONLY ; 这一行必有的,除了MY_FUNCTION可以自己取名,其它都是模板
EXPORT Init_1 ; 与在c文件中定义的Init_1函数关联起来
; 高级语言中的声明和使用变量其实是对板子寄存器的使用,所以我们只需要直接使用寄存器即可
Init_1
ADD R0,#100 ; 将传入的值+100
MOV PC,LR ; 返回R0
LOOP ; 写在最左边的是程序段的段名,执行跳转程序时用到
CMP R1,#10 ; 比较R1和10的大小
BHS LOOP_END ; 如果R1大于等于10,则跳转到LOOP_END程序段,反之忽略该语句,直接执行下面的语句
ADD R2,#1 ; j++
ADD R1,#1 ; i++
B LOOP ; 循环
LOOP_END
NOP
END ; 必须空格后再写END,不然会被认为是段名,表示程序结束
main.c:
# include<stdio.h>
extern int Init_1(int x);
int main(){
Init_1(100);
return 0;
}
重复上面的编译调试:
可以看见最开始R0的值是100,
当函数执行完后:
R0的值变成了0x000000C8,也就是200,达到了我们预期的值
四. 汇编语言调用C函数
修改代码:
func.s:
AREA MY_Function,CODE,READONLY
EXPORT Init_1 ; 与在c文件中定义的Init_1函数关联起来
IMPORT get11 ; 声明get11 为外部引用
; 高级语言中的声明和使用变量其实是对板子寄存器的使用,所以我们只需要直接使用寄存器即可
Init_1
MOV R1,#0 ; 设R1寄存器为i
MOV R2,#0 ; 设R2寄存器为j
LOOP ; 写在最左边的是程序段的段名,执行跳转程序时用到
CMP R1,#10 ; 比较R1和10的大小
BHS LOOP_END ; 如果R1大于等于10,则跳转到LOOP_END程序段,反之忽略该语句,直接执行下面的语句
ADD R2,#1 ; j++
ADD R1,#1 ; i++
BL get11 ; 调用get11,返回的值传入R0
B LOOP ; 循环
LOOP_END
NOP
END ; 必须空格后再写END,不然会被认为是段名,表示程序结束
main.c:
# include<stdio.h>
extern void Init_1(void);
int get11(void);
int main(){
printf("Begin...\n");
Init_1();
return 0;
}
int get11(){
return 11;
}
运行调试后:
R0就是11,输出正确
四. 总结
这次试验让我清楚了keil的工作原理,能大大提高工作效率,我学到了如何用汇编程序和c语言程序之间的相互调用,在实验过程中出现的错误需要我们耐心仔细去发现问题并解决问题。