Assembly 8086汇编问题,这段代码做什么

Assembly 8086汇编问题,这段代码做什么,assembly,intel,x86,Assembly,Intel,X86,在我的组装课程中,我收到了这个问题: 此过程的作用是什么 它应该如何命名 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 它看起来像是一个参数而不是返回地址,所以应该用“jmp”而不是“call”来调用它。 我真的不明白应该在[esi+4]和esi+8上找到什么(返回地址) 嗯

在我的组装课程中,我收到了这个问题:

此过程的作用是什么
它应该如何命名

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
它看起来像是一个参数而不是返回地址,所以应该用“jmp”而不是“call”来调用它。 我真的不明白应该在
[esi+4]
esi+8
上找到什么(返回地址) 嗯,我真的很困惑,希望你能帮我

提前感谢。

当您调用此函数时,返回地址(调用后指令地址的eip)被推送到堆栈上,在第一个函数前导之后,
[ebp+4]
引用该返回地址。然后,函数体将该地址视为2个整数,被减法后的结果放入
eax
,然后返回地址增加8,即这2个整数的大小通过
add esi,8
mov[ebp+4],esi
ret
只是将我们放回到新的返回地址(希望这是一条有效的指令……)


一个奇怪的函数,在一些自我修改的代码中看起来合适

不,它肯定应该用
call
调用-它的末尾有一个
ret

就它的作用而言,你应该坐下来拿一张纸,上面有一个寄存器列表,然后一步一步地在你的头脑中编码,在你走的时候更新寄存器。那么发生的事情应该是显而易见的:

eax:
esp:
ebp:
esi:
以及其他相关内存(例如堆栈顶部周围的区域)


这是学习编程的理想方式(无论如何,对于小程序来说),因为您可以学习详细分析事物并真正理解它们。恐怕这和我给家庭作业的帮助差不多:-)正如你正确地注意到的,如果这个例程是用
调用调用的,那么
[ebp+4]
就是返回地址。这并不意味着这是一个坏主意

假设使用
调用调用该例程
。此时,推送到堆栈上的“返回地址”是紧跟在
调用之后的字节地址。我们把这个地址叫做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),获取地址y和y+4处的两个单词,将减法结果计算到
eax
,然后将y+8存储回
[ebp+4]
插槽。最后,
ret
将该插槽解释为返回地址,即执行应跳转到的某些代码的地址。无
呼叫
操作码参与该地址的生成并不重要
ret
仍将跳转到它。这一次,调用代码可能如下所示:

    push   foobar
    jmp    yourroutine
    ...  ; unreached code

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

这一次,这看起来像是一个带有
eax
固有加载的参数化跳转。这样的代码可以存在于某些应用程序的实现中。然而,作为一个家庭作业问题,我很确定这不是我的初衷(线程代码解释器比动态链接更麻烦)。

但是p+=2没有任何效果,因为p是堆栈变量。你提前得到了我的投票,所以我不能再投票了。(我对你有信心……:-)事情越来越清楚了,但有一件事我不明白。当我们使用“ret”时,eip当您调用时,当前的eip被推送到堆栈上,实际上,
[ebp+4]
是返回地址。我猜想编写它的人没有测试它,并且假设没有帧指针,或者没有很好地计算到第一个参数的偏移量。一个带有32位寄存器的8086?