为什么有时使用 offset flat:label 有时不用

why sometimes use offset flat:label and sometimes not

我正在使用英特尔语法使用 GNU 汇编器学习汇编,有人认为我不太了解。举例来说,这段代码就在这里:

.intel_syntax noprefix
.data
string: .asciz "hello world"

.text
.global entry
.type entry, @function

entry:
    mov byte ptr[string + 4], 'a'
    mov eax, offset flat:string
    ret

我想到使用 offset flat: 因为我们正在编写可重定位代码。但是为什么我们不在他的行中也指定 offset flat:string : mov byte ptr[string + 4], 'a' 就像我们在这里所做的那样 mov eax, offset flat:string ?

我真的很困惑。如果执行 mov byte ptr[string + 4], 'a' 可以获取 string 标签的地址 + 4 那么为什么执行 mov eax, string 不一样?

编辑:

澄清一下,在调用 entry 之后,我使用 printf 打印 EAX 中的内容,如下所示:

#include <stdio.h>

extern char *entry(void);

int main(int argc, char*argv[])
{
    printf("%s", entry());

}

当你想要一个符号地址作为立即数时,你总是需要 OFFSET,比如 AT&T 语法 $string 而不是 string。其他任何时候都不需要它。


基本上归结为这样一个事实,即在 GAS Intel 语法中(如 AT&T movb $'a', string+4),string 即使没有 [] 也是一个内存操作数,因此它需要额外的语法来询问地址而不是该地址的内存。

当使用 string 作为 [string + 4] 的一部分时,您不是在请求偏移量,而是在 label/symbol 地址寻址内存。将其用作寻址模式的一部分。

如果您更愿意使用 better-designed 语法,其中 mov eax, string+4 确实为您提供了地址(无需取消引用),请使用 NASM.

否则请参阅 Confusing brackets in MASM32(GAS 的 Intel 语法在大多数方面都类似于 MASM,只是 mov eax, [12] 是从该绝对地址加载的,而不是 MASM 的等价于 [=19 的疯狂=]),

并且有些相关: 关于 GAS 如何解析常量,但更多的是关于 .equ foo, 4 / foo = 4 出现在引用它的指令之前和之后,如果您使用 mov eax, foo 而不是明确的 mov eax, [foo]mov eax, OFFSET foo

还有: