assembly - 标签后面是冒号还是等号气体?
问题描述
有这个:
.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
?
解决方案
标签后跟:
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
.
推荐阅读
- python - Python 2.7.5 和 Python 3.6.5
- c++ - 精确到毫秒的日期和时间操作
- java - 私有变量的继承
- javascript - 在 ReactJs 中 defaultProps 是否有效
- typescript - TypeScript 内联静态类型保护
- reactjs - 使用 mapDispatchToProps 的 Redux 连接容器不起作用
- scala - 窗户上的苏打水
- css - SVG,为什么 :hover 可以改变笔画宽度但不能改变笔画颜色?
- c++ - 一次分配内存是否需要更多时间?
- angular - 使用 SSR 调试 Angular 6 Universal