Home > Enterprise >  declare mutable string with varying size dynamically
declare mutable string with varying size dynamically

Time:07-11

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.

  • Related