14.7寄存器分配
编译器一项很重要的优化功能就是对寄存器的分配。与分配在寄存器中的变量相比,分配到内存的变量访问要慢得多。所以如何将尽可能多的变量分配到寄存器,是编程时应该重点考虑的问题。
注意
当使用-g或-dubug选项编译程序时,为了确保调试信息的完整性,寄存器分配的效率比不使用-g或-dubug选项低很多。
14.7.1变量寄存器分配
一般情况下,编译器会对C函数中的每一个局部变量分配一个寄存器。如果多个局部变量不会交迭使用,那么编译器会对它们分配同一个寄存器。当局部变量多于可用的寄存器时,编译器会把多余的变量存储到堆栈。这些被写入堆栈需要访问存储器的变量被称为溢出(Spilled)变量。
为了提高程序的执行效率:
·使溢出变量的数量最少;
·确保最重要的和经常用到的变量被分配在寄存器中。
可以被分配到寄存器的变量包括:
·程序中的局部变量;
·调用子程序时传递的参数;
·与地址无关变量。
另外,在一些特定条件下,结构体中的域也可以被分配到寄存器中。
表14.1显示了当C编译器采用ARM-Thumb过程调用标准时,内部寄存器的编号、名字和分配方法。
表14.1 C编译器寄存器用法
寄存器编号
可选寄存器名
特殊寄存器名
寄存器用法
r0
a1
函数调用时的参数寄存器,用来存放前4个函数参数和存放返回值。在函数内如果将这些寄存器用作其他用途,将破坏其值。
r1
a2
r2
a3
r3
a4
r4
v1
通用变量寄存器
r5
v2
r6
v3
r7
v4
r8
v5
r9
v6或SB或TR
平台寄存器,不同的平台对该寄存器的定义不同
r10
v7
通用变量寄存器。在使用堆栈边界检测的情况下,r10保存堆栈边界的地址
r11
v8
通用变量寄存器。
r12
IP
临时过渡寄存器,函数调用时会破坏其中的值
r13
SP
堆栈指针
r14
LR
链接寄存器
r15
PC
程序计数器
从表14.1可以看出,编译器可以分配14个变量到寄存器而不会发生溢出。但有些寄存器编译器会有特殊用途(如r12),所以在编写程序时应尽量限制变量的数目,使函数内部最多使用12个寄存器。
注意
在C语言中,可以使用关键词register给指定变量分配专用寄存器。但不同的编译器对该关键词的处理可能不同,使用时要查阅相关手册。