基于C语言的ARM嵌入式程序设计教学探讨

时间:2022-08-27 01:58:43

基于C语言的ARM嵌入式程序设计教学探讨

文章编号:1672-5913(2008)06-0098-02

摘要:本文探讨基于C语言arm嵌入式程序设计课程中学生反映不好掌握的一些知识点。

关键词:ARM嵌入式;C语言;程序设计;技巧

中图分类号:G642

文献标识码:B

引言

嵌入式C语言程序设计是利用基本的C语言知识,面向嵌入式工程实际应用进行程序设计语言。如何能够在嵌入式系统开发中熟练、正确地运用C语言开发出高质量的应用程序,是学习嵌入式程序设计的关键。下面介绍基于C语言的ARM嵌入式程序设计课程中学生反映不好掌握的一些难点。

1变量定义

先看下面一个例子:

char  a; char  a;

short b; char  c;

char  c; short b;

int

d; int

d;

这里定义的4个变量形式都一样,只是次序不同,却导致了在最终映像中不同的数据布局,如图1所示。显然,第2种方式节约了更多的存储空间(Pad为无意义的填充数据)。

由此可见,在变量声明时,最好把所有相同类型的变量放在一起定义,这样可以优化存储器布局。

图1变量在数据区里的布局

对于局部变量类型的定义,一般情况下,人们总是设法使用short或char来定义变量,以节省存储空间;但是,当一个函数的局部变量数目有限时,其结果恰恰相反。因为编译器会把局部变量分配给内部寄存器,每个变量占用一个寄存器,如图2所示。假定a1是任意可能的寄存器存储函数的局部变量,同样完成加1的操作,32位的int型变量最快,只用1条加法指令。而8位和16位变量,完成加法操作后,还需要在32位的寄存器中进行括号扩展,其中有符号的变量,要用逻辑左移(LSL)和算术右移(ASR)2条指令才能完成符号扩展;无符号的变量,要使用1条逻辑“与”(AND)指令对符号位进行清0。所以,使用32位int或unsingedint局部变量最有效率。

图2不同类型局部变量的编译结果

变量定义中,为了精简程序,程序员总是竭力避免使用冗余变量。通常情况下这是正确的,但也有例外。

例如:冗余变量的使用与否比较。

int f(void);

int g(void);

int errs;

void test1(void)

{

errs+=f();

errs+=g();

}

void test2(void)

{

int localerrs=errs;

localerrs+=f();

localerrs+=g();

errs=localerrs;

}

在第一种情况test1()里,每次访问全局变量errs时,都要先从相应的存储器Load到寄存器里,经f()或g()函数调用后再Store回原来的存储区里面。在这个例子里,一共要进行2次这样的Load/Store操作(第一次是Load,第2次是Store)。而在第2种情况test2()里,局部变量localerrs被分配以寄存器,这样一来,整个函数就只需1次Load/Store访问全局变量存储器。减少存储器访问的次数对于系统性能的改善是非常有好处的。

2参数传递

为了使单独编译的C语言程序和汇编程序能够互相调用,定义了统一的函数过程调用标准ATPCS(ARM-Thumb Procedure Call Standard)。ATPCS定义了寄存器组中的{R0~R3}作为参数传递和结果返回寄存器。如果参数数目超过4个,则使用堆栈进行传递。由于内部寄存器的访问速度远远大于存储器,所以要尽量使参数传递在寄存器里面进行,即应尽量把函数的参数控制在4个以下。例如:从C语言中直接调用汇编语言函数:

extern void strcopy(char *d,const char *s);

int main(void){

const char src=“Source”;

char dest[10];

strcopy(dest,src);

}

AREAStrCopy,CODE,READONLY

EXPORT strcopy

strcopy

LDRBR2,[R1],#1

STRBR2,[R0],#1

CMP R2,#0

BNE strcopy

MOVPC,LR

END

例子中的函数strcopy(dest,src)用汇编来实现。根据ATPCS的定义,函数参数从左到右由寄存器进行传递,所以在汇编中可直接由R0和R1进行引用。这样,在C语言和汇编语言之间进行相互调用就容易实现了。

3循环条件

计数循环是程序中十分常用的流程控制结构。在C语言中,常用下面累加计数的循环形式:

for(loop=1;loop

这种累加计数的方法符合一般的自然思维习惯,所以下面这种递减计数方法很少使用:

for(loop= limit;loop!=0;loop--)

这2种循环形式在逻辑上并没有效率差异,但是映射到具体的体系结构中时,就产生了很大的不同,如图3所示。

图3不同的循环条件设置比较

从图中可以发现,累加法比递减法多用了1条指令,当循环次数比较大时,这2段代码就会在性能上产生明显的差异。

其本质原因是:当进行一个非0常数比较时,必须用专门的CMP指令来执行;而当一个变量与0进行比较时,ARM指令则可直接利用条件执行的特性(NE)来进行判别。因此,在ARM的体系结构下编程,最好采用递减至0的方法来设置循环条件。

参考文献

[1] 梁合庆等. 从C到嵌入式C编程语言[M]. 北京航空航天大学出版社,2000.

[2] 田泽. 嵌入式系统开发与应用[M]. 北京航空航天大学出版社,2005.

[3] 杜春雷. ARM体系结构与编程[M]. 北京:清华大学出版社,2003.

[4] 桑楠. 嵌入式系统原理及应用开发技术[M]. 北京航空航天大学出版社,2002.

上一篇:计算机专业工程实习平台建设的探讨 下一篇:计算机基础课程体系建设研究