首页 > 解决方案 > 标签后面是冒号还是等号气体?

问题描述

有这个:

.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)这里是str用冒号(我通常看到),但随后len=. 我不认为那是因为str是地址和len数字(因此类型不同),但为什么可以分配不同的方式?还是两个标签?

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

标签: assemblyx86-64gnu-assembler

解决方案


标签后跟:

An=不是标签,它以某种方式将符号定义为汇编时间.set常数.equ。这是让汇编器在汇编时为您计算字符串的长度。

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


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

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

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

但是,这是将标签/符号地址放入寄存器的最糟糕的方法movabs一个 8 字节的立即数相当于一个 10 字节的指令总数,并且是绝对的,当加载器为可执行文件选择一个实际的基地址时,它需要在 PIE 可执行文件或库(ELF 共享对象)中进行运行时修复。

您实际上想要LEA str(%rip), %rsi(7 个字节),或者在静态地址适合地址空间的低 31 位的非 PIE Linux 可执行文件中,mov $str, %esi .


推荐阅读