Search code examples
assemblyx86-64gnu-assembler

Are labels followed by colon or equal sign in gas?


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?


Solution

  • 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 use movabs $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.