Keil下STM32的C与汇编语言混合编程

一. C语言调用汇编函数

目录

一. C语言调用汇编函数

1.KILL创建项目

 2. 添加main.c和Func.s

3. 编写代码

二.  无参数调用汇编

 三. 有参数调用汇编

原汇编语言 Init_1函数的类型改为 int Init_1(init)

1. 代码修改

四. 汇编语言调用C函数

四. 总结

五. 参考链接


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语言程序之间的相互调用,在实验过程中出现的错误需要我们耐心仔细去发现问题并解决问题。

五. 参考链接

Keil下STM32的C与汇编语言混合编程

STM32的C与汇编语言混合编程【嵌入式】

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值