I made my own string declarator with macro in GNU Assembler in x64 machine.
.macro declareString identifier, value
.pushsection .data
\identifier: .ascii "\value"
"lengthof.\identifier"= . - \identifier
.popsection
.endm
This is how to use it:
.data
ANOTHER_VARIABEL: .ascii "why"
.text
_start:
declareString myString, "good"
lea rax, myString
mov rbx, lengthof.myString
So basically my macro is just label
maker.
So in debugger, rax
will be value of myString address because myString
basically just a label
.
And rbx
will be value of myString length (4).
So If I want change myString from good
which has 4 chars to rocker
which has 6 chars at runtime, I'm afraid it will overwrite another variabel
due to size collision.
I heard about heap memory but I'm not sure how does it work. I only know about stack, but I'm used to use stack as temporary backup.
So how do I declare mutable string in assembly?
CodePudding user response:
Same as in C; if you want to use static storage (in .data
) for the characters themselves (like static char myString[4] = "good";
note not including a terminating 0 byte), you actually need to reserve enough space for the largest you ever want this string to be. Like static char myString[128] = "good"
.
In your case, like .space 124
after your .ascii
would be a total of 128 bytes reserved after the label myString
.
You're correct that you shouldn't write past the size you reserve, although it would come after ANOTHER_VARIABEL
, not before, since that part of your .data
section is earlier in your source than where you use the macro containing .pushsection
If you wanted to do dynamic allocation, you might want to make an mmap(..., MAP_PRIVATE|MAP_ANONYMOUS, PROT_READ|PROT_WRITE, ...)
system call to allocate 1 or more pages of memory, then copy bytes into it. (You're writing a _start
so I'm assuming you're not linking libc.)
You could make your global variable a pointer, but if you free the old pointer and allocate a new one (or mremap to the new size), you should start with runtime allocation and init of it. You don't want to munmap
a page of .rodata
.
Or instead of mmap
/munmap
, Linux mremap(MREMAP_MAYMOVE)
can ensure that the allocation is big enough to hold your whole string without copying it. MAYMOVE lets it pick a new virtual address if there aren't enough free virtual pages following the currently pointed-to page, but without copying the actual data in the already-allocated pages.
There are tons of Q&As about making system calls in assembly so I'm not going into details about that; you can think about how you're managing memory in terms of system calls to make, separately from implementing it in asm. Thinking about it in C is pretty much equally valid; asm doesn't add much in terms of being able to declare static data or make system calls. Other than the fact that you could in asm make sure that a page of .data
was exclusively dedicated to this string, with no other things using it, so you could potentially let mremap
unmap that page from your .data and map it at a different virtual address.