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 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 在Keil下用C语言调用汇编函数 -> 正文阅读

[C++知识库]在Keil下用C语言调用汇编函数

一、在C函数中调用汇编函数

1.1 调用不带参数的汇编函数

关于建立MDK工程的具体操作,可参考我的另一篇博文:
基于MDK创建纯汇编语言的STM32工程

  1. 新建一个main.c文件
#include <stdio.h>
extern void Init_1(void);
int main()
{
	Init_1();
	return 0;
}
  1. 新建一个func.s文件
    AREA	My_Function,CODE,READONLY
	EXPORT Init_1
 
Init_1
	MOV R1,#0
	MOV R2,#0
	
LOOP
	CMP R1,#10
	BHS LOOP_END
	ADD R2,#1
	ADD R1,#1
	B LOOP
	
LOOP_END
	NOP
	
	END

关于上述汇编代码的解释:

  • EXPORT:将c文件中定义的函数相关联;
  • Init_1LOOPLOOP_END:程序段名,是跳转程序的参照;
  • MOV R1,#0MOV R2,#0:将R1,R2寄存器的初值设置为0;
  • CMP R1,#10BHS LOOP_END:将R1的值与10相比较,若R1大于10,就调到LOOP_END
  • ADD R2,#1ADD R1,#1:R1,R2寄存器加1;
  • B LOOP:再次进入循环的标志;
  • END:程序结束。

关于汇编代码格式的注意事项:

  1. 开头部分:AREA My_Function ,CODE,READONLY
    这个指令一定不要顶格写!
  2. 中间部分:程序名必须顶格写;
  3. 末尾部分:必须空格后再写END,不然会被认为是段名,表示程序结束;

在这里插入图片描述

  1. 仿真调试
    使用单步调试,可以看到R1从0变到9,再变为A(10在16进制下为A)时 ,跳出汇编程序,具体过程如下所示:
    初始状态:
    在这里插入图片描述
    R1变为0:
    在这里插入图片描述
    R1变为1:
    在这里插入图片描述
    R1变为2:
    在这里插入图片描述
    一直执行,到9:
    在这里插入图片描述
    最后到A:
    在这里插入图片描述
    跳出循环:
    在这里插入图片描述

1.2调用带形参的汇编函数

  1. 修改代码

将原汇编语言 Init_1函数的类型改为 int Init_1(init) ,此函数功能修改为 传入一个整型数x,函数运行后返回整型数 x+100;

  • 修改main.c
#include <stdio.h>
extern int Init_1(int a);
int main()
{
	Init_1(5);
	return 0;
}
  • 修改func.s
Init_1
    ADD R0,R0,#100	;R0记录传入的形参,并且执行R0=R0+100;
	BX LR           ;跳转的LR的地址执行,在这里,LR记录main函数调用子函数的返回地址

在这里插入图片描述

之所以让R0加100,是因为在arm编程里,函数调用过程中,子函数的参数值传递按顺序存放在R0、R1、R2、R3里,超过4个参数值传递放栈帧里,所以我们给定的参数值默认是放在R0中的,要想实现x+100,就要对R0寄存器加100。

  1. 进入调试:
    在这里插入图片描述
    可以看到R0初始值为十六进制下的78,进入单步运行后,R0变为5:
    在这里插入图片描述
    再次点击进入汇编文件,R0加了100,变为16进制下的105为69
    在这里插入图片描述

二、在汇编函数中调用c函数

在c文件中写入函数Init_1,将主函数放入汇编文件当中,可以发现,将以前的导入函数EXPORT改为了导入INPORT

2.1 代码文件

  1. main.c
#include<stdio.h>
extern int Init_1();
int Init_1()
{
	int x=5;
	return x+100;
}
  1. func.s
    IMPORT Init_1
	AREA MYCODE, CODE
 
	EXPORT __main
 
__main
    BL Init_1
		
	END

在这里插入图片描述

注意:ARM汇编指令不支持顶格写,否则不能识别;声明变量时不要有空格,不然会出现奇奇怪怪的错误。

2.2 仿真调试

调试方法依旧如上,编译无误后进入仿真调试
初始状态:
在这里插入图片描述

F5跳入主函数的断点处
在这里插入图片描述

再经过单步调试后,可以看到寄存器R0变为16进制的105,即69 ,证明试验无误。
在这里插入图片描述

三、汇编函数与c函数混合调用

3.1 代码文件

  • main.c
extern int SUM_ASM(void);
int sum(int a,int b)
{
	int c;
	a=100;
	b=200;
	c=a+b;
	return c;
}
int main(void)
{
	SUM_ASM();
	return 0;
}
  • func.s
    AREA	 My_Function ,CODE,READONLY  	
	IMPORT sum
	EXPORT SUM_ASM
		
	ENTRY

SUM_ASM
	LDR R0,=0X3
	LDR R1,=0X4
	BL sum 
	MOV PC,LR
	
	
	END

在这里插入图片描述

3.2 仿真调试

初始状态:
在这里插入图片描述
运行结果:
在这里插入图片描述

四、总结C语言与汇编语言混合编程的规则

4.1寄存器的使用规则

  • R1~R3通常用来传递函数参数,当参数个数多于4个时,使用堆栈来传递参数,此时R0-R3可记作A1-A4;
  • R4~R11用来保存程序运算的中间结果或函数的局部变量,因此当进行子程序调用时要注意对这些寄存器的保存和恢复,此时R4-R11可记作V1-V8;
  • R12通常用来作为函数调用过程中的临时寄存器,用于保存堆栈指针SP,当子程序返回时使用该寄存器出栈,记作IP;
  • R13寄存器是堆栈寄存器(SP),用来保存堆栈的当前指针
  • R14寄存器是链接寄存器(LR),用来保存函数的返回地址
  • R15寄存器是程序寄存器(PC),指向程序当前的地址

4.2 堆栈的使用规则

ATPCS规定堆栈采用满递减类型(FD,Full Descending),即堆栈通过减小存储器地址而向下增长,堆栈指针指向内含有效数据项的最低地址。

4.3 参数的传递规则

  1. C语言在ARM中函数调用时,如果形参个数少于或等于4,则形参由R0,R1,R2,R3四个寄存器进行传递;若形参个数大于4,大于4的部分必须通过堆栈进行传递,且压入堆栈的顺序是与函数中形参的顺序相反。
  2. 对于X86平台,32位程序使用栈传递,而64位程序则根据参数的个数而不同。当参数少于6,使用寄存器传递参数;当参数大于6,多出来的参数使用栈传递。
  3. 子程序的返回结果为一个32位整数时,通过R0返回;返回结果为一个64位整数时,通过R0和R1返回;依此类推。结果为浮点数时,通过浮点运算部件的寄存器F0、D0或者S0返回。

五、总结

无论是在汇编程序中调用c程序,还是c程序中调用汇编程序,或者是二者相互嵌套,都涉及到子程序的调用、参数的传递、子程序的返回等问题,以及寄存器、堆栈的存储规则。在了解这些具体调用规则后,再通过设计程序进行仿真试验,更能理解每一步的执行过程,掌握其运行原理。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-10-15 11:36:23  更:2021-10-15 11:36:34 
 
开发: 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/24 2:32:33-

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