keil下C与汇编语言混合编程
文章目录
- 前言
- 一、在c函数中调用汇编函数
- 1.调用不带参数的汇编函数
- 2.调用带形参的汇编函数
- 二、在汇编函数中调用c函数
- 三、汇编函数与c函数混合调用
- 总结
前言
如今C语言很强大,在嵌入式编程当中应用广泛,但是为什么还要在c语言中还要嵌入汇编语言,对于没有学过汇编语言的情况下,难学又不易理解?
因为汇编语言实时性比C语言好,占用单片机资源少,生成的执行文件更小,汇编语言程序直接被转换成机器指令。执行效率更高,这对某些嵌入式领域所要求的高实时性有一定帮助,此外,有时在涉及到硬件底层操作的代码时必须使用汇编代码。
所以说,在一些性能要求比较高的情况下,通常会在c语言程序在内嵌一些汇编代码。下面让我们来体会一下,在Keil环境下C与汇编语言的混合使用。
一、在c函数中调用汇编函数
关于新建一个MDK工程,并添加一个新项目的步骤
可参考我的另一篇博客
MDK下汇编语言调试分析
1.调用不带参数的汇编函数
- 新建一个main.c文件
#include <stdio.h>extern void Init_1(void);
int main()
{Init_1();return 0;
}
- 新建一个func.s文件
AREA My_Function ,CODE,READONLY EXPORT Init_1 ;将Init_1导出,供工程中其他文件调用实现Init_1MOV R1, #1 ;将立即数1放到寄存器R1中,即将R1寄存器初始化为1MOV R2, #2 ;将立即数2放到寄存器R2中,即将R2寄存器初始化为2LOOP ;循环开始的地方CMP R1, #10 ;比较R1与10的大小BHS LOOP_END ;如果R1大于等于10,则跳转到LOOP_END,循环结束;否则,执行下一语句ADD R2, #1 ;R2=R2+1;ADD R1, #1 ;R1=R1+1;B LOOP ;无条件跳转到LOOP执行下一次循环LOOP_END ;循环结束NOP ;空指令,延时等待END
注意:
必须空格后再写END,不然会被认为是段名,表示程序结束,还有就是
AREA My_Function ,CODE,READONLY
这个指令一定不要顶格写!
这个指令一定不要顶格写!
这个指令一定不要顶格写!
汇编指令对格式要求比较高,大家在编写代码时一定要注意!
- 开始调试
- 单步执行
程序执行到如上图所示时,可以发现R0
,R1
寄存器的值已经变为1
,2
2.调用带形参的汇编函数
下面由于要涉及到arm寄存器的一些分析,所以我在这先简单介绍一下。
R1~R3通常用来传递函数参数
R4~R11用来保存程序运算的中间结果或函数的局部变量
R12通常用来作为函数调用过程中的临时寄存器
R13寄存器是堆栈寄存器(SP),用来保存堆栈的当前指针
R14寄存器是链接寄存器(LR),用来保存函数的返回地址
R15寄存器是程序寄存器(PC),指向程序当前的地址
- 修改代码
将原汇编语言 Init_1
函数的类型改为 int Init_1(init)
,此函数功能修改为 传入一个整型数x,函数运行后返回整型数 x+100
修改main.c
#include <stdio.h>
extern int Init_1(int a);
int main()
{Init_1(66);return 0;
}
修改func.s
Init_1ADD R0,R0,#100 ;R0记录传入的形参,并且执行R0=R0+100;BX LR ;跳转的LR的地址执行,在这里,LR记录main函数调用子函数的返回地址
- 初始化形参
可以看到我传入的函数参数是66,转换为16进制即为0x42
,说明函数形参已被写入寄存器R0
中
- 记录返回地址
我们看到在进入子函数时,一般有两个准备工作
1)初始化形参
2)R14(LR)寄存器值发生变化,记录从子函数返回当前函数的地址
- 进入子函数、执行指令
我们看到,下一条指令执行是R0=R0+0x64
,此时R0的值为0x42,我们可以预测执行完这步,R0的值应变为0xA6
果然R0的值变为0xA6
,如下图
- 返回主程序
当程序运行到如上图所示时,点击单步调试,注意观察到R14(LR)中的地址0x080003D5
-1被加载到R15(PC)指针,PC指针指向该地址0x080003D4
,即可返回主程序。
至此,一个函数的调用过程到此为止。
本例是以一个参数为例的,但当函数参数多于4个时,所调用的方式有所不同。前4个参数分别用R0~R3寄存器来记录,多余参数被加载到内存中使用栈来传递。
关于ARM体系下有多个函数形参的情况下,我写了一篇博客具体分析了一下
ARM体系下函数形参调用寄存器详解
二、在汇编函数中调用c函数
- 在
main.c
中修改代码
int sum(int a,int b)
{int c;a=100;b=200;c=a+b;return c;}
- 在
func.s
中修改代码
AREA My_Function ,CODE,READONLY IMPORT sumENTRYEXPORT __main ;注意这里有两个下划线,中间没空格__main ;注意这里有两个下划线,中间没空格BL sumBX LREND
- 仿真调试
调用子函数的过程与c文件调用汇编函数的过程大同小异,有兴趣的话可以自己尝试一下仿真跟踪调试。
注意:
ARM汇编指令不支持顶格写,否则不能识别;声明变量时不要有空格,不然会出现奇奇怪怪的错误。
三、汇编函数与c函数混合调用
- 修改
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 sumEXPORT SUM_ASMENTRYSUM_ASMLDR R0,=0X3LDR R1,=0X4BL sum MOV PC,LREND
- 小结
此代码实现了在c函数中调用汇编函数,再从汇编函数中调用c函数,调用方式与之前大同小异,但是了解c程序和汇编程序相互调用,混合编程还是很有帮助的。
如在MDK下stm32程序的执行过程为
先执行.s的汇编程序,再.s文件中执行以下操作
- 初始化堆栈指针 SP=_initial_sp
- 初始化 PC 指针 =Reset_Handler
- 初始化中断向量表
- 配置系统时钟
- 调用 C 库函数 _main 初始化用户堆栈,从而最终调用 main 函数去到 C 的世界
然后再跳转到main函数,执行一些c语言程序。
在一些对性能要求比较高的情况下,有时也会在c语言程序在内嵌一些汇编代码。
总结
无论是在汇编程序中调用c程序,还是c程序中调用(内嵌)汇编程序,往往都涉及到子程序的调用、参数的传递、子程序的返回等问题。不同的语言有着不同程度的指令集封装,在了解这些函数调用过程时,首先要初步了解ATPCS(ARM-Thumb Processor Call standard),其核心内容是子程序调用的基本规则和堆栈的使用约定等。
此外,了解了这些子程序的具体调用规则,设计程序仿真调试去验证、理解每一步如何得来,亲自实践操作对于理解子程序的调用方式是很有帮助的。
以上是我的相关学习体会,如有问题,望大家不吝指教。
参考书籍
1.嵌入式c语言自我修养 从芯片、编译器到操作系统 电子工业出版社 王利涛著
2.<STM32库开发指南–基于野火指南者开发板>
keil下C与汇编语言混合编程相关推荐
- keil4c语言和汇编混合,keil C语言与汇编语言混合编程
keil C语言与汇编语言混合编程 1. C语言中嵌入汇编 1.在 C 文件中要嵌入汇编代码片以如下方式加入汇编代码: #pragma ASM ; Assembler Code Here #pragm ...
- c语言与汇编语言混合编程实验,C语言与汇编语言混合编程实验
混合编程方法: 模块链接法 汇编指令嵌入法 1: 模块链接法则 模块链接法是指分别用汇编语言和C语言实现独立的模块(或子程序),再用链接程序把各模块生成的obj文件连接成一个可执行程序. 1:C语言调 ...
- C语言数据交换算法和伪指令,补充:单片机c语言与汇编语言混合编程.ppt
补充:单片机c语言与汇编语言混合编程 reg51.h和reg52.h:实质上是没有区别的,都是一些特殊功能寄存器的申明 sfr P0 = 0x80; sfr P1 = 0x90; sfr P2 = 0 ...
- 汇编c语言混合编程pdf,C语言及汇编语言混合编程的方法.pdf
维普资讯 1993矩 化 工 电 子 计 算 第 2期 C语言与汇编语言混合编程的方法 f/1) (南京犬李葛于如丽顶吾学系) 摘 要 本文通过实例阐述了当前较为漉行的两种c语盲 (Microsoft ...
- c语言混合编程 pdf,C语言与汇编语言混合编程的方法.pdf
C语言与汇编语言混合编程的方法 维普资讯 讫 梅 龄 施 扰 绝 埔 综 勿 穗 直 触 搔 拌 橱 悬 邱 舟 絮 颈 茬 辞 乏 味 绞 涡 菊 黄 宜 悄 条 搬 悄 俱 泼 洋 醚 檀 测 易 ...
- ARM下C语言和汇编语言混合编程
文章目录 一. 在C语言中调用汇编语言 1. 编写代码 2. 调试验证 二. 在汇编语言中调用C语言 1. 编写代码 2. 调试验证 关于函数的传递参数以及接受返回值的原理,在另一篇博客:X86与AR ...
- c语言汇编混合编程方法,C语言和汇编语言混合编程方法
摘要: C语言是一种高级的面向过程的开发语言,汇编语言是一种低级的面向机器的编程语言.两者在程序设计开发方面各有优劣,目前两者的混合编程得到了广泛的应用.本文通过具体的实例,说明了混合编程的基本方法, ...
- c语言与汇编语言混合编程
如何从汇编语言过渡到c语言? 从编译过程谈起 编译小知识 源代码编译后得到目标文件 (二进制文件) 不同语言可编译得到相同格式的目标文件 链接器负责将目标文件组装得到可执行文件 老生常谈的问题... ...
- STM32的C与汇编语言混合编程
本次我们要运用到汇编语言,并且将其与c混合编程.内容较多. 一.在c语言中调用汇编语言 新建一个工程 new project 芯片型号,STM32F103VE 配置如下 创建c文件 代码部分几乎相同, ...
最新文章
- Rocksdb 的优秀代码(二)-- 工业级 打点系统 实现分享
- 魔幻!2021年,6种将死的编程语言?
- 深入理解int a[5];
- 数学建模——线性规划模型详解Python代码
- Kubernetes 稳定性保障手册 -- 可观测性专题
- ceil和floor
- 高仿真的类-单例工厂的顶层设计
- 字符串得结果!Java数组模拟栈以实现中缀表达式综合计算器,字符串表达式计算器
- linux自动启动network服务,Windows/Linux 创建开机启动服务
- timer数据库总显示连接不上服务器,asp.net 上传服务器后,MSSQL数据库连接问题
- 关于request.getParameter(java.lang.String name)
- 技巧:你未必知道的IE8九大功能
- 最大流问题(超详细!!!)
- 【数据分析】如何构建指标体系 设计一份优质报表
- CTSCAPIOTHUPC2018颓废记
- Java通过名字查询缘分,姓名缘分配对 从姓名笔画看两人姻缘
- 如何设置网页标题图标 FavIcon
- ffmpeg命令:wav转pcm,pcm转wav
- 基于 bioMart 构建绵羊(非常见物种) OrgDb 包/数据库
- GBase 8a 虚拟集群
热门文章
- Win10蓝牙开关突然消失不见 已经解决方法2023.2.11
- 使用 Flutter 创建自适应应用
- Linux搭建samba文件共享服务器,实现基于Linux和Windows的共享文件服务
- 年会 司庆 主体活动 婚庆 拓展 复用抽奖软件
- python个人所得税怎么写分录_缴纳的个人所得税的会计分录怎么写?
- 超级玛丽HTML5源代码学习------(四)
- 【树莓派4B:安装QT5开发环境】
- kettle 筛选数据 并根据关键字段去重 设计
- 程序员能有什么好出路?前路漫漫,望长风破浪!
- android recyclerview 横向移动,RecyclerView实现纵向和横向滚动