Suppose, I've created a local variable in stack or rather allocated memory for a string and now I want to put a value in it.
push ebp
mov ebp, esp
sub esp, 0xff ; 255 bytes
And storing strings in the stack in C:
strcat(my_str1, "something1");
strcat(my_str1, get_var2());
strcat(my_str1, "something3");
strcat(my_str1, get_var4());
I want to undertand how to do that without "strcat" in FASM or NASM:
;1
mov byte ptr [esp - 1], 's'
mov byte ptr [esp - 2], 'o'
mov byte ptr [esp - 3], 'm'
mov byte ptr [esp - 4], 'e'
; and so on
Is this how it's done? And about the part with "get_var2()" and "get_var4()"?
;2
call get_var2
mov ??byte?? ptr [esp - 11], eax
; or lea?
1) sub esp, 0xff
keep esp
aligned, at least per 4. If you need only 255 bytes for C string (254 chars + zero terminator), then allocate 256.
2) mov [esp-1],'s'
You already decremented esp
, so the local variable is at some [esp+X]
address (how much depends how many other values you did push on stack). Or rather use [ebp-Y]
with C-like function prologue, initializing stack frame pointer in ebp
first (push ebp
mov ebp,esp
sub esp,local_vars_size
.. then epilogue mov esp,ebp
pop ebp
ret
).
But never touch values UNDER esp
, unless you know exactly what you are doing and why (like writing into red zone in 64b mode), because if you are not sure, then in 99% it will end as bug, and very often one of those difficult to find, which affects the code only rarely.
3) in NASM those 4 movs can be done with single dword constant mov [esp-4],dword 'emos'
(BTW, you probably did want to set 'some'
?)
And yes, that's the common way how compiler set up shorter constants in locally allocated stack space, for bigger data they may use memcpy
from constant template data.
4) about get_var2()
, so get_var2()
returns stable (char *)
pointer? Then you will have to reimplement full strcat
, unless you can tell how many chars are already in the string, and how many will be added. If get_var2()
returns some value, you have first convert it to some characters and decide how many, etc.. then you can write them directly, or in some loop, etc. Too broad.
Also when operating on local stack, I would allocate some safety space around your variables in case you go beyond boundaries and overwrite few bytes over. And you even may set up those extra bytes to some canary value first, and then check it upon function end, to see if some stack overwrite happened (in debug builds at least). And instead of strcat
you then need strncat
or similar, to avoid stack overrun by malicious data.
Otherwise as Jester suggest, maybe try to implement just strcat
first, on fixed memory buffers, so you can focus on the code itself, not resolving allocation of local memory. Then you may build upon it, even use it as function call.