When i declare a string in assembly like that:
string DB "My string", 0
where is the string saved? Can i determine where it will be saved when declaring it?
When i declare a string in assembly like that:
string DB "My string", 0
where is the string saved? Can i determine where it will be saved when declaring it?
db
assembles output bytes to the current position in the output file. You control exactly where they go.
There is no indirection or reference to any other location, it's like char string[] = "blah blah"
, not char *string = "blah blah"
(but without the implicit zero byte at the end, that's why you have to use ,0
to add one explicitly.)
When targeting a modern OS (i.e. not making a boot-sector or something), your code + data will end up in an object file and then be linked into an executable or library.
On Linux (or other ELF platforms), put read-only constant data including strings in section .rodata
. This section (along with section .text
where you put code) becomes part of the text segment after linking.
Windows apparently uses section .rdata
.
Different assemblers have different syntax for changing sections, but I think section .whatever
works in most of the one that use DB
for data bytes.
;; NASM source for the x86-64 System V ABI.
section .rodata ; use section .rdata on Windows
string DB "My string", 0
section .data
static_storage_for_something: dd 123 ; one dword with value = 123
;; usually you don't need .data and can just use registers or the stack
section .bss ; zero-initialized memory, bytes not stored in the executable, just size
static_array: resd 12300000 ;; 12300000 dwords with value = 0
section .text
extern puts ; defined in libc
global main
main:
mov edi, string ; RDI = address of string = first function arg
;mov [rdi], 1234 ; would segfault because .rodata is mapped read-only
jmp puts ; tail-call puts(string)
peter@volta:/tmp$ cat > string.asm
(and paste the above, then press control-D)
peter@volta:/tmp$ nasm -f elf64 string.asm && gcc -no-pie string.o && ./a.out
My string
peter@volta:/tmp$ echo $?
10
10 characters is the return value from puts
, which is the return value from main because we tail-called it, which becomes the exit status of our program. (Linux glibc puts
apparently returns the character count in this case. But the manual just says it returns non-negative number on success, so don't count on this)
I used -no-pie
because I used an absolute address for string
with mov
instead of a RIP-relative LEA.
You can use readelf -a a.out
or nm
to look at what went where in your executable.