8086汇编问题,此代码做什么

问题描述

| 我在组装课程中收到了以下问题: 这个程序做什么 以及如何称呼它?
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
看起来ѭ1是一个参数而不是返回地址,因此应使用\“ jmp \”而不是\“ call \”进行调用。 我不太了解
[esi+4]
esi+8
(寄信人地址)上的内容 嗯,我真的很困惑,希望你能帮助我 提前致谢。     

解决方法

        正如您正确地指出的那样,如果使用
call
调用此例程,则
[ebp+4]
是返回地址。这并不意味着这是一个坏主意。 假定例程以
call
调用。此时,压入堆栈的“返回地址”是紧随“ 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]
槽中。最后,“ 10”将那个插槽解释为返回地址,即执行应跳转到的某些代码的地址。该地址的产生不涉及任何“ 4”操作码,这无关紧要;
ret
仍会跳到它。这次,调用代码可能类似于:
    push   foobar
    jmp    yourroutine
    ...  ; unreached code

foobar:
    dd 56478634
    dd 18943675
    mov  ebx,eax  ; an example instruction
这次,这看起来像是带有一些固有负载inherent8ѭ的参数化跳转。诸如此类的代码可以存在于某些线程代码解释器的实现中。但是,作为一个作业问题,我非常确定这不是预期的目的(线程代码解释器比动态链接还要毛茸茸)。     ,        不,绝对应以
call
开头-末尾有
ret
。 就其功能而言,您应该坐在一张纸上,列出寄存器列表,然后单步执行代码,然后随心更新寄存器。然后很明显发生了什么:
eax:
esp:
ebp:
esi:
以及其他相关的内存(例如堆栈顶部周围的区域)。 这是学习编程的一种理想方式(无论如何对于小型程序而言),因为您可以学习详细地分析事物并真正理解它们。而且,恐怕这和我要给家庭作业分配的帮助差不多:-)     ,        当您对该函数进行调用时,返回地址(调用后指令地址的地址)被压入堆栈,并且在第一个函数前导之后,,1ѭ引用该返回地址。然后,函数主体将这个地址视为2个整数,将它们相减,结果存入
eax
,然后将返回地址加8,即,这2个整数的大小分别增加
add esi,8
mov [ebp+4],esi
ret
只是将我们带回到新的寄信人地址(希望这是一条有效的说明。。。)。 怪异的功能,在一些自修改代码中看起来就位...     

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...