> 文章列表 > ARM与C语言的混合编程【嵌入式系统】

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

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, READONLYEXPORT asmVisit	; 声明全局函数,供C程序调用??IMPORT g_var		; 引入在C程序中声明定义的全局变量GLOBAL _multiple	; 声明全局变量,供C程序访问
asmVisitLDR	R0,	=g_varLDR	R1,	[R0]LDR	R2,  	=_multipleLDR	R2, 	[R2]MOV	R3,   	R1,   LSL R2	; 将R1中的值扩大指定的倍数STR	R3,	[R0]MOV	PC,	LRAREA asmData, DATA, READWRITE
_multiple DCD 2END 

ARM7汇编程序调用C程序

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

; asmfile.s文件AREA asmfile, CODE, READONLYIMPORT cFun			; 声明引用外部函数ENTRYCODE32
startMOV	R0,	#1MOV	R1,	#2MOV	R2,	#3BL	cFun			; 此时结果和在R0中
stopMOV	R0,	#0x18		; 程序结束返回编译器调试环境LDR	R1,	=0x20026SWI	0x123456END
/* 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.sAREA strcpy,CODE, READONLYEXPORT  strcpy	; 完成源字符串R0到目的字符串R1的拷贝
loopLDRB    R5,  [R0], 	#1CMP	      R5,  #0		; 是否到字符串结束BEQ	      exitSTRB    R5,   [R1],     #1B           loop
exitMOV       PC,   LREND

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],	 #1STRB	ch,	[dest], #1CMP	ch,	#0BNE	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

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

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