GCC 上 x86 intel asm 中方括号前的偏移量 [英] Offset before square bracket in x86 intel asm on GCC

查看:24
本文介绍了GCC 上 x86 intel asm 中方括号前的偏移量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从我找到的所有文档中,没有提到像英特尔 x86 语法中的 offset[var+offset2] 这样的语法,但是 GCC 有以下标志

From all the docs I've found, there is no mention of syntax like offset[var+offset2] in Intel x86 syntax but GCC with the following flags

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

对于这个程序

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

生产

    .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

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

I'd like to highlight the line mov BYTE PTR -1[rbp], 104 where offset -1 appears outside the square brackets. TBH, I'm just guessing that it is an offset, can anyone direct me to a proper documentation highlighting this ?

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

Here is a similar question: Squared Brackets in x86 asm from IDA where a comment does mention that it is an offset but I'd really like a proper documentation reference.

推荐答案

是的,这只是 [rbp - 1] 的另一种写法,而 -1 是技术 x86 寻址模式术语1中的置换.

Yes, it's just another way of writing [rbp - 1], and the -1 is a displacement in technical x86 addressing mode terminology1.

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

The GAS manual's section on x86 addressing modes only mentions the [ebp - 4] possibility, not -4[ebp], but GAS does assemble it.

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

And disassembly in AT&T or Intel syntax confirms what it meant. x86 addressing modes are constrained by what the machine can encode (Referencing the contents of a memory location. (x86 addressing modes)), so there isn't a lot of wiggle room on what some syntax might mean. (This syntax was emitted by GCC so we can safely assume that it's valid. And that it means the same thing as the -1(%rbp) it emits in AT&T syntax mode.)

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

Footnote 1: The whole rbp-1 effective address is the offset part of a seg:off address. The segment base is fixed at 0 in 64-bit mode, except for FS and GS, and even in 32-bit mode mainstream OSes use a flat memory model, so you can ignore the segment base. I point this out only because "offset" in x86 terminology does have a specific technical meaning separate from "displacement", in case you care about using terminology that matches Intel's manuals.

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

For some reason GCC's choice of syntax depends on -fno-pie or not. https://godbolt.org/z/iK9jh6 (On modern GNU/Linux distros like your Arch system, -fpie is enabled by default. On Godbolt it isn't).

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

This choice continues with optimization enabled, if you use volatile to force the stack variable to be written, or do other stuff with pointers: e.g. https://godbolt.org/z/4P92Fk. It applies to arbitrary dereferences like ptr[1 + x] from function args.

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

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

IDK why GCC's internals choose differently based on PIE mode. No obvious reason; perhaps for some reason they just use different code paths in GCC's internals, or different format strings and they just happen to make different choices.

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

Both with and without PIE, a global (static storage) is referenced as glob[rip], not [RIP + glob] which is also supported. In both cases that means glob with respect to RIP, not actually RIP + absolute address of the symbol. But that's an exception to the rule that applies for any other register, or for no register.

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

GAS .intel_syntax is MASM-like, and MASM certainly does support symbol[register] and I think even 1234[register]. It's more normal for the displacement.

这篇关于GCC 上 x86 intel asm 中方括号前的偏移量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆