气体标签后跟冒号还是等号?

Are labels followed by colon or equal sign in gas?

有这个:

.text
    .globl main
str:
    .string "hello world"
len = .-str #a strange assignment
main:
    mov , %eax
    mov , %edi
    movabs $str, %rsi
    mov $len, %rdx
    syscall 
    call exit

1) 这里是带冒号的 str(我通常看到的),但是 len 是由 = 赋值的。我不认为这是因为 str 是地址,而 len 是数字(因此类型不同),但为什么可以用不同的方式分配一个?或者两者都是标签?

2) 为什么要使用 mov str(%rip), %rsi,我可以使用 movabs $str, %rsi

标签后跟:

= 不是标签,它将符号定义为 assemble 时间常数,就像 .set.equ 那样。这是让 assembler 在 assemble 时为您计算字符串的长度。

. 是当前位置。将 . 视为此行开头的隐式标签。您可以等效地在字符串后放置一个 str_end: 标签并完成 len = str_end - str.


Why to use mov str(%rip), %rsi, when I can use movabs $str, %rsi?

它们不等同! mov str(%rip), %rsi 将从该地址加载 8 个字节,将字符串数据放入寄存器。但是你需要一个指向寄存器中字符串的 指针 作为 write(int fd, void *buf, size_t len) 系统调用的参数。在调试器中尝试 and/or strace 并观察它是否失败。

这就是为什么此代码中的 movabs 使用 $str 来获取地址作为 64 位立即数。

然而,那是 movabs 8 字节立即数相当于 10 字节指令总数,并且当加载程序为可执行文件选择实际基地址时,绝对需要在 PIE 可执行文件或库(ELF 共享对象)中进行运行时修正。

你实际上想要 LEA str(%rip), %rsi(7 个字节),或者 non-PIE Linux executable where static addresses fit in the low 31 bits of address space, mov $str, %esi