having this:
.text
.globl main
str:
.string "hello world"
len = .-str #a strange assignment
main:
mov $1, %eax
mov $1, %edi
movabs $str, %rsi
mov $len, %rdx
syscall
call exit
1) here is str
with colons (as I see usually), but then len
is assigned by =
. I do not think that is because the str
is address, and len
is number (and thus different type), but why one can be assigned different ways? Or are both labels?
2) Why to use mov str(%rip), %rsi
, when I can use movabs $str, %rsi
?
Labels are followed by :
An =
isn't a label, it defines a symbol as an assemble-time constant the way .set
or .equ
does. This is getting the assembler to calculate the length of the string for you, at assemble time.
.
is the current position. Think of .
as an implicit label at the start of this line. You could equivalently have put a str_end:
label after the string and done len = str_end - str
.
Why to use
mov str(%rip), %rsi
, when I can usemovabs $str, %rsi
?
Those aren't equivalent! mov str(%rip), %rsi
would load 8 bytes from that address, getting the string data into a register. But you need a pointer to the string in a register as an arg for a write(int fd, void *buf, size_t len)
system call. Try it in a debugger and/or strace
and watch it fail.
That's why the movabs
in this code uses $str
, to get the address as a 64-bit immediate.
However, that's the worst way to put a label/symbol address into a register. movabs
with an 8 byte immediate amounts to a 10-byte instruction total, and being absolute it needs runtime fixups in a PIE executable or library (ELF shared object) when the loader chooses an actually base address for the executable.
You actually want LEA str(%rip), %rsi
(7 bytes), or in a non-PIE Linux executable where static addresses fit in the low 31 bits of address space, mov $str, %esi
.