在程序集中按值传递字符串,而不知道它的大小



所以我正在实现C编译器的子集,有一个特性让我头疼。所以我想要一些如何解决它的想法。

在我的节目中。语言是由值传递的所有参数,包括字符串,其声明如下:

string str;

我的问题是,正如你所看到的,我不知道字符串在声明过程中的大小(与C不同),所以当我生成程序集时,我不清楚在堆栈上为它创建多大的空间。如果我有这样的代码:

string str;
int number;
str = something;

我不知道如何为字符串str分配正确的空间,因为以后可以实际分配。最后一个条件是,我不能使用堆。

谢谢,很抱歉我英语不好。

编辑:

谢谢你的回答。在我看来,从回应来看,如果字符串在堆栈上变得更大,最大的问题将是重新分配字符串,以防这个字符串后面已经有东西了,我认为最简单的解决方案是在堆栈上创建新的空间,旧的空间一直保留,直到本地作用域被处理。。。这将是浪费,是的

我假设您有某种dup_string例程,它在新的内存块中复制字符串。这个dup例程必须知道源字符串有一个未知的长度,只有在执行复制时才能确定,比如:

char *dup_string (char *s)
{
  char *d = realloc(strlen(s)+1);
  memcpy (d, s, strlen(s)+1);
  return d;
}

因此,您可以通过在调用方代码和被调用方epilog中使用它来透明地使用此函数,如下所示。。。

/* Source code: your programming language */
str s;
s = "whatever...";
func (s);

生成的汇编代码如下(例如使用IA32代码和C调用约定):

[Caller: this block repeated for every string passed as parameter to a function]
push offset s
call dup_string  ;string copy pointed by EAX
add esp,4   ;get rid of parameter    
push eax
call func
add esp,4   ;get rid of parameter
...
...
[Callee]
push ebp
mov ebp,esp
mov esi,[ebp+8]  ; ESI = pointer to string
...use string in ESI...
...
...
EPILOG 
    (this block repeated for every string passed as argument):
    mov esi,[ebp+8]  ;8 because in this example, it's the first argument.
    call free   /* standard free() function */
mov esp,ebp
ret

您可以从零长度的字符串开始。

由于您事先不知道大小,一旦执行分配,或者字符串被连接、重新分配、离开作用域等时,您将不得不在运行时动态分配和解除分配字符串存储

由于它是您自己的语言,我假设您也可以控制代码的生成方式。因此,您可以分配足够的堆栈空间并将字符串复制到那里。我在自己的函数中使用了这样一种方法,它附加了两个未知长度的路径部分(basepath和filename作为参数),因为我不想使用malloc和free。你唯一需要注意的是堆栈的对齐,因为它必须保持均匀。

当然,这取决于你的程序有多大,因为对于足够复杂的程序,堆栈可能很快就会变大。

最新更新