栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

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

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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

文章目录
  • 一、c语言调用汇编语言
  • 二、修改init_1函数功能再次调用
  • 三、在汇编函数中调用c语言函数
  • 四、总结
  • 五、参考

一、c语言调用汇编语言

在main.c中调用在test.s中定义的init_1函数,并通过调试的方式跟踪寄存器的内容来验证。

值得注意的是,在ARM中,寄存器R0~R3保存的是函数的参数,当参数大于4个后,多余的参数将会被压入栈中。而返回结果会被保存在R0当中。

1.main.c代码

#include

extern void Init_1(void);

int main()
{
	Init_1();
	
	return 0;
}

2.test.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,不然会被认为是段名,表示程序结束


3.在keil中设置对应断点。

4.点击build后开始调试。按F11,可以看到R1、R2的值不断增加。

5.直到值变为0xA,也就是十进制的11的时候退出循环。

二、修改init_1函数功能再次调用

把init_1函数修改为传入一个整数x,然后返回x+100的值。
1.main.c代码

# include

extern int Init_1(int x);

int main(){
	
	int x=Init_1(1);
	printf("%d",x);
	
	return 0;
}

2.test.s代码

	
	AREA	My_Function,CODE,READonLY
	EXPORT 	Init_1  ; 与在c文件中定义的Init_1函数关联起来
	; 高级语言中的声明和使用变量其实是对板子寄存器的使用,所以我们只需要直接使用寄存器即可

Init_1
	ADD R0,#1     ; 将传入的值+1
	MOV PC,LR		; LR(R14)保存返回地址,PC(R15)是当前地址,把LR给PC就是从子程序返回,返回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,不然会被认为是段名,表示程序结束

3.设置断点

4.重新build后开始调试
进入init_1函数前R0寄存器的值

5.执行一次后R0的值变为0x65,也就是十进制的101。

6.继续调试,到调用printf函数,可以看到x的值为0x65,也就是十进制的101。

三、在汇编函数中调用c语言函数

在mian.c中定义一个fun函数,作用是把传入的一个整形参数+1再返回。
1.main.c代码

# include

extern int Init_1(int x);

int fun(int x);

int main(){
	
	int x=Init_1(1);
	printf("%d",x);
	
	return 0;
}

int fun(int x){
	return x+2;
}

2.test.s代码


	AREA	My_Function,CODE,READonLY
	EXPORT 	Init_1  ; 与在c文件中定义的Init_1函数关联起来
	import  fun    ; 声明get5 为外部引用

; 高级语言中的声明和使用变量其实是对板子寄存器的使用,所以我们只需要直接使用寄存器即可

Init_1
	ADD R0,#1	  ;将传入的值+1
	MOV R1,#0     ; 设R1寄存器为i
	MOV R2,#0	  ; 设R2寄存器为j
	BL fun  	  ; 调用fun,返回的值传入R0
	MOV PC,LR		;LR(R14)保存返回地址,PC(R15)是当前地址,把LR给PC就是从子程序返回,返回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,不然会被认为是段名,表示程序


3.重新设置断点

4.重新build再调试
R0初始值为1。

5.执行init_1函数后+1

6.执行完fun函数后再+2,最终结果为4

四、总结

通过这次实验,知道了在ARM中存储参数的寄存器为R0~R3,多余的会储存在栈中,返回结果也是储存在R0中。同时,学会了c语言和汇编语言的混合编程。

五、参考

https://blog.csdn.net/weixin_45919652/article/details/120631225

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/312033.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号