2013-12-09 18 views
0

所以我正在实现你可以说C编译器的子集,并且有一个特性让我头疼。所以我想要一些想法如何解决它。通过汇编中的值传递字符串,而不知道它的大小

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

string str; 

而我的问题是,你可以看到,我不知道它的声明(由C差)期间字符串大小,所以当我正在生成组装时,我不知道在堆栈上为它创建多大的空间。 如果我有这样的代码:

string str; 
int number; 
str = something; 

我不知道如何分配正确的空间字符串str,当它以后可以分配practicaly anythign。最后一个条件是,我无法使用堆。

谢谢,对不起我的英语不好。

编辑:

感谢您的回答。从我看来,最大的问题将是重新分配字符串,如果它在堆栈中变得更大,以防字符串后面有东西,我认为最简单的解决方案是在堆栈上创建新的空间,旧的直到本地范围将被处置...这将是浪费,是的

+0

你通常可以在堆栈上分配动态数组相当容易,但它通常需要一个基本指针,因为偏移量会发生变化。看看在你选择的架构上如何实现alloca和C99可变长度数组。棘手的部分是在混合调用/数据堆栈上返回动态字符串。后一个问题的一个相对简单的解决方案是一个固定的返回缓冲区(例如,单个值的第二个“栈”),被调用者从该缓冲区中获得结果。 – doynax

回答

0

我假设你有某种dup_string例程在新的内存块中复制一个字符串。这DUP日常一定要注意,源字符串有一个未知的长度,这将在执行复制时仅确定,是这样的:

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

所以,你可以使用此功能透明地在您的来电者使用它代码和卡莱收尾,这样的...

/* 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 
0

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

既然你不提前知道时间,你将有一次分配执行或者字符串连,重新分配,则保留范围等在运行时动态分配和释放字符串存储大小

0

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

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

+0

我考虑过这个问题,但问题是,字符串的长度仅受堆栈大小的限制... –

+0

那么对于内存使用情况你有什么限制?你说你不想使用堆,所以内存应该从哪里来?从OS分配它(哪一个?)? – Devolus

+0

一个不能使用堆cuz我使用的程序集不支持堆分配,不要问为什么:P,但我想说的是,在堆栈中分配空间,希望字符串不会大于该空间不会工作为了我 –

相关问题