首页 > 解决方案 > 给定序列的一条 ASM 指令

问题描述

我需要将以下序列编写为一条 ASM 指令,但我不知道它是什么指令:

push ebp
mov ebp,esp
mov ebp,[ebp]
mov ebx,[ebp]
mov [esp],ebx

标签: assemblyx86nasm

解决方案


用 1 条甚至 2 条指令完全重现所有输入值的所有行为是不可能的。


前 3 条指令压入 EBP,然后将刚刚保存的 EBP 值重新加载到 EBP。所以前 3 个的净效应是lea esp, [esp-4](不是 SUB,因为那会影响 FLAGS)1

push ebp          ; save old EBP,  ESP-=4

mov ebp,esp 
mov ebp,[ebp]     ; reload old EBP
;; net effects so far: ESP-=4.
;;                     memory at [ESP] replaced with old-EBP.

mov ebx,[ebp]     ; EBX = [EBP].  This could overlap with dword [ESP]

mov [esp],ebx     ; replace pushed original_EBP value with [original_EBP]

我怀疑他们回答他们正在寻找的可能是push [ebp],但如果是这样,这个问题完全是垃圾。 有 2 个不会重现的关键副作用:

  • 它不会[EBP]在 EBX 中留下价值
  • 如果[EBP](部分)重叠[ESP-4]

要重现 set-EBX 行为,您至少需要 2 条指令。x86 有一些复杂的指令,但没有一个会推送内存复制到整数寄存器。 Jester 的 2 条指令序列看起来最接近:mov ebx, [ebp]/push ebx

您也可以考虑push dword [ebp]/ mov ebx, [esp],但这显然效率较低,并且存储/重新加载[ebp]与给定序列不同的值。

[ebp]但是,如果与推送目的地重叠,它们都不会重现确切的行为。例如lea ebp, [esp-2],在这些说明之前考虑。 给定的序列在加载之前存储了 EBP [ebp],没有任何东西告诉我们没有重叠。 如果您使用 EBP 作为帧指针,通常它不会指向 ESP 下方,但我们没有被告知。



脚注 1: 当然,假设没有其他线程正在修改我们存储/重新加载 EBP 的内存,否则存储/重新加载可能不会总是重新加载相同的值!我们最终会存储到[esp],因此如果 ESP 指向不可读写的内存,优化掉一些内存访问并不会改变故障行为。

问题中没有任何内容表明我可以对 ESP 指向的位置做出任何假设,或者与该内存位置异步发生的其他事情。

就我们所知,ESP 指向一个 MMIO 区域,每次存储/加载都有一个可见的副作用,比如将位放在并行端口的引脚上,或者读取它们!

在正常情况下,ESP 指向写回区域中没有其他线程引用的可读写内存,那么优化存储/重新加载是有效的。但就像我说的,没有什么说我们可以假设。


推荐阅读