您的位置 首页 FPGA

ARM中C和汇编混合编程及示例ARM中C和汇编混合编程及示

在嵌入式系统开发中,目前使用的主要编程语言是C和汇编,C++已经有相应的编译器,但是现在使用还是比较少的。在稍大规模的嵌入式软件中,例…

嵌入式体系开发中,现在运用的首要编程言语是C汇编,C++已经有相应的编译器,可是现在运用仍是比较少的。在稍大规划的嵌入式软件中,例如含有OS,大部分的代码都是用C编写的,首要是因为C言语的结构比较好,便于人的了解,而且有许多的支撑库。

尽管如此,许多当地仍是要用到汇编言语,例如开机时硬件体系的初始化,包括CPU状况的设定,中止的使能,主频的设定,以及RAM的操控参数及初始化,一些中止处理方面也或许触及汇编。别的一个运用汇编的当地便是一些对功能十分灵敏的代码块,这是不能依托C编译器的生成代码,而要手艺编写汇编,到达优化的意图。而且,汇编言语是和CPU的指令集严密相连的,作为触及底层的嵌入式体系开发,娴熟对应汇编言语的运用也是有必要的。

单纯的C或许汇编编程请参阅相关的书本或许手册,这儿首要评论C和汇编的混合编程,包括彼此之间的函数调用。下面分四种状况来进行评论,暂不触及C++。

1. 在C言语中内嵌汇编

在C中内嵌的汇编指令包括大部分的ARM和Thumb指令,不过其运用与汇编文件中的指令有些不同,存在一些约束,首要有下面几个方面:

a. 不能直接向PC寄存器赋值,程序跳转要运用B或许BL指令

b. 在运用物理寄存器时,不要运用过于杂乱的C表达式,防止物理寄存器抵触

c. R12和R13或许被编译器用来寄存中心编译成果,核算表达式值时或许将R0到R3、R12及R14用于子程序调用,因而要防止直接运用这些物理寄存器

d. 一般不要直接指定物理寄存器,而让编译器进行分配

内嵌汇编运用的符号是 __asm或许asm关键字,用法如下:

__asm

{

instruction [; instruction]

[instruction]

}

asm(“instruction [; instruction]”);

下面经过一个比如来阐明如安在C中内嵌汇编言语,

#include

void my_strcpy(const char *src, char *dest)

{

char ch;

__asm

{

loop:

ldrb ch, [src], #1

strb ch, [dest], #1

cmp ch, #0

bne loop

}

}

int main()

{

char *a = “forget it and move on!”;

char b[64];

my_strcpy(a, b);

printf(“original: %s”, a);

printf(“copyed: %s”, b);

return 0;

}

  在这儿C和汇编之间的值传递是用C的指针来完成的,因为指针对应的是地址,所以汇编中也可以拜访。

2. 在汇编中运用C界说的全局变量

内嵌汇编不必独自修改汇编言语文件,比较简练,可是有许多约束,当汇编的代码较多时一般放在独自的汇编文件中。这时就需求在汇编和C之间进行一些数据的传递,最简洁的办法便是运用全局变量。

#include

int gVar_1 = 12;

extern asmDouble(void);

int main()

{

printf(“original value of gVar_1 is: %d”, gVar_1);

asmDouble();

printf(” modified value of gVar_1 is: %d”, gVar_1);

return 0;

}

对应的汇编言语文件

;called by main(in C),to double an integer, a global var defined in C is used.

AREA asmfile, CODE, READONLY

EXPORT asmDouble

IMPORT gVar_1

asmDouble

ldr r0, =gVar_1

ldr r1, [r0]

mov r2, #2

mul r3, r1, r2

str r3, [r0]

mov pc, lr

END

3. 在C中调用汇编的函数

在C中调用汇编文件中的函数,要做的首要作业有两个,一是在C中声明函数原型,并加extern关键字;二是在汇编顶用EXPORT导出函数名,并用该函数名作为汇编代码段的标识,最后用mov pc, lr回来。然后,就可以在C中运用该函数了。从C的视点,并不知道该函数的完成是用C仍是汇编。更深的原因是因为C的函数名起到标明函数代码开始地址的左右,这个和汇编的label是共同的。

#include

extern void asm_strcpy(const char *src, char *dest);

int main()

{

const char *s = “seasons in the sun”;

char d[32];

asm_strcpy(s, d);

printf(“source: %s”, s);

printf(” destination: %s”,d);

return 0;

}

;asm function implementation

AREA asmfile, CODE, READONLY

EXPORT asm_strcpy

asm_strcpy

loop

ldrb r4, [r0], #1 ;address increment after read

cmp r4, #0

beq over

strb r4, [r1], #1

b loop

over

mov pc, lr

END

  在这儿,C和汇编之间的参数传递是经过ATPCS(ARM Thumb Procedure Call Standard)的规则来进行的。简略的说便是假如函数有不多于四个参数,对应的用R0-R3来进行传递,多于4个时凭借栈,函数的回来值经过R0来回来。

4. 在汇编中调用C的函数

在汇编中调用C的函数,需求在汇编中IMPORT 对应的C函数名,然后将C的代码放在一个独立的C文件中进行编译,剩余的作业由连接器来处理。

;the details of parameters transfer comes from ATPCS

;if there are more than 4 args, stack will be used

EXPORT asmfile

AREA asmfile, CODE, READONLY

IMPORT cFun

ENTRY

mov r0, #11

mov r1, #22

mov r2, #33

BL cFun

END

int cFun(int a, int b, int c)

{

return a + b + c;

}

  在汇编中调用C的函数,参数的传递也是经过ATPCS来完成的。需求指出的是当函数的参数个数大于4时,要凭借stack,详细见ATPCS标准。

小结

  以上经过几个简略的比如演示了嵌入式开发中常用的C和汇编混合编程的一些办法和根本的思路,其实最中心的问题便是如安在C和汇编之间传值,剩余的问题便是各自用自己的方法来进行处理。以上仅仅抛砖引玉,更详细和杂乱的运用办法要结合实际运用并参阅相关的材料。

阐明

  以上代码在ADS 1.2的工程中编译,并在对应的AXD中软件仿真经过。

在C和汇编混合编程的时分,存在C言语和汇编言语的变量以及函数的接口问题。
在C程序中界说的变量,编译为.asm文件后,都被放进了.bss区,而且变量名的前面都带了一个下划线。在C程序中界说的函数,编译后在函数名前也带了一个下划线。例如:

extern int num就会变成 .bss _num, 1
extern float nums[5]就会变成.bss _nums, 5
extern void func ( )就会变成 _func,

汇编和C的彼此调用可以分以下几种状况:

(1) 汇编程序中拜访c程序中的变量和函数。
在汇编程序中,用_XX就可以拜访C中的变量XX了。拜访数组时,可以用_XX+偏移量来拜访,如_XX+3拜访了数组中的XX[3]。

在汇编程序调用C函数时,假如没有参数传递,直接用_funcname 就可以了。假如有参数传递,则函数中最左面的一个参数由寄存器A给出,其他的参数按次序由仓库给出。回来值是回来到A寄存器或许由A寄存器给出的地址。一起留意,为了可以让汇编言语能拜访到C言语中界说的变量和函数,他们有必要声明为外部变量,即加extern 前缀。

(2) c程序中拜访汇编程序中的变量

假如需求在c程序中拜访汇编程序中的变量,则汇编程序中的变量名有必要以下划线为首字符,并用global使之成为全局变量。

假如需求在c程序中调用汇编程序中的进程,则进程名有必要以下划线为首字符,而且,要根据c程序编译时运用的形式是stack-based model仍是register argument model来正确地编写该进程,使之能正确地获得调用参数。

(3) 在线汇编

在 C程序中直接刺进 asm(“***”),内嵌汇编句子,需求留意的是这种用法要慎用,在线汇编供给了能直接读写硬件的才能,如读写中止操控答应寄存器等,但编译器并不查看和剖析在线汇编言语,刺进在线汇编言语改动汇编环境或或许改动C变量的值或许导致严峻的过错。

二 汇编和C接口中寻址方法的改动:

需求留意的是,在C言语中,关于局部变量的树立和拜访,是经过仓库完成的,它的寻址是经过仓库寄存器SP完成的。而在汇编言语中,为了使程序代码变得更为精简,TI在直接寻址方法中,地址的低7位直接包括在指令中,这低7位所能寻址的详细位置可由DP寄存器或SP寄存器决议。详细完成可经过设置ST1寄存器的CPL位完成,CPL=0,DP寻址,CPL=1,SP寻址。在DP寻址的时分,由DP供给高9位地址,与低7位组成16位地址;在SP寻址的时分,16位地址是由SP(16位)与低7位直接相加得来。

因为在C言语的环境下,局部变量的寻址有必要经过SP寄存器完成,在混合编程的时分,为了使汇编言语不影响仓库寄存器SP,一般的方法是在汇编环境中运用DP方法寻址,这样可以使二者互不搅扰。编程中只需留意对CPL位正确设置即可。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/fangan/fpga/276690.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部