GCC 上 x86 intel asm 中方括号前的偏移量

Hri*_*tik 3 x86 assembly gcc gnu-assembler intel-syntax

从我发现的所有文档中,没有提到像offset[var+offset2]Intel x86 语法那样的语法,但是 GCC 有以下标志

gcc -S hello.c -o - -masm=intel

对于这个程序

#include<stdio.h>
int main(){
    char c = 'h';
    putchar(c);
    return 0;
}

Run Code Online (Sandbox Code Playgroud)

产生

    .file   "hello.c"
    .intel_syntax noprefix
    .text
    .globl  main
    .type   main, @function
main:
.LFB0:
    .cfi_startproc
    push    rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    mov rbp, rsp
    .cfi_def_cfa_register 6
    sub rsp, 16
    mov BYTE PTR -1[rbp], 104
    movsx   eax, BYTE PTR -1[rbp]
    mov edi, eax
    call    putchar@PLT
    mov eax, 0
    leave
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE0:
    .size   main, .-main
    .ident  "GCC: (Arch Linux 9.3.0-1) 9.3.0"
    .section    .note.GNU-stack,"",@progbits
Run Code Online (Sandbox Code Playgroud)

我想突出显示mov BYTE PTR -1[rbp], 104偏移-1出现在方括号外的行。TBH,我只是猜测这是一个偏移量,任何人都可以指导我找到突出显示这一点的适当文档吗?

这是一个类似的问题:来自 IDA 的 x86 asm 中的 Squared Brackets评论确实提到它是一个偏移量,但我真的很想要一个适当的文档参考。

Pet*_*des 5

是的,这只是另一种写法[rbp - 1],它-1是技术 x86 寻址模式术语1替代

GAS 手册关于 x86 寻址模式的部分只提到了[ebp - 4]可能性,而不是-4[ebp],但 GAS 确实组装了它。

AT&T 或 Intel 语法中的反汇编证实了它的含义。x86 寻址模式受机器可以编码的内容的限制(引用内存位置的内容。(x86 寻址模式)),因此在某些语法可能意味着什么上没有太多的回旋余地。(这个语法是由 GCC 发出的,所以我们可以安全地假设它是有效的。它的意思与-1(%rbp)它在 AT&T 语法模式下发出的意思相同。)

脚注 1:整个rbp-1有效地址是seg:off 地址的偏移部分。64 位模式下段基数固定为 0,除了 FS 和 GS,即使在 32 位模式下主流操作系统也使用平面内存模型,因此可以忽略段基数。我指出这一点只是因为 x86 术语中的“偏移”确实具有与“位移”不同的特定技术含义,以防您关心使用与英特尔手册匹配的术语。


出于某种原因,GCC 的语法选择取决于-fno-pie与否。 https://godbolt.org/z/iK9jh6 (在像 Arch 系统这样的现代 GNU/Linux 发行版上-fpie,默认情况下是启用的。在 Godbolt 上则不是)。

如果您使用volatile强制写入堆栈变量或使用指针执行其他操作,则此选择将继续启用优化:例如https://godbolt.org/z/4P92Fk。它适用于任意取消引用,如ptr[1 + x]函数 args。

  • GCC-fno-pie选择[rbp - 1][rdi+4+rsi*4]
  • GCC-fpie选择-1[rbp]4[rdi+rsi*4]

IDK 为什么 GCC 的内部基于 PIE 模式选择不同。没有明显的原因;也许出于某种原因,他们只是在 GCC 的内部使用了不同的代码路径,或者不同的格式字符串,他们只是碰巧做出了不同的选择。

无论有没有 PIE,全局(静态存储)都被引用为glob[rip],不[RIP + glob]支持。在这两种情况下,这意味着glob 相对于RIP,实际上并不是 RIP + 符号的绝对地址。但这是适用于任何其他寄存器或无寄存器的规则的一个例外。


GAS.intel_syntax类似于 MASM,而且 MASM 确实支持symbol[register],我认为甚至1234[register]. 位移比较正常。