Passing string by value in assembly without knowing it's size

So I am implementing you could say subset of C compiler, and there is one feature which gives me headache. So I would like some ideas how to solve it.

In my prog. language are all arguments passed by value including strings, whose are declared like this:

string str;

And my issue is that, as you can see, I don't know string size during its declaration(difference from C), so when i am generating assembly i don't know how big space to create on stack for it. If I have code like this:

string str;
int number;
str = something;

I don't know how to allocate correct space for string str, when it later can be assigned practicaly anythign. And last condition is, that I can't use heap.

Thanks, and sorry for my bad english.

Edit:

Thanks for the answers. From the responses it seems to me, that biggest problem will be reallocation string if it gets bigger on stack in case when there is already something behind this string, the simplest solution i think would be create new space on stack and the old one let be until local scope will be disposed... It would be wasting, yes

Answers


I assume you have some sort of dup_string routine that duplicates a string in a new memory block. That dup routine must be aware that the source string has an unkown length, that will be only determined while the copying is being performed, something like:

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

So you can use this function transparently by using it in your caller code and your calle epilog, like this...

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

Generated assembly code would be like this (example using IA32 code, and C calling convention):

[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

You can start with a zero-length string.

Since you don't know the size ahead of time you will have to dynamically allocate and deallocate string storage in your runtime once an assignment is performed or when strings are concatenated, re-assigned, leave scope, etc.


Since it is your own language, I assume that you have also control over how the code is generated. So you can allocate enough stackspace and copy the string there. I was using such an approach in my own function, which appended two path parts of unknown length (basepath and filename as arguments) because I didn't want to bother with malloc and free. The only thing you have to take care of is the alignment of the stack, because it has to stay even.

Of course, it depends on how big your programs are, because for sufficiently complex programs, the stack may soon get to big.


Need Your Help

Getting Django to play nice with Angular routing

javascript python angularjs django

I have an existing Django project and am adding a new app which consists of an API (using the rest-framework) and an angular app. This app contains one Django template, which simply serves as a way...