【发布时间】:2014-07-10 16:42:54
【问题描述】:
我正在写一个简单的玩具编译器,我来到生成机的部分 代码(本例中为 x86-32 程序集)。这就是我现在所拥有的:
给定赋值语句: d := (a-b)+(c-a)-(d+b)*(c+1)
我先生成如下中间代码(三元组形式的3个地址代码):
(0) sub, a, b
(1) sub, c, a
(2) add, (0), (1)
(3) add, d, b
(4) add, c, 1
(5) mul, (3), (4)
(6) sub, (2), (5)
(7) asn, d, (6)
我正在使用中间代码,希望稍后执行一些优化 在上面。目前,我不操纵 3AC 并直接从中生成程序集。
我的寄存器使用方案如下:我执行所有算术运算 使用 EAX 并将中间结果保存在其他寄存器 EBX、ECX 和 EDX 中。为了 例如,从之前的 3AC 我生成以下程序集:
mov eax, a
sub eax, b ; eax = (0)
mov ebx, eax ; ebx = (0) & eax = free
mov eax, c
sub eax, a ; eax = (1)
add ebx, eax ; ebx = (2) & eax = free
mov eax, d
add eax, b ; eax = (3)
mov ecx, eax ; ecx = (3) & eax = free
mov eax, c
add eax, 1 ; eax = (4)
imul ecx ; eax = (5) & ecx = free
sub ebx, eax ; ebx = (6) & eax = free
mov eax, ebx ; eax = (6) & ebx = free
mov d, eax
我的问题是:当我需要溢出 EAX 的结果但所有 寄存器忙(EBX、ECX 和 EDX 正在临时保存)。我应该保存 堆栈中 EAX 的值并稍后恢复?如果是这样,我应该预订吗 每个函数的堆栈框架中有一些额外的空间用于额外的临时?
我再说一遍,这只是我现在的想法。如果还有其他简单的 我想知道的分配寄存器方案(我知道存在 涉及图形着色等的更复杂的解决方案;但我只是在寻找一些东西 简单实用)。
【问题讨论】:
-
由于这是一个玩具编译器,你不必太担心。您可以使用简单的
push和pop,它们仅在必要时不应破坏堆栈。另外,也许这会有所帮助:en.wikipedia.org/wiki/Sethi%E2%80%93Ullman_algorithm. -
哦,还要记住,如果你不需要完整的 32 位,你可以将它们拆分,并使用
ah/al、bh/bl等。 -
反之亦然。您在堆栈帧中为每个变量分配一个插槽,然后您开始尝试不使用它们。显而易见的好处是,您总是有办法溢出寄存器。
标签: assembly compiler-construction x86 allocation cpu-registers