我正在为C的一个子集编写一个编译器。我正在尝试实现数组但是当我不知道数组的大小时我怎么知道何时在我的数组的堆栈上分配空间在编译时。
我可以使用.space
指令声明我在编译时知道大小的数组。否则,我可以通过递减%esp
并将其用作地址来为我的堆栈分配空间。
但是,假设以下代码:
int f(int param)
{
int x;
x = 2;
if(param < x)
{
// Array declareren van compile time onbekende grootte
int new_array[g(param)];
}
}
无法在编译时声明数组。
我使用的中间表示是三个地址代码。所以我最初的想法是创建一个三个地址代码语句,如ARRAYALLOC _var1
wher _var1
将是决定数组大小的表达式的结果。这将允许我在发出x86代码时插入释放堆栈空间的语句。
然而,我觉得这可能不是接近事物的惯用方式。谷歌让我在这个问题上陷入困境。
有人可以详细说明吗?
注意:此编译器是玩具编译器。我已经学会了大部分事情要自己做。即,它是迄今为止专业的方法,并且在堆栈上分配数组不是问题。
答案 0 :(得分:1)
一种可能的方法,当您知道数组的大小时,从esp
中减去该数量。然后只需按偏移量填充数组项。你可以这样做:
; Enter the frame
push ebp
mov ebp, esp
sub esp, <The size of the array>
... Code code code ...
mov [ebp - 4], 1 ; Put '1' in the first slot (Assuming size int32)
mov [ebp - 8], 2 ; Put '2' in the second slot
mov eax, [ebp - 12] ; Grab element 3
; Exit the frame
add esp, <Size of the array>
pop esp
答案 1 :(得分:1)
一旦你知道它是什么,你需要通过从%esp减去数组的大小来动态地分配堆栈空间。你最终会得到类似的东西:
; start of function f
f:
push ebp
mov ebp, esp
sub esp, <size of other local vars>
:
cmp dword ptr [ebp+8], 2 ; compare param with 2
bge label_after_if
push dword ptr [ebp+8]
call g
add esp,4
shl eax, 2 ; compute size of new_array
sub esp, eax ; allocate space -- new_array is at esp
:
label_after_if:
mov esp, ebp
pop ebp
ret