【问题标题】:Redundant Assembly Instructions?冗余组装说明?
【发布时间】:2011-07-01 18:14:48
【问题描述】:

最近我一直在尝试学习逆向工程。因此,我一直在研究很多汇编代码。我对以下内容感到困惑:

movq    %rax,0xf8(%rbp)
movq    0xf8(%rbp),%rax

我已经看过好几次了。不是多余的吗?为什么编译器会这样做?我正在查看的二进制文件是用 gcc 编译的。

【问题讨论】:

    标签: gcc assembly x86 reverse-engineering


    【解决方案1】:

    您可能编译时没有优化 (-O)。您所看到的是对中间表示的直接、幼稚的翻译。像这样的片段通常是由于值存储在局部变量中,在本例中为 0xf8(%rbp)。然后立即使用该值,因此它再次将其加载到寄存器 %rax 中。优化器会发现从 %rax 存储只是为了恢复到同一个寄存器是多余的,并完全删除序列。如果所有优化阶段都失败了,至少有一个窥视孔会发现这两条指令是连续的。

    如果您确实启用了优化,那么这确实很奇怪,但如果您发布更大(但不是过大)的序列可能会得到解释。仍然有很多情况会产生明显次优的结果,但没有比这更明显的了。

    【讨论】:

    • 即使在最佳设置下,只要使用 volatile 说明符声明局部变量,该程序集列表也应该很容易生成。不过,这不是您应该在现实生活中的代码中找到的东西......
    • 虽然在这种情况下这可能是正确的答案,但必须注意冗余操作也用于重新对齐代码地址以帮助处理管道,这在“密集”循环之前很常见。
    • 这非常罕见(这不是您的情况的原因),但在处理内存映射设备时可能需要这样的序列。
    • @iManBiglari: NOP 只是一个字节,对于 inst fetch-and-decode 来解码跨越整个重新对齐的指令而不是一次一个字节(AMD 有列出要使用 2 到 15 个字节长度的最佳情况无操作 insts 的某处)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多