【问题标题】:Purpose of conditional jump after zeroing a register寄存器清零后条件跳转的目的
【发布时间】:2017-01-04 01:01:46
【问题描述】:

我遇到了一个 x86 汇编器是这样的:

  push eax
  xor eax, eax
  je label1
  add esp, 4
label1:
  pop eax

据我所知,xor 指令将始终保持 ZF 设置,这反过来又使 je 始终触发。这段代码是否等同于nop? 编译器会生成这个吗?如果是,为什么?

【问题讨论】:

  • 可能有其他代码直接跳转jeadd指令,跳过xor。但它看起来不太可能,而且看起来不太可能某些高级语言编译器会生成这样的代码。
  • @Ped7g 不,没有其他代码跳转到这个 sn-p。
  • 那么从执行的角度来看是没用的。 (它可能仍然通过指令操作码形成一些二进制数据,因此可能其他部分正在将那些xor/je/add 指令作为数据读取)。也可能是后来其他人修改代码的结果,没有源代码。或者其他什么,很难说 - 在组装整个二进制文件和目标平台时形成完整的上下文。您可能遗漏了一些小细节。
  • 而不是xor eax,eaxjeor eax,eax 之后是有意义的,但其余的(add esp,4pop eax)则不会。这段代码看起来很像以前不同,并且由于某种原因被修改了。
  • 你在哪里遇到这个问题?你能提供一些上下文吗?

标签: assembly compilation x86


【解决方案1】:

直接回答您的问题:

这段代码是否等同于nop

没有。它确实更改了标志(通过xor eax,eax),并且确实将[esp-4] 的内存设置为原始eax 值。 (我的意思是第一条指令和最后一条指令之间的总机器状态差异)

此外,它在内存中形成的操作码与其他形式的 nop 不同(以防这些操作码也被读取为其他地方的数据,例如校验和作为防篡改措施等)。

并且内部 CPU 状态可能会比nop 修改得更多,一些分支预测数据确实很可能由于je 而改变,并且内存写入堆栈区域可能会触发缓存状态的进一步变化(不太可能,因为这部分内存可能被围绕这部分的指令广泛使用)。而且它的时间与nop不同。

编译器会生成这个吗?如果是,为什么?

我不这么认为,编译器很少在大量指令中使用标志,并且要在不稳定的堆栈区域中设置内存,将使用move [esp-4],eax,但首先编译器不太可能需要在那里设置值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-02-04
    • 1970-01-01
    • 2014-02-21
    • 1970-01-01
    • 1970-01-01
    • 2018-07-21
    • 2016-08-20
    相关资源
    最近更新 更多