当前位置: 首页 > article >正文

ARM与C语言的混合编程【嵌入式系统】

ARM与C语言的相互调用【嵌入式系统】

  • 前言
  • 推荐
  • ARM与C语言的相互调用
    • 说明
    • ARM7汇编语言与C语言间的模块接口
    • ARM7汇编程序与C程序间变量互访
    • ARM7汇编程序调用C程序
    • C程序调用汇编程序
    • C程序中内嵌ARM7汇编代码
  • 最后

前言

以下内容源自《【嵌入式系统】》
仅供学习交流使用

推荐

Keil 4 安装教程及简单使用【嵌入式系统】

ARM简单程序设计【嵌入式系统】

ARM与C语言的相互调用

说明

需要下载Keil for C51

可以看Keil 4 安装教程及简单使用【嵌入式系统】

ARM7汇编语言与C语言间的模块接口

ARM7汇编程序与C程序间变量互访

①汇编程序访问C程序中的变量
具体操作步骤:
在C程序中,将供汇编程序访问的变量用关键字extern声明为全局外部变量;
汇编程序中,用伪指令IMPORT引入C程序中声明的全局变量;
使用伪指令LDR读取这个全局变量的地址;
使用指令LDR读取这个全局变量的值;
在汇编程序中使用这个全局变量;

②C程序访问汇编程序中的变量
具体操作步骤:
在汇编语言程序中,用伪指令“global”定义全局变量,变量名必须是下划线“_”为首字符的字母数字串;
C程序中将该变量声明为外部变量,即可访问汇编程序定义的全局变量。

例:汇编程序和C程序间变量互访

/* print.c 定义全局变量,并作为主程序 */
#include <stdio.h>
extern int g_var = 124;	/* 全局变量 */
extern asmVisit(void); 	/* 汇编程序中声明的全局函数 */
extern int _multiple;	/* 声明汇编程序中的全局变量_multiple为外部变量 */
int main()
{
printf("Original value of g_var is: %d  \n ", g_var);
asmVisit();		/* 调用汇编程序中的函数,访问全局变量g_var */
printf("mult is %d",_multiple); 	/* 访问汇编程序中全局变量_multiple */
printf(" Modified value of g_var is: %d", g_var);
return 0;
} 
; visit.s文件
	AREA asmfile, CODE, READONLY
	EXPORT asmVisit	; 声明全局函数,供C程序调用??
	IMPORT g_var		; 引入在C程序中声明定义的全局变量
	GLOBAL _multiple	; 声明全局变量,供C程序访问
asmVisit
	LDR	R0,	=g_var
	LDR	R1,	[R0]
	LDR	R2,  	=_multiple
	LDR	R2, 	[R2]
	MOV	R3,   	R1,   LSL R2	; 将R1中的值扩大指定的倍数
	STR	R3,	[R0]
	MOV	PC,	LR

	AREA asmData, DATA, READWRITE
_multiple DCD 2
	END 

ARM7汇编程序调用C程序

汇编程序中调用C函数,只需在汇编程序中用伪指令IMPORT将需要调用的C函数名引用即可,然后将C函数放在一个独立的C文件中进行编译,剩下的工作就由链接器来处理。
汇编程序与C函数间参数的传递规则遵守ATPCS(ARM Thumb Procedure Call Standard)规则:用ARM处理器寄存器组中的{R0 - R3}作为参数传递和结果返回寄存器;如果参数数目超过4个,则使用堆栈进行传递。

; asmfile.s文件
	AREA asmfile, CODE, READONLY
	IMPORT cFun			; 声明引用外部函数
	ENTRY
	CODE32
start
	MOV	R0,	#1
	MOV	R1,	#2
	MOV	R2,	#3
	BL	cFun			; 此时结果和在R0中
stop
	MOV	R0,	#0x18		; 程序结束返回编译器调试环境
	LDR	R1,	=0x20026
	SWI	0x123456
	END
/* cFun.c文件,由asmFile.s文件调用 */
int cFun(int a, int b, int c)
{
return a + b + c;
}

C程序调用汇编程序

C程序调用汇编程序子程序,要做的主要工作有两个:
一是在C程序中用关键字extern声明汇编子程序的函数原型(C程序是函数结构的程序设计风格),声明该函数的实现代码在其他文件中;
二是在汇编程序中用伪指令EXPORT导出子程序名,并且用该子程序名作为汇编代码段的标识,最后用mov pc, lr返回。
这样,在C程序中就可以像调用C函数一样调用该汇编子程序了。

具体操作步骤:
汇编程序中,用该子程序名作为汇编代码段的标识,定义程序代码,最后用“MOV PC, LR”指令返回;
汇编程序中用伪指令EXPORT导出子程序名;
C程序中用关键字extern声明该汇编子程序的函数原型;然后就可在C程序中访问该函数;
函数调用时的参数传递规则:寄存器组中的{R0 - R3}作为参数传递而返回值用寄存器R0返回;如果参数数目超过4个,则使用堆栈进行传递。

/* cfile.c */
#include <stdio.h>
extern void  strcpy(const char *src, char *dest);
int main()
{
char *s = "this string is in C file";
char temp[32];
strcpy(s, temp);
printf("Source   string : %s \n", s);
printf("Destination sting: %s", temp);
return 0;
}
; asmfile.s
	AREA strcpy,CODE, READONLY
	EXPORT  strcpy	; 完成源字符串R0到目的字符串R1的拷贝
loop
	LDRB    R5,  [R0], 	#1
	CMP	      R5,  #0		; 是否到字符串结束
	BEQ	      exit
	STRB    R5,   [R1],     #1
	B           loop
exit
	MOV       PC,   LR
	END

C程序中内嵌ARM7汇编代码

C 程序中内嵌的汇编代码可使用大部分的ARM 和Thumb 指令,存在一些限制,主要有下面几个方面:
不能直接向寄存器PC赋值,程序跳转要使用指令B或者BL;
在访问物理寄存器时,不要使用过于复杂的C表达式,避免物理寄存器冲突;
R12和R13常被编译器用来存放中间编译结果,计算表达式值时可能将R0~R3、R12及R14用于子程序调用,因此要避免直接使用这些物理寄存器;

在C程序中使用“__asm”关键字标记内嵌汇编代码,
格式如下:

__asm		; 注意是双下划线
{
	......		; 汇编指令编写的代码
}
#include <stdio.h>
void  strcpy(const char *src, char *dest) 
{
	char ch;			; 检查字符串是否结束的标志
	__asm
	{	; 功能:完成将源字符串src中的数据拷贝到目的字符串dest中
	LOOP:	
		LDRB	ch,	[src],	 #1
		STRB	ch,	[dest], #1
		CMP	ch,	#0
		BNE	LOOP
	}
}

int main()
{
    char *s= "this is a example AsmInC !";
    char temp[64];
    strcpy(s , temp);
    printf("Original string:  %s \n ",  s);
    printf("Copyed string:  %s",  temp);
    return 0;
}

最后

2023-4-11 20:06:34

你对我百般注释,并不能构成万分之一的我,却是一览无余的你。

祝大家逢考必过
点赞收藏关注哦


http://www.kler.cn/a/10096.html

相关文章:

  • Flink API 的层次结构
  • redis实现消息队列的几种方式
  • 双十一云服务器抢购后,用SD-WAN连通多云网络
  • Iceberg 写入和更新模式,COW,MOR(Copy-on-Write,Merge-on-Read)
  • 设计模式-七个基本原则之一-单一职责原则 + SpringBoot案例
  • 第七部分:2. STM32之ADC实验--AD多通道(AD采集三路传感器模块实验:光敏传感器、热敏传感器、反射式传感器附赠温湿度传感器教程)
  • STC89C52定时器的简介
  • Shader 海面/水面
  • 一次弄懂gzip模块启用和配置指令
  • TypeScript类成员的存取器
  • 《八次危机》速读笔记
  • 【ROS2指南-1】配置ROS2环境
  • 机器学习实战:Python基于K近邻KNN进行分类预测(四)
  • 【举一反三】只出现一次的数字
  • Pandas 秘籍:1~5
  • Nodejs中的fs模块
  • 前脚我的 GPT4 被封,后脚收到了文心一言的邀请账号
  • Java阶段一Day20
  • Linux网络虚拟化2
  • SpringBoot使用Freemarker导出word模板(OpenXML)
  • Spring boot+Vue3博客平台:文章搜索与推荐和文章阅读统计模块
  • HTML - 实现IE浏览器访问网址自动跳转至谷歌浏览器打开
  • 电脑重装了系统开不了机怎么办?
  • 嵌入式入门基础知识有哪些?
  • pytorch张量及其使用——初学者入门必看
  • kruskal重构树