3.3.4 寄存器变量
GNU C对C语言的另一个扩充是允许我们把一些变量值放到CPU寄存器中,即所谓寄存器变量。这样CPU就不用经常花费较长时间访问内存去取值。寄存器变量可以分为两种:全局寄存器变量和局部寄存器变量。全局寄存器变量会在程序的整个运行过程中保留寄存器专门用于几个全局变量。相反,局部寄存器变量不会保留指定的寄存器,而仅在内嵌asm汇编语句中作为输入或输出操作数时使用专门的寄存器。gcc编译器的数据流分析功能本身有能力确定指定的寄存器何时含有正在使用的值,何时可派其他用场。当gcc数据流分析功能认为存储在某个局部寄存器变量值无用时就可能将其删除,并且对局部寄存器变量的引用也可能被删除、移动或简化。因此,若不想让gcc作这些优化改动,最好在asm语句中加上 volatile关键字。
如果想在嵌入汇编语句中把汇编指令的输出直接写到指定的寄存器中,那么此时使用局部寄存器变量就很方便。由于Linux内核中通常只使用局部寄存器变量,因此这里我们只对局部寄存器变量的使用方法进行讨论。在GNU C程序中我们可以在函数中用如下形式定义一个局部寄存器变量:
register int res __asm__("ax"); |
这里 ax 是变量res希望使用的寄存器。定义这样一个寄存器变量并不会专门保留这个寄存器不派其他用途。另外,gcc并不保证编译出的代码会把变量一直放在指定的寄存器中。因此在嵌入汇编的指令部分最好不要明确地引用该寄存器并且假设该寄存器肯定引用的是该变量值。然而把该变量用做asm的操作数还是能够保证指定的寄存器被用做该操作数。