ARM与C语言的混合编程【嵌入式系统】
ARM与C语言的相互调用【嵌入式系统】
前言
以下内容源自《【嵌入式系统】》
仅供学习交流使用
推荐
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
你对我百般注释,并不能构成万分之一的我,却是一览无余的你。
祝大家逢考必过
点赞收藏关注哦