C编译器剖析_6.2 汇编代码生成_寄存器的管理

本文详细介绍了C编译器如何有效地利用寄存器资源,减少内存访问,提高代码运行速度。UCC编译器在汇编代码生成阶段,尽可能将公共子表达式存入寄存器,并通过寄存器分配算法处理寄存器不足的情况。文章以实例展示了函数f和g的寄存器分配过程,并探讨了有名变量的处理,以及在遇到控制流跳转和函数调用时的寄存器回写策略。

    在计算机中,CPU的速度比内存的速度快得多,编译器应尽量有效地利用寄存器资源,减少对内存的不必要访问,从而提高由编译器生成的汇编代码的运行速度。在中间代码生成阶段,UCC编译器用临时变量t来存放形如“t: a+b;”的公共子表达式的值;到了汇编代码生成时,UCC编译器会尽可能地把这些公共子表达式的值存放在寄存器,当需要再次重用时,就可以直接由相应的寄存器中得到。不过,CPU中寄存器的资源是很有限的,在32位的x86 芯片上,汇编程序员可用的寄存器有{eax,ebx, ecx,edx, esi,edi,esp,ebp},不过寄存器esp一般用于指向栈顶,而ebp一般用于指向活动记录的底部。真正可供选择的寄存器就只有{eax,ebx,ecx,edx,esi,edi}这6个,当公共子表达式的个数比可用寄存器更多时,我们就要把某些寄存器的值回写(WriteBack)到“临时变量对应的内存单元”中,以便腾出可用寄存器来存放其他值。当然如果待回写的寄存器中的值已经不再需要,或者从内存载入CPU后并没有发生变化,我们就不必浪费时间去做回写操作了。这有点类似操作系统请求分页中的页面置换算法。为了简化寄存器的分配算法,UCC编译器只为临时变量分配寄存器,这意味着我们希望尽可能地重用形如“t: a+b;”这样的公共子表达式。我们还是用一个简单的例子来说明一下UCC编译器的寄存器分配,如图6.2.1所示,第2至8行为函数f的代码,第9至13行为函数g的代码,在函数f第5行完成对s3的赋值后,我们有意在第6和第7行再次使用公共子表达式(a+b)和(c+d)。第32至46行是函数f对应的汇编代码,而第48至58行是函数g对应的汇编代码。


图6.2.1  寄存器分配的例子

    由图6.2.1第15至23行的中间代码,我们可以发现函数f中有3个临时变量,每个都用于存放整数,共占用12字节的栈空间,第34行的“subl  $12, %esp”用于在栈中开辟12字节内存来存放这3个临时变量。虽然我们通过第36行的“movl  a,%eax”指令,把全局变量a从内存载入寄存器eax中,但在执行第37行的“addl  b,%eax”指令后,寄存器eax中保存的就是临时变量“t0: a+b”的值,之后寄存器eax就一直分配给t0 ,直到t0不再被使用,或者寄存器不够用时。可以发现,在第42行和第4

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值