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

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

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

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

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

文章目录
        • Keil下STM32的C与汇编语言混合编程
          • 1、函数调用时的规则
          • 2、C语言调用汇编
          • 3、汇编调用C函数

1、函数调用时的规则

1、父函数与子函数间的入口参数依次通过R0–R3这4个寄存器传递。父函数在调用子函数前先将参数存入到R0–R3中,若只有一个参数则使用R0传递,2个则使用R0和R1传递,依次类推,当超过4个参数时,其它参数通过栈传递。当子函数运行时,根据自身参数个数自动从R0~R3或者栈中读取参数。
2、子函数通过R0寄存器将返回值传递给父函数。子函数返回时,将返回值存入R0,当返回到父函数时,父函数读取R0获得返回值。
3、发生函数调用时,R0—R3是传递参数的寄存器,即使是父函数没有参数需要传递,子函数也可以任意更改R0–R3寄存器,无需考虑会破坏它们在父函数中保存的数值,返回父函数前无需恢复其值。AAPCS规定,发生函数调用前,由父函数将R0–R3中有用的数据压栈,然后才能调用子函数,以防止父函数R0–R3中的有用数据被子函数破坏。
4、R4——R11为普通的通用寄存器,若子函数需要使用这些寄存器,则需要将这些寄存器先压栈然后再使用,以免破坏了这些寄存器中保存的父函数的数值,子函数返回父函数前需要先出栈恢复其数值,然后再返回父函数。AAPCS规定,发生函数调用时,父函数无需对这些寄存器进行压栈处理,若子函数需要使用这些寄存器,则由子函数负责压栈,以防止父函数R4R11中的数据被破坏。
5、编译器在编译时就确定了函数间的调用关系,它会使函数间的调用遵守3、4条规定。但编译器无法预知中断函数的调用,被中断的函数无法提前对R0–R3进行压栈处理,因此需要在中断函数里对它所使用的R0–R11压栈。对于中断函数,不遵守第3条规定,遵守第5条规定。
6、R12寄存器在某些版本的编译器下另有它用,用户程序不能使用,因此我们在编写汇编函数时也必须对它进行压栈处理,确保它的数值不能被破坏。
7、R13寄存器是堆栈寄存器(SP),用来保存堆栈的当前指针。
8、R14寄存器是链接寄存器(LR),用来保存函数的返回地址。
9、R15寄存器是程序寄存器(PC),指向程序当前的地址。

原文链接:https://blog.csdn.net/STCNXPARM/article/details/108742047

2、C语言调用汇编

main.c

# include
extern int add(int x);
	int sum=0;
int main()
	{
  sum=add(7);
		return 0;
}

汇编函数fun.s

    AREA   Add,CODE,READonLY
	EXPORT add
		
add
    mov R1,#100
	ADD R0,R0,R1
	mov pc,lr
	end

程序的入口是main,在main里调用汇编的函数.

在C语言中,要extern 一个函数声明即可,然后这个函数在汇编里面实现。

在汇编里面,用EXPORT 把C语言定义的函数名引进来,再开始编写函数名开始的段

由函数调用规则可知,4个以内的参数,直接存放在R0~R3 这4个寄存器里面。

4个以后的参数放在堆栈里。

如果函数有返回值,那么返回值放在R0里。

通过调试来验证:

由寄存器R0的值可知,c函数的参数值直接保存在R0中

通过汇编函数,将R1赋值为100,然后通过add,将R0与R1寄存器中的值求和重新放入R0中,作为函数的返回值

可以验证的确R0是存放返回值的

3、汇编调用C函数

汇编程序的书写要遵循ATPCS规则,以保证程序调用时参数正确传递。在汇编程序中调用C程序的方法为:首先在汇编程序中使用import伪指令事先声明将要调用的C语言函数;然后通过BL指令来调用C函数。

汇编代码ss.s

    import ADD
    AREA   Add,CODE,READonLY
	EXPORT add
		
add
	BL ADD
	mov pc,lr
	end

main.c

# include
extern int add(int a);
int main()
	{
  add(3);
		return 0;
}

add.c

int ADD(int a)
{
return a+100;
}

程序入口为main函数,通过main函数调用汇编函数add,在通过汇编函数add调用c函数ADD

通过调试来验证是否成功

通过主函数中add的参数值赋给R0寄存器,因为只有一个参数,所以只用一个寄存器R0

汇编语言执行BL ADD,调用C函数,此时程序进入ADD函数中,寄存器R0的值还未发生改变。

通过函数ADD,寄存器R0的值发生改变。

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

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

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