IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> Keil下STM32的C与汇编语言混合编程 -> 正文阅读

[嵌入式]Keil下STM32的C与汇编语言混合编程

Keil下STM32的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<stdio.h>
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里。

通过调试来验证:

image-20211012124335115

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

image-20211012125403048

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

image-20211012125933048

可以验证的确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<stdio.h>
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

通过调试来验证是否成功

image-20211012132044166

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

image-20211012132415828

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

image-20211012132803891

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

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-10-13 11:36:15  更:2021-10-13 11:36:35 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 6:00:55-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码