ARM程序设计优化策略与技术 大小端模式

1、ARM程序设计优化策略与技术

程序优化是指软件编程结束后,利用软件开发工具对程序进行调整和改进,让程序充分利用资源, 提高运行效率,缩减代码尺寸的过程。按照优化的侧重点不同,程序优化可分为运行速度优化和代码尺寸优化。

运行速度优化是指在充分掌握软硬件特性的基础上,通过应用程序结构调整等手段来降低完成指定任务所需执行的指令数。在同一个处理器上,经过速度优化的程序比未经优化的程序在完成指定任务时所需的时间更短,即前者比后者具有更高的运行效率。代码尺寸优化是指,采取措施使应用程序在能够正确完成所需功能的前提下,尽可能减少程序的代码量。

然而在实际的程序设计过程中,程序优化的两个目标(运行速度和代码大小)通常是互相矛盾的。为了提高程序运行效率,往往要以牺牲存储空间、增加代码量为代价,例如程序设计中经常使用的以查表代替计算、循环展开等方法就容易导致程序代码量增加。而为了减少程序代码量、压缩存储器空间,可能又要以降低程序运行效率为代价。因此,在对程序实施优化之前, 应先根据实际需求确定相应的策略。在处理器资源紧张的情况下,应着重考虑运行速度优化;而在存储器资源使用受限的情况下, 则应优先考虑 代码尺寸的优化。

1 程序运行速度优化

程序运行速度优化的方法可分为以下几大类。

1.1 通用的优化方法

(1)减小运算强度

利用左/ 右移位操作代替乘/ 除2 运算:通常需要乘以或除以2 的幂次方都可以通过左移或右移n 位来完成。实际上乘以任何一个整数都可以用移位和加法来代替乘法。ARM 7 中加法和移位可以通过一条指令来完成,且执行时间少于乘法指令。例如: i = i × 5 可以用i = (i

利用乘法代替乘方运算:ARM7 核中内建有32 ×8 乘法器,因此可以通过乘法运算来代替乘方运算以节约乘方函数调用的开销。例如: i = pow(i, 3.0) 可用 i = i×i × i 来代替。

利用与运算代替求余运算:有时可以通过用与(AND )指令代替求余操作(% )来提高效率。例如:i = i % 8 可以用 i = i &0x07 来代替。

(2)优化循环终止条件

在一个循环结构中,循环的终止条件将严重影响着循环的效率,再加上ARM 指令的条件执行特性,所以在书写循环的终止条件时应尽量使用count-down-to-zero结构。这样编译器可以用一条BNE (若非零则跳转)指令代替CMP (比较)和BLE (若小于则跳转)两条指令,既减小代码尺寸,又加快了运行速度。

(3)使用inline 函数

ARM C 支持 inline 关键字,如果一个函数被设计成一个inline 函数,那么在调用它的地方将会用函数体来替代函数调用语句, 这样将会彻底省去函数调用的开销。使用inline 的最大缺点是函数在被频繁调用时,代码量将增大。

1.2 处理器相关的优化方法

(1)保持流水线畅通

从前面的介绍可知,流水线延迟或阻断会对处理器的性能造成影响,因此应该尽量保持流水线畅通。流水线延迟难以避免,但可以利用延迟周期进行其它操作。

LOAD/STORE 指令中的自动索引(auto-indexing)功能就是为利用流水线延迟周期而设计的。当流水线处于延迟周期时,处理器的执行单元被占用, 算术逻辑单元(ALU )和桶形移位器却可能处于空闲状态,此时可以利用它们来完成往基址寄存器上加一个偏移量的操作,供后面的指令使用。例如:指令 LDR R1, [R2], #4 完成 R1= *R2 及 R2 += 4 两个操作,是后索引(post-indexing)的例子;而指令 LDR R1, [R2, #4]! 完成 R1 = *(R2 + 4) 和 R2 +=4 两个操作,是前索引(pre-indexing)的例子。

流水线阻断的情况可通过循环拆解等方法加以改善。一个循环可以考虑拆解以减小跳转指令在循环指令中所占的比重,进而提高代码效率。下面以一个内存复制函数加以说明。

void memcopy(char *to, char *from, unsigned int nbytes)

{

while(nbytes--)

*to++ = *from++;

}

为简单起见,这里假设nbytes 为16 的倍数(省略对余数的处理)。上面的函数每处理一个字节就要进行一次判断和跳转, 对其中的循环体可作如下拆解:

void memcopy(char *to, char *from, unsigned int nbytes)

{

while(nbytes)

{

*to++ = *from++;

*to++ = *from++;

*to++ = *from++;

*to++ = *from++;

nbytes - = 4;

}

}

这样一来,循环体中的指令数增加了,循环次数却减少了。跳转指令带来的负面影响得以削弱。利用ARM 7 处理器32 位字长的特性,上述代码可进一步作如下调整:

void memcopy(char *to, char *from, unsigned int nbytes)

{

int *p_to = (int *)to;

int *p_from = (int *)from;

while(nbytes) {

*p_to++ = *p_from++;

*p_to++ = *p_from++;

*p_to++ = *p_from++;

*p_to++ = *p_from++;

nbytes - = 16;

}

}

经过优化后,一次循环可以处理16 个字节。跳转指令带来的影响进一步得到减弱。不过可以看出, 调整后的代码在代码量方面有所

增加。

(2)使用寄存器变量

CPU 对寄存器的存取要比对内存的存取快得多,因此为变量分配一个寄存器, 将有助于代码的优化和运行效率的提高。整型、指针、浮点等 类型的变量都可以分配寄存器;一个结构的部分或者全部也可以分配寄存器。给循环体中需要频繁访问的变量分配寄存器也能在一定程度上提高程序效率。

1.3 指令集相关的优化方法

有时可以利用ARM7 指令集的特点对程序进行优化。

(1)避免除法

ARM 7 指令集中没有除法指令,其除法是通过调用C 库函数实现的。一个32 位的除法通常需要20~140 个时钟周期。因此, 除法成了一个程序效率的瓶颈,应尽量避免使用。有些除法可用乘法代替,例如: if ( (x / y) > z)可变通为 if ( x > (y × z)) 。在能满足精度,且存储器空间冗余的情况下,也可考虑使用查表法代替除法。当除数为2 的幂次方时, 应用移位操作代替除法。

(2)利用条件执行

ARM 指令集的一个重要特征就是所有的指令均可包含一个可选的条件码。当程序状态寄存器(PSR )中的条件码标志满足指定条件时,带条件码的指令才能执行。利用条件执行通常可以省去单独的判断指令,因而可以减小代码尺寸并提高程序效率。

(3)使用合适的变量类型

ARM 指令集支持有符号/ 无符号的8 位、16 位、32位整型及浮点型变量。恰当的使用变量的类型,不仅可以节省代码,并且可以提高代码运行效率。应该尽可能地避免使用char、short 型的局部变量,因为操作8 位/16 位局部变量往往比操作3 2 位变量需要更多指令,请对比下列3 个函数和它们的汇编代码。

intwordinc(inta) wordinc

{ ADD a1,a1,#1

return a + 1; MOV pc,lr

} shortinc

shortshortinc(shorta) ADD a1,a1,#1

{ MOV a1,a1,LSL #16

return a + 1; MOV a1,a1,ASR #16

} MOV pc,lr

charcharinc(chara) charinc

{ ADD a1,a1,#1

return a + 1; AND a1,a1,#&ff

} MOV pc,lr

可以看出, 操作3 2 位变量所需的指令要少于操作8位及16 位变量。

1.4 存储器相关的优化方法

(1)用查表代替计算

在处理器资源紧张而存储器资源相对富裕的情况下,可以用牺牲存储空间换取运行速度的办法。例如需要频繁计算正弦或余弦函数值时,可预先将函数值计算出来置于内存中供以后查找。

(2)充分利用片内RAM

一些厂商出产的ARM 芯片内集成有一定容量的RAM,如Atmel 公司的AT91R40807 内有128KB 的RAM,夏普公司的LH75400/LH75401 内有32KB 的RAM。处理器对片内RAM 的访问速度要快于对外部RAM 的访问,所以应尽可能将程序调入片内RAM 中运行。若因程序太大无法完全放入片内RAM ,可考虑将使用最频繁的数据或程序段调入片内RAM 以提高程序运行效率。

1.5 编译器相关的优化方法

多数编译器都支持对程序速度和程序大小的优化,有些编译器还允许用户选择可供优化的内容及优化的程度。相比前面的各种优化方法,通过设置编译器选项对程序进行优化不失为一种简单有效的途径。

2 代码尺寸优化

精简指令集计算机的一个重要特点是指令长度固定,这样做可以简化指令译码的过程,但却容易导致代码尺寸增加。为避免这个问

题,可以考虑采取以下措施来缩减程序代码量。

2.1 使用多寄存器操作指令

ARM 指令集中的多寄存器操作指令LDM/STM 可以加载/ 存储多个寄存器,这在保存/ 恢复寄存器组的状态及进行大块数据复制时非常有效。例如要将寄存器R4~R12 及R14 的内容保存到堆栈中,若用STR 指令共需要10 条,而一条STMEA R13!, {R4 ?? R12, R14} 指令就能达到相同的目的,节省的指令存储空间相当可观。不过需要注意的是,虽然一条LDM/STM 指令能代替多条LDR/STR 指令,但这并不意味着程序运行速度得到了提高。实际上处理器在执行LDM/STM 指令的时候还是将它拆分成多条单独的LDR/STR 指令来执行。

2.2 合理安排变量顺序

ARM 7 处理器要求程序中的32 位/16 位变量必须按字/ 半字对齐,这意味着如果变量顺序安排不合理, 有可能会造成存储空间的浪

费。例如:一个结构体中的4个32 位int 型变量i1 ~ i4 和4 个8 位char 型变量c1 ~ c4,若按照i1、c1、i2、c2、i3、c3、i4、c4 的

顺序交错存放时, 由于整型变量的对齐会导致位于2 个整型变量中间的那个8 位char 型变量实际占用 32 位的存储器,这样就造成了存储空间的浪费。为避免这种情况, 应将int 型变量和char 型变量按类似i1、i2、i3、i4、c1、c2、c3、c4 的顺序连续存放。

2.3 使用Thumb 指令

为了从根本上有效降低代码尺寸,ARM 公司开发了16 位的Thumb 指令集。Thumb 是ARM 体系结构的扩充。Thumb 指令集是大多数常用32 位ARM 指令压缩成16 位宽指令的集合。在执行时,16 位指令透明的实时解压成32 位ARM 指令并没有性能损失。而且程序在Thumb状态和ARM 状态之间切换是零开销的。与等价的32 位ARM 代码相比,Thumb 代码节省的存储器空间可高达35% 以上。

结语

综上所述,优化的过程是在透彻了解软/ 硬件结构和特性的前提下,充分利用硬件资源,不断调整程序结构使之趋于合理的过程。其目的是最大程度发挥处理器效能,最大限度利用资源,尽可能提高程序在特定硬件平台上的性能。随着ARM 处理器在通信及消费电子等行业中的应用日趋广泛,优化技术将在基于ARM 处理器的程序设计过程中发挥越来越重要的作用。值得注意的是,程序的优化通常只是软件设计需要达到的诸多目标之一,优化应在不影响程序正确性、健壮性、可移植性及可维护性的前提下进行。片面追求程序的优化往往会影响健壮性、可移植性等重要目标。

参考文献

1 Advanced RISC Machines Ltd (ARM). ARM7TDMI DataSheet

2 Advanced RISC Machines Ltd (ARM). ARM Architecture Reference Manual

3 ARM 高级编程. 哈工大旋极信息技术培训中心培训材料

4 Kernighan Brain W. 程序设计实践. 北京:机械工业出版社,2000

C循环结构

◎ 使用减数到零的循环体,以节省指令和寄存器的使用。

◎ 使用无符号的循环计数值,并用条件 i != 0中止。

◎ 如果循环体至少执行一次,用优先选用do-while。

◎ 适当情况下展开循环体。

◎ 尽量使用数组的大小是4或8的倍数,用此倍数展开循环体

寄存器分配

◎ 尽量限制函数内部循环所用局部变量的数目,最多不超过12个,以便编译器能把变量分配到寄存器。

◎ 可以引导编译器,通过查看是否属于最内层循环的便赖宁嘎来去定某个变量的重要性。

函数调用

ARM中的函数前4个整型参数通过寄存器r0、r1、r2、r3来传递,随后的整型参数通过堆栈来传递。(full desceding stack)。

◎ 尽量限制函数参数,不要超过四个,也可以把相关的参数组织在结构体传递。

◎ 把比较小的被调用函数和调用函数放在同一个源文件中,并且限定一,后调用,编译器能进行优化。

◎ 用_inline内联性能影响较大的重要函数。

指针别名

◎ 用一个局部变量来保存公共子表达式的值,保证该表达式只求一次值。

◎ 避免使用局部变量的地址,否则访问这个变量的效率较低。

结构体的安排

◎ 小的元素放在结构体的开始,大的元素放在结构体的最后

◎ 避免使用过大的结构体,用层次话的小结构体代替。

◎ 人工对API的结构体增加填充位以提高移植性。

◎ 枚举类型要慎用,因为它的大小与编译器相关。

位域

◎ 尽量用define或者enum来代替位域

◎ 用逻辑运算来丢位域操作

边界不对齐数据和字节排列方式

◎ 尽量避免使用边界不对齐数据;

◎ 用char× 可指向任意字节对齐的的数据,与逻辑运算配合,可访问任意边界和排列的数据。

除法

◎ 一堆算法,不好写,总的来说是以乘代除,配合移位运算。

内联函数和内嵌汇编

◎ 没什么好写的,就是内联减少调用开销,内嵌汇编提高运行效率。

大端模式

所谓的大端模式,是指数据的高位,保存在内存的低地址中,而数据的低位,保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放;  例子:  0000430: e684 6c4e 0100 1800 53ef 0100 0100 0000  0000440: b484 6c4e 004e ed00 0000 0000 0100 0000  在大端模式下,前16位应该这样读: e684  记忆方法: 地址的增长顺序与值的增长顺序相反 小端模式

所谓的小端模式,是指数据的高位保存在内存的高地址中,而数据的低位保存在内存的低地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低,和我们的逻辑方法一致。  例子:  0000430: e684 6c4e 0100 1800 53ef 0100 0100 0000  0000440: b484 6c4e 004e ed00 0000 0000 0100 0000  在小端模式下,前16位应该这样读: 84e6  记忆方法: 地址的增长顺序与值的增长顺序相同

1、ARM程序设计优化策略与技术

程序优化是指软件编程结束后,利用软件开发工具对程序进行调整和改进,让程序充分利用资源, 提高运行效率,缩减代码尺寸的过程。按照优化的侧重点不同,程序优化可分为运行速度优化和代码尺寸优化。

运行速度优化是指在充分掌握软硬件特性的基础上,通过应用程序结构调整等手段来降低完成指定任务所需执行的指令数。在同一个处理器上,经过速度优化的程序比未经优化的程序在完成指定任务时所需的时间更短,即前者比后者具有更高的运行效率。代码尺寸优化是指,采取措施使应用程序在能够正确完成所需功能的前提下,尽可能减少程序的代码量。

然而在实际的程序设计过程中,程序优化的两个目标(运行速度和代码大小)通常是互相矛盾的。为了提高程序运行效率,往往要以牺牲存储空间、增加代码量为代价,例如程序设计中经常使用的以查表代替计算、循环展开等方法就容易导致程序代码量增加。而为了减少程序代码量、压缩存储器空间,可能又要以降低程序运行效率为代价。因此,在对程序实施优化之前, 应先根据实际需求确定相应的策略。在处理器资源紧张的情况下,应着重考虑运行速度优化;而在存储器资源使用受限的情况下, 则应优先考虑 代码尺寸的优化。

1 程序运行速度优化

程序运行速度优化的方法可分为以下几大类。

1.1 通用的优化方法

(1)减小运算强度

利用左/ 右移位操作代替乘/ 除2 运算:通常需要乘以或除以2 的幂次方都可以通过左移或右移n 位来完成。实际上乘以任何一个整数都可以用移位和加法来代替乘法。ARM 7 中加法和移位可以通过一条指令来完成,且执行时间少于乘法指令。例如: i = i × 5 可以用i = (i

利用乘法代替乘方运算:ARM7 核中内建有32 ×8 乘法器,因此可以通过乘法运算来代替乘方运算以节约乘方函数调用的开销。例如: i = pow(i, 3.0) 可用 i = i×i × i 来代替。

利用与运算代替求余运算:有时可以通过用与(AND )指令代替求余操作(% )来提高效率。例如:i = i % 8 可以用 i = i &0x07 来代替。

(2)优化循环终止条件

在一个循环结构中,循环的终止条件将严重影响着循环的效率,再加上ARM 指令的条件执行特性,所以在书写循环的终止条件时应尽量使用count-down-to-zero结构。这样编译器可以用一条BNE (若非零则跳转)指令代替CMP (比较)和BLE (若小于则跳转)两条指令,既减小代码尺寸,又加快了运行速度。

(3)使用inline 函数

ARM C 支持 inline 关键字,如果一个函数被设计成一个inline 函数,那么在调用它的地方将会用函数体来替代函数调用语句, 这样将会彻底省去函数调用的开销。使用inline 的最大缺点是函数在被频繁调用时,代码量将增大。

1.2 处理器相关的优化方法

(1)保持流水线畅通

从前面的介绍可知,流水线延迟或阻断会对处理器的性能造成影响,因此应该尽量保持流水线畅通。流水线延迟难以避免,但可以利用延迟周期进行其它操作。

LOAD/STORE 指令中的自动索引(auto-indexing)功能就是为利用流水线延迟周期而设计的。当流水线处于延迟周期时,处理器的执行单元被占用, 算术逻辑单元(ALU )和桶形移位器却可能处于空闲状态,此时可以利用它们来完成往基址寄存器上加一个偏移量的操作,供后面的指令使用。例如:指令 LDR R1, [R2], #4 完成 R1= *R2 及 R2 += 4 两个操作,是后索引(post-indexing)的例子;而指令 LDR R1, [R2, #4]! 完成 R1 = *(R2 + 4) 和 R2 +=4 两个操作,是前索引(pre-indexing)的例子。

流水线阻断的情况可通过循环拆解等方法加以改善。一个循环可以考虑拆解以减小跳转指令在循环指令中所占的比重,进而提高代码效率。下面以一个内存复制函数加以说明。

void memcopy(char *to, char *from, unsigned int nbytes)

{

while(nbytes--)

*to++ = *from++;

}

为简单起见,这里假设nbytes 为16 的倍数(省略对余数的处理)。上面的函数每处理一个字节就要进行一次判断和跳转, 对其中的循环体可作如下拆解:

void memcopy(char *to, char *from, unsigned int nbytes)

{

while(nbytes)

{

*to++ = *from++;

*to++ = *from++;

*to++ = *from++;

*to++ = *from++;

nbytes - = 4;

}

}

这样一来,循环体中的指令数增加了,循环次数却减少了。跳转指令带来的负面影响得以削弱。利用ARM 7 处理器32 位字长的特性,上述代码可进一步作如下调整:

void memcopy(char *to, char *from, unsigned int nbytes)

{

int *p_to = (int *)to;

int *p_from = (int *)from;

while(nbytes) {

*p_to++ = *p_from++;

*p_to++ = *p_from++;

*p_to++ = *p_from++;

*p_to++ = *p_from++;

nbytes - = 16;

}

}

经过优化后,一次循环可以处理16 个字节。跳转指令带来的影响进一步得到减弱。不过可以看出, 调整后的代码在代码量方面有所

增加。

(2)使用寄存器变量

CPU 对寄存器的存取要比对内存的存取快得多,因此为变量分配一个寄存器, 将有助于代码的优化和运行效率的提高。整型、指针、浮点等 类型的变量都可以分配寄存器;一个结构的部分或者全部也可以分配寄存器。给循环体中需要频繁访问的变量分配寄存器也能在一定程度上提高程序效率。

1.3 指令集相关的优化方法

有时可以利用ARM7 指令集的特点对程序进行优化。

(1)避免除法

ARM 7 指令集中没有除法指令,其除法是通过调用C 库函数实现的。一个32 位的除法通常需要20~140 个时钟周期。因此, 除法成了一个程序效率的瓶颈,应尽量避免使用。有些除法可用乘法代替,例如: if ( (x / y) > z)可变通为 if ( x > (y × z)) 。在能满足精度,且存储器空间冗余的情况下,也可考虑使用查表法代替除法。当除数为2 的幂次方时, 应用移位操作代替除法。

(2)利用条件执行

ARM 指令集的一个重要特征就是所有的指令均可包含一个可选的条件码。当程序状态寄存器(PSR )中的条件码标志满足指定条件时,带条件码的指令才能执行。利用条件执行通常可以省去单独的判断指令,因而可以减小代码尺寸并提高程序效率。

(3)使用合适的变量类型

ARM 指令集支持有符号/ 无符号的8 位、16 位、32位整型及浮点型变量。恰当的使用变量的类型,不仅可以节省代码,并且可以提高代码运行效率。应该尽可能地避免使用char、short 型的局部变量,因为操作8 位/16 位局部变量往往比操作3 2 位变量需要更多指令,请对比下列3 个函数和它们的汇编代码。

intwordinc(inta) wordinc

{ ADD a1,a1,#1

return a + 1; MOV pc,lr

} shortinc

shortshortinc(shorta) ADD a1,a1,#1

{ MOV a1,a1,LSL #16

return a + 1; MOV a1,a1,ASR #16

} MOV pc,lr

charcharinc(chara) charinc

{ ADD a1,a1,#1

return a + 1; AND a1,a1,#&ff

} MOV pc,lr

可以看出, 操作3 2 位变量所需的指令要少于操作8位及16 位变量。

1.4 存储器相关的优化方法

(1)用查表代替计算

在处理器资源紧张而存储器资源相对富裕的情况下,可以用牺牲存储空间换取运行速度的办法。例如需要频繁计算正弦或余弦函数值时,可预先将函数值计算出来置于内存中供以后查找。

(2)充分利用片内RAM

一些厂商出产的ARM 芯片内集成有一定容量的RAM,如Atmel 公司的AT91R40807 内有128KB 的RAM,夏普公司的LH75400/LH75401 内有32KB 的RAM。处理器对片内RAM 的访问速度要快于对外部RAM 的访问,所以应尽可能将程序调入片内RAM 中运行。若因程序太大无法完全放入片内RAM ,可考虑将使用最频繁的数据或程序段调入片内RAM 以提高程序运行效率。

1.5 编译器相关的优化方法

多数编译器都支持对程序速度和程序大小的优化,有些编译器还允许用户选择可供优化的内容及优化的程度。相比前面的各种优化方法,通过设置编译器选项对程序进行优化不失为一种简单有效的途径。

2 代码尺寸优化

精简指令集计算机的一个重要特点是指令长度固定,这样做可以简化指令译码的过程,但却容易导致代码尺寸增加。为避免这个问

题,可以考虑采取以下措施来缩减程序代码量。

2.1 使用多寄存器操作指令

ARM 指令集中的多寄存器操作指令LDM/STM 可以加载/ 存储多个寄存器,这在保存/ 恢复寄存器组的状态及进行大块数据复制时非常有效。例如要将寄存器R4~R12 及R14 的内容保存到堆栈中,若用STR 指令共需要10 条,而一条STMEA R13!, {R4 ?? R12, R14} 指令就能达到相同的目的,节省的指令存储空间相当可观。不过需要注意的是,虽然一条LDM/STM 指令能代替多条LDR/STR 指令,但这并不意味着程序运行速度得到了提高。实际上处理器在执行LDM/STM 指令的时候还是将它拆分成多条单独的LDR/STR 指令来执行。

2.2 合理安排变量顺序

ARM 7 处理器要求程序中的32 位/16 位变量必须按字/ 半字对齐,这意味着如果变量顺序安排不合理, 有可能会造成存储空间的浪

费。例如:一个结构体中的4个32 位int 型变量i1 ~ i4 和4 个8 位char 型变量c1 ~ c4,若按照i1、c1、i2、c2、i3、c3、i4、c4 的

顺序交错存放时, 由于整型变量的对齐会导致位于2 个整型变量中间的那个8 位char 型变量实际占用 32 位的存储器,这样就造成了存储空间的浪费。为避免这种情况, 应将int 型变量和char 型变量按类似i1、i2、i3、i4、c1、c2、c3、c4 的顺序连续存放。

2.3 使用Thumb 指令

为了从根本上有效降低代码尺寸,ARM 公司开发了16 位的Thumb 指令集。Thumb 是ARM 体系结构的扩充。Thumb 指令集是大多数常用32 位ARM 指令压缩成16 位宽指令的集合。在执行时,16 位指令透明的实时解压成32 位ARM 指令并没有性能损失。而且程序在Thumb状态和ARM 状态之间切换是零开销的。与等价的32 位ARM 代码相比,Thumb 代码节省的存储器空间可高达35% 以上。

结语

综上所述,优化的过程是在透彻了解软/ 硬件结构和特性的前提下,充分利用硬件资源,不断调整程序结构使之趋于合理的过程。其目的是最大程度发挥处理器效能,最大限度利用资源,尽可能提高程序在特定硬件平台上的性能。随着ARM 处理器在通信及消费电子等行业中的应用日趋广泛,优化技术将在基于ARM 处理器的程序设计过程中发挥越来越重要的作用。值得注意的是,程序的优化通常只是软件设计需要达到的诸多目标之一,优化应在不影响程序正确性、健壮性、可移植性及可维护性的前提下进行。片面追求程序的优化往往会影响健壮性、可移植性等重要目标。

参考文献

1 Advanced RISC Machines Ltd (ARM). ARM7TDMI DataSheet

2 Advanced RISC Machines Ltd (ARM). ARM Architecture Reference Manual

3 ARM 高级编程. 哈工大旋极信息技术培训中心培训材料

4 Kernighan Brain W. 程序设计实践. 北京:机械工业出版社,2000

C循环结构

◎ 使用减数到零的循环体,以节省指令和寄存器的使用。

◎ 使用无符号的循环计数值,并用条件 i != 0中止。

◎ 如果循环体至少执行一次,用优先选用do-while。

◎ 适当情况下展开循环体。

◎ 尽量使用数组的大小是4或8的倍数,用此倍数展开循环体

寄存器分配

◎ 尽量限制函数内部循环所用局部变量的数目,最多不超过12个,以便编译器能把变量分配到寄存器。

◎ 可以引导编译器,通过查看是否属于最内层循环的便赖宁嘎来去定某个变量的重要性。

函数调用

ARM中的函数前4个整型参数通过寄存器r0、r1、r2、r3来传递,随后的整型参数通过堆栈来传递。(full desceding stack)。

◎ 尽量限制函数参数,不要超过四个,也可以把相关的参数组织在结构体传递。

◎ 把比较小的被调用函数和调用函数放在同一个源文件中,并且限定一,后调用,编译器能进行优化。

◎ 用_inline内联性能影响较大的重要函数。

指针别名

◎ 用一个局部变量来保存公共子表达式的值,保证该表达式只求一次值。

◎ 避免使用局部变量的地址,否则访问这个变量的效率较低。

结构体的安排

◎ 小的元素放在结构体的开始,大的元素放在结构体的最后

◎ 避免使用过大的结构体,用层次话的小结构体代替。

◎ 人工对API的结构体增加填充位以提高移植性。

◎ 枚举类型要慎用,因为它的大小与编译器相关。

位域

◎ 尽量用define或者enum来代替位域

◎ 用逻辑运算来丢位域操作

边界不对齐数据和字节排列方式

◎ 尽量避免使用边界不对齐数据;

◎ 用char× 可指向任意字节对齐的的数据,与逻辑运算配合,可访问任意边界和排列的数据。

除法

◎ 一堆算法,不好写,总的来说是以乘代除,配合移位运算。

内联函数和内嵌汇编

◎ 没什么好写的,就是内联减少调用开销,内嵌汇编提高运行效率。

大端模式

所谓的大端模式,是指数据的高位,保存在内存的低地址中,而数据的低位,保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放;  例子:  0000430: e684 6c4e 0100 1800 53ef 0100 0100 0000  0000440: b484 6c4e 004e ed00 0000 0000 0100 0000  在大端模式下,前16位应该这样读: e684  记忆方法: 地址的增长顺序与值的增长顺序相反 小端模式

所谓的小端模式,是指数据的高位保存在内存的高地址中,而数据的低位保存在内存的低地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低,和我们的逻辑方法一致。  例子:  0000430: e684 6c4e 0100 1800 53ef 0100 0100 0000  0000440: b484 6c4e 004e ed00 0000 0000 0100 0000  在小端模式下,前16位应该这样读: 84e6  记忆方法: 地址的增长顺序与值的增长顺序相同


相关文章

  • 32位嵌入式微处理器--ARM.MIPS.PowerPC.DSP
  • 由于嵌入式系统的专用型与定制性,与全球PC市场不同,没有一种微处理器或者微处理器公司可以主导嵌入式系统.本文分析了当前市场上主流的一些32位嵌入式微处理器的特点和应用场合,并对其未来发展做一些展望.这里只是按照体系结构分类,不涉及具体的处理 ...查看


  • 智能家居系统方案设计
  • 智能家居系统 方案设计文档 目 录 0. 文档介绍 ...................................................... 3 0.1 文档目的 ............................ ...查看


  • ARM控制伺服点焊枪的设计
  • ARM控制伺服点焊枪的设计 王军,罗震 天津大学材料学院点焊实验室,天津(300072) 摘 要:设计了一种新型的伺服驱动的悬挂式点焊钳,该焊钳能够在焊接的过程中对电极压力进行实时的调节,实现复杂的焊接循环.伺服焊钳以滚珠丝杠为主要传动机构 ...查看


  • 智能家居远程监控系统毕业论文
  • 智能家居远程监控系统毕业论文 基于ARM9的智能家居远程监控系统的设计与实现 摘要 目 录 1 绪论 ..................................................................... ...查看


  • 惠水县职称论文发表网-电气工程
  • 云发表,专业论文发表网站!http://www.yunfabiao.com/ 面向作者直接收稿,省去中间环节,价格更低,发表更快,收录更快! 惠水县职称论文发表网-电气工程| 管理 |设计审图 |质量控制论文选题题目 惠水县职称论文发表网- ...查看


  • 国家级省级"项目阶段报告"书写格式
  • "基于无线传感网络的核电站人员定位系统设计"阶段性研 究报告 金师兴 李永强 刘思綦 一.项目名称 基于无线传感网络的核电站人员定位系统设计 二.项目综述 无线传感网络(Wireless Sensor Network)技 ...查看


  • 智能手机的系统架构及其低功耗设计
  • 智能手机的系统架构及其低功耗设计 智能手机的系统架构及其低功耗设计 随着通信产业的不断发展,移动终端已经由原来单一的通话功能向话音.数据.图像.音乐和多媒体方向综合演变.而对于移动终端,基本上可以分成两种:一种是传统手机(featureph ...查看


  • 软件行业现状以及未来发展前景趋势分析
  • 目 录 CONTENTS 第一篇:英特尔评估车载软件释疑车联网智能汽车前景分析 --------------------------------------- 1 第二篇:软件行业现状分析2015年软件收入排行榜华为入围 --------- ...查看


  • 海洋科学毕业论文题目
  • 毕业论文(设计) 题 目 学 院 学 院 专 业 学生姓名 学 号 年级 级 指导教师 教务处制表 二〇一三 年 三月 二十 日 海洋科学毕业论文题目 本团队专业从事论文写作与论文发表服务,擅长案例分析.仿真编程.数据统计.图表绘制以及相关 ...查看


热门内容