C语言如何与ARM汇编语言混合编程示例详解

目录
  • 一、ARM汇编语言简介
  • 二、C语言调用汇编语言
    • 1.无参数调用
    • 2.有参数调用
  • 三、汇编语言调用C语言
  • 四、总结
  • 五、参考文献

主要使用软件:keiL μVision5

一、ARM汇编语言简介

什么是汇编语言?汇编语言是任何一种适用于电子计算机、微处理器或其他可编程器件的低级语言。虽然被称为“低级语言”,但是并不是说汇编语言真的“低级”。特定的汇编语言和特定的机器语言指令集是一一对应的,不同平台之间不可直接移植。汇编语言主要包括传送指令、逻辑运算、移位指令、位操作、控制转移、串操作和输入输出等指令。

二、C语言调用汇编语言

1.无参数调用

在Keil中创建工程文件在我之前的博客中已经介绍了,这里不做过多介绍。

VScode + keil开发环境搭建安装使用过程 https://www.jb51.net/article/218432.htm

使用VSCode和VS2017编译调试STM32程序的实现 https://www.jb51.net/article/186069.htm

首先创建工程文件,然后添加CORE和Starup

然后鼠标右键点击左边工程文件中的Source Group,选择Add New Item…

依次添加Fun.s和main.c两个文件

Func.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段
LOOP_END
	NOP

	END				;必须空格后再写END,不然会被认为是段名,表示程序结束

main.c

#include<stdio.h>
 extern void Init_1(void);
  int main()
{
	 Init_1();
	 return 0;
}

注意:需要勾选软件调试,然后修改参数。刚开始选择的芯片是stmf103c8,所以此处Parameter填写-pSTM32F103C8

设置断点

可以通过寄存器变化观察程序运行情况

2.有参数调用

简单修改一下代码

Func.s

	AREA My_Function,CODE,READONLY		;这一行必有的 除了My_Function可以自己取名以外,其他都是模板
	EXPORT Init_1		;与在C文件中定义的Init_1函数关联起来
;高级语言中的声明和使用变量其实是对寄存器的使用,所以我们只需要直接使用寄存器即可
Init_1
	ADD R0,#100		;将传入的值+100
	MOV PC,LR		;返回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段
LOOP_END
	NOP
	END				;必须空格后再写END,不然会被认为是段名,表示程序结束

main.c

#include<stdio.h>
extern int Init_1(int x);

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

调试程序观察寄存器变化

此时R1寄存器的值为0x208,即520,调用成功。

三、汇编语言调用C语言

修改代码

Func.s

	AREA My_Function,CODE,READONLY		;这一行必有的 除了My_Function可以自己取名以外,其他都是模板
	EXPORT Init_1		;与在C文件中定义的Init_1函数关联起来
	IMPORT 	return1		;声明return1为外部引用
;高级语言中的声明和使用变量其实是对寄存器的使用,所以我们只需要直接使用寄存器即可
Init_1
	ADD R0,#100		;将传入的值+100
	MOV PC,LR		;返回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段
LOOP_END
	NOP
	END				;必须空格后再写END,不然会被认为是段名,表示程序结束

main.c

#include<stdio.h>
extern int Init_1(int x);
int return1(void);
int main()
{
	 int x = Init_1(420);
	 printf("%d",x);
	 return 0;
}
int return1(void)
{
	return 1;
}

编译并调试

可以看到R0的值变为了1,可见C函数被成功调用。

四、总结

本次实验需要学习C语言及汇编语言的相关知识,还需要了解C语言和汇编语言的参数如何调用,为以后的嵌入式打下一定基础。

五、参考文献

汇编语言(面向机器的程序设计语言)_百度百科 (baidu.com)

常用的ARM汇编指令

以上就是C与ARM汇编语言混合编程示例详解的详细内容,更多关于C与ARM汇编语言混合编程的资料请关注我们其它相关文章!

(0)

相关推荐

  • 汇编语言入门教程(这一篇足矣)

    汇编语言是一种最低级.最古老.不具有移植性的编程语言,它能够直接访问计算机硬件,所以执行效率极高,占用资源极少,一般用于嵌入式设备.驱动程序.实时应用.核心算法等. 汇编语言的缺点是开发周期特别长,实现一个简单的功能都非常麻烦,已经很少用来编写应用程序了. 1 本讲座以汇编初学者或对汇编一点也不了解的读者为对象,汇编高手不属于该范围,但强烈建议高手指导并增补.修改本文. 2 任何读者可以跟此贴,提出疑问,或解答其中的问题,但对于所有跟贴,水贴.内容有错.毫不相干贴将直接删除,有意义的贴可能会合并

  • C与汇编混合编程的实现示例

    目录 1. C语言内联汇编 2. C语言调用汇编函数 3. 汇编代码调用C语言函数 上一期中,使用链表的方式进行对不同任务的调用,实现的效果还是不错的,但是,任务在进行过程中不能进行来回的切换,必须要执行完,这是一个弊端,若不使用实时操作系统的情况下,如何切换呢,那就要说一下万能的汇编了,用汇编则可以做到任务的切换 首先我们知道,c与汇编的联合使用就三种情况,如下 1. C语言内联汇编 首先看一下代码 __inline int ADD(int input1,int intput2) { int

  • 从汇编看c++中引用与指针的使用分析

    首先是引用情形下的c++源码: 复制代码 代码如下: void add(int a, int b, int&c) {    c = a + b;} int main() {    int a = 1;    int b = 2;    int c = 0;    add(a, b, c); } 下面是main对应的汇编码: 复制代码 代码如下: ; 6    : int main() { push    ebp    mov    ebp, esp    sub    esp, 12      

  • C语言中的数组和指针汇编代码分析实例

    今天看<程序员面试宝典>时偶然看到讲数组和指针的存取效率,闲着无聊,就自己写了段小代码,简单分析一下C语言背后的汇编,可能很多人只注重C语言,但在实际应用当中,当出现问题时,有时候还是通过分析汇编代码能够解决问题.本文只是为初学者,大牛可以飘过~ C源代码如下: 复制代码 代码如下: #include "stdafx.h" int main(int argc, char* argv[]) {        char a=1;        char c[] = "

  • C语言如何与ARM汇编语言混合编程示例详解

    目录 一.ARM汇编语言简介 二.C语言调用汇编语言 1.无参数调用 2.有参数调用 三.汇编语言调用C语言 四.总结 五.参考文献 主要使用软件:keiL μVision5 一.ARM汇编语言简介 什么是汇编语言?汇编语言是任何一种适用于电子计算机.微处理器或其他可编程器件的低级语言.虽然被称为"低级语言",但是并不是说汇编语言真的"低级".特定的汇编语言和特定的机器语言指令集是一一对应的,不同平台之间不可直接移植.汇编语言主要包括传送指令.逻辑运算.移位指令.位

  • Go语言基础切片的创建及初始化示例详解

    目录 概述 语法 一.创建和初始化切片 make 字面量 二.使用切片 赋值和切片 切片增长 遍历切片 总结 总示例 示例一  两个slice是否相等 示例二 两个数字是否包含 概述 切片是一种动态数组 按需自动改变大小 与数组相比,切片的长度可以在运行时修改 语法 一.创建和初始化切片 make 使用内置函数make()创建切片: var slice []type = make([]type, len, cap) //简写: slice := make([]type, len, cap) 字面

  • Go语言基础go build命令用法及示例详解

    目录 go build 一个Go项目在GOPATH下,会有如下三个目录 使用: 注意: go build 1. 用于测试编译多个包或一个main包 2. build命令编译包丢弃非main包编译结果,只是检查是否能够被编译 3. 保留main包编译结果 一个Go项目在GOPATH下,会有如下三个目录 bin存放编译后的可执行文件 pkg存放编译后的包文件 src存放项目源文件 一般,bin和pkg目录可以不创建,go命令会自动创建(如 go install),只需要创建src目录即可. 使用:

  • Go语言基础变量的声明及初始化示例详解

    目录 一.概述 二.声明变量 三.编译器推导类型的格式[一定要赋值] 四.短变量声明并初始化 五.匿名变量--没有名字的变量 六.注意 七.案例 一.概述 变量的功能是存储用户的数据 二.声明变量 Go语言的每一个变量都拥有自己的类型,必须经过声明才能开始用 变量的声明格式: var <变量名称> [变量类型] var a int //声明一个整型类型的变量,可以保存整数数值 var b string //声明一个字符串类型的变量 var c float32 //声明一个32位浮点切片类型的变

  • Go语言基础if条件语句用法及示例详解

    目录 概述 语法 格式规则 概述 条件语句需要开发者通过指定一个或多个条件 并通过测试条件是否为 true 来决定是否执行指定语句 并在条件为 false 的情况再执行另外的语句. 语法 package main func main() { //第一种格式 if 条件表达式 { 语句1 } //第二种格式 if 初始化表达式; 条件表达式 { 语句1 } //第三种格式 if 初始化表达式; 条件表达式 { 语句1 }else{ 语句2 } //第四种格式 if 初始化表达式; 条件表达式 {

  • C语言实现生成新春福字的示例详解

    目录 主要代码 字面量以及数据结构 定义一个回调函数,刷新福字 应用初始化程序 主程序 效果展示 快新年了,支付宝扫福活动又开始了,每次都要百度找福,这次不想找了,自己写一个程序生成各种字体的福字. 主要代码 字面量以及数据结构 #define FONT_DISPLAY "福" // g_fu_label中的每一个控件都是一个福字 static GtkWidget *g_fu_label[3][3]; // 记录所有的字体family typedef struct { int n_fa

  • R语言使用cgdsr包获取TCGA数据示例详解

    目录 TCGA数据源 TCGA数据库探索工具 查看任意数据集的样本列表方式 选定数据形式及样本列表后获取感兴趣基因的信息,下载mRNA数据 选定样本列表获取临床信息 综合性获取 下载mRNA数据 获取病例列表的临床数据 从cBioPortal下载点突变信息 从cBioPortal下载拷贝数变异数据 把拷贝数及点突变信息结合画热图 TCGA数据源 众所周知,TCGA数据库是目前最综合全面的癌症病人相关组学数据库,包括的测序数据有: DNA Sequencing miRNA Sequencing P

  • go语言reflect.Type 和 reflect.Value 应用示例详解

    目录 一.使用 reflect.Type 创建实例 二.使用 reflect.Value 调用函数 一.使用 reflect.Type 创建实例 在通过 reflect.TypeOf 函数获取到变量的反射类型对象之后,可以通过反射类型对象 reflect.Type 的 New 函数来创建一个新的实例,注意这个实例的类型是 reflect.Type 类型的. package main import ( "fmt" "reflect" ) func main() { v

  • Go语言学习教程之结构体的示例详解

    目录 前言 可导出的标识符 嵌入字段 提升 标签 结构体与JSON相互转换 结构体转JSON JSON转结构体 练习代码步骤 前言 结构体是一个序列,包含一些被命名的元素,这些被命名的元素称为字段(field),每个字段有一个名字和一个类型. 结构体用得比较多的地方是声明与数据库交互时需要用到的Model类型,以及与JSON数据进行相互转换.(当然,项目中任何需要多种数据结构组合在一起使用的地方,都可以选择用结构体) 代码段1:声明一个待办事项的Model类型: type Todo struct

  • C语言动态内存管理malloc柔性数组示例详解

    目录 1.1为什么存在动态内存管理 1.2动态内存管理函数 1.2.1malloc 1.2.2free 1.2.3calloc 1.2.4realloc 1.3动态内存管理函数易错点 1.3.1对NULL指针的解引用操作 1.3.2对动态开辟空间的越界访问 1.3.3对非动态开辟内存使用free释放 1.3.4使用free释放一块动态开辟内存的一部分 1.3.5对同一块动态内存多次释放 1.3.6动态开辟内存忘记释放(内存泄漏) 2.1常见相关笔试题 2.2C/C++语言中的内存开辟 2.3柔性

随机推荐