【问题标题】:8086 Assembly question, what does this code do8086 汇编问题,这段代码是做什么的
【发布时间】:2011-06-13 08:05:23
【问题描述】:

我在装配课程中收到了这个问题:

这个程序有什么作用
应该怎么称呼?

push ebp
mov ebp, esp    
push esi

mov esi, [ebp+4]
mov eax, [esi]
sub eax, [esi+4]
add esi, 8
mov [ebp+4], esi

pop esi
pop ebp
ret

看起来[ebp+4] 是一个参数而不是返回地址,所以它应该用“jmp”而不是“call”来调用。 我真的不明白应该在[esi+4]esi+8 上找到什么(返回地址) 嗯,我真的很困惑,希望你能帮助我
提前致谢。

【问题讨论】:

  • 具有 32 位寄存器的 8086?

标签: assembly intel x86


【解决方案1】:

正如您正确地注意到的,如果使用call 调用此例程,则[ebp+4] 是返回地址。这并不意味着这是一个坏主意。

假设使用call 调用例程。此时,压入堆栈的“返回地址”是紧跟在call 操作码之后的字节的地址。我们称这个地址为 x。然后,该例程从地址 x 提取两个 32 位字,一个在地址 x,一个在地址 x+4。它从第一个单词中减去第二个单词,将结果存储在eax 中。最后,例程将值 x+8 存储在堆栈槽 [ebp+4] 中,最终结果是当到达 ret 时,在地址 x+8。有了这个假设,该例程看起来像是一种减去位于代码中间的整数的方法,如下所示:

call yourroutine
dd   56478634
dd   18943675
mov  ebx, eax  ; an example instruction

这里,call 返回到mov 指令,此时eax 包含值 37534959(即从 56478634 中减去 18943675)。

作为一个代码例程,它并不是非常有用,因为它是一种使用硬编码的常量值加载eax 的复杂方式(代码空间在执行期间通常是只读的)。有人可能会想,这样的例程可能会作为运行时支持的一部分出现,以支持某些架构上的动态链接(动态链接是一个棘手的主题)。

现在,我们假设使用jmp 调用例程。 [ebp+4] 现在指定当时堆栈顶部的任何内容。该例程获取该值(我们称其为 y),获取地址 yy+4 处的两个单词,将减法结果计算为eax,然后将 y+8 存储回 [ebp+4] 插槽。最后,ret解释该槽作为返回地址,即执行应该跳转到的某些代码的地址。没有call 操作码参与该地址的产生并不重要; ret 仍然会跳转到它。这一次,调用代码可能如下所示:

    push   foobar
    jmp    yourroutine
    ...  ; unreached code

foobar:
    dd 56478634
    dd 18943675
    mov  ebx, eax  ; an example instruction

这一次,这看起来像是一个带有eax 的固有加载的参数化跳转。类似的代码可以存在于某些interpreters for threaded code 的实现中。然而,作为一个家庭作业问题,我很确定这不是预期的(线程代码解释器甚至比动态链接更复杂)。

【讨论】:

    【解决方案2】:

    不,绝对应该用call 调用它——它的末尾有一个ret

    就它的作用而言,您应该坐下来拿一张纸,上面列出寄存器,然后在脑海中单步执行该代码,随时更新寄存器。然后应该很明显发生了什么:

    eax:
    esp:
    ebp:
    esi:
    

    以及其他相关的内存(例如栈顶周围的区域)。

    这是学习编程(无论如何都是小程序)的理想方式,因为您可以学习详细分析事物并真正理解它们。恐怕这与我为家庭作业提供的帮助一样多:-)

    【讨论】:

      【解决方案3】:

      当您调用此函数时,返回地址(调用后指令地址的 eip)被压入堆栈,在第一个函数前导码之后,[ebp+4] 引用该返回地址。然后函数的主体将此地址视为 2 个整数,减去它们,结果放入 eax,然后返回地址增加 8,即这 2 个整数的大小为 add esi,8mov [ebp+4], esiret 只是让我们回到那个新的返回地址(希望这是一个有效的指令......)。

      一个奇怪的功能,看起来在一些自我修改的代码等......

      【讨论】:

      • 但是 p+=2 没有效果,因为 p 是一个堆栈变量。
      • 你提前得到了我的投票,所以我不能再投票了。 (我对你有信心……):-)
      • 事情越来越清楚了,但有一件事我不明白。当我们使用“ret”时,eip
      • 当你调用时,当前的eip被压入堆栈,而[ebp+4]确实是返回地址。
      • 我的猜测是写它的人没有测试它,并且假设没有帧指针,或者没有真正计算好第一个参数的偏移量。
      猜你喜欢
      • 2015-01-14
      • 2019-02-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-31
      • 2022-12-09
      • 1970-01-01
      相关资源
      最近更新 更多