【发布时间】:2011-07-01 18:14:48
【问题描述】:
最近我一直在尝试学习逆向工程。因此,我一直在研究很多汇编代码。我对以下内容感到困惑:
movq %rax,0xf8(%rbp)
movq 0xf8(%rbp),%rax
我已经看过好几次了。不是多余的吗?为什么编译器会这样做?我正在查看的二进制文件是用 gcc 编译的。
【问题讨论】:
标签: gcc assembly x86 reverse-engineering
最近我一直在尝试学习逆向工程。因此,我一直在研究很多汇编代码。我对以下内容感到困惑:
movq %rax,0xf8(%rbp)
movq 0xf8(%rbp),%rax
我已经看过好几次了。不是多余的吗?为什么编译器会这样做?我正在查看的二进制文件是用 gcc 编译的。
【问题讨论】:
标签: gcc assembly x86 reverse-engineering
您可能编译时没有优化 (-O)。您所看到的是对中间表示的直接、幼稚的翻译。像这样的片段通常是由于值存储在局部变量中,在本例中为 0xf8(%rbp)。然后立即使用该值,因此它再次将其加载到寄存器 %rax 中。优化器会发现从 %rax 存储只是为了恢复到同一个寄存器是多余的,并完全删除序列。如果所有优化阶段都失败了,至少有一个窥视孔会发现这两条指令是连续的。
如果您确实启用了优化,那么这确实很奇怪,但如果您发布更大(但不是过大)的序列可能会得到解释。仍然有很多情况会产生明显次优的结果,但没有比这更明显的了。
【讨论】:
NOP 只是一个字节,对于 inst fetch-and-decode 来解码跨越整个重新对齐的指令而不是一次一个字节(AMD 有列出要使用 2 到 15 个字节长度的最佳情况无操作 insts 的某处)。