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