Ale*_*lex 5 assembly reverse-engineering disassembly
我有一个跟踪指令,想要提取函数调用和返回.
我发现除了call指令,push+ jmp和push+ ret可用于函数调用?起初我想确定是正确的吗?如果是的话他们之间有什么区别?
此外,如果push+ ret是一种调用,那么函数的结束或返回是什么?在ret没有push指示之前看到它?
简单来说:
通话地址
这会将更新的程序计数器(指向 之后的指令call)压入堆栈,然后跳转到指示的地址(可能适用寻址模式)。
回复
该指令在内部弹出堆栈并从堆栈中寻址并跳转到它。这很好地匹配,call因此它可以返回到之前的指令之后call。
跳转地址
这只是跳转到给定的地址(可能适用寻址模式)。它对堆栈根本没有任何作用。
push address
ret
Run Code Online (Sandbox Code Playgroud)
它将弹出并跳转到如上所述被推入堆栈的地址。这是在跳转指令中不支持间接寻址模式的微处理器中进行间接跳转的巧妙方法。
序列:
push address
jmp someplace
Run Code Online (Sandbox Code Playgroud)
将简单地跳转到某个地方而不影响堆栈或使用压入堆栈的地址。如果地址是 之后的指令jmp,则大致相当于call someplace。
对于不支持间接寻址跳转的指令集,我已经看到了这个不错的小解决方法:
push address
ret
Run Code Online (Sandbox Code Playgroud)
哪个会跳到任何东西address。
是的,你是对的.
当call发出a时,推送到堆栈的返回地址是下一个执行应该继续的地址(紧跟当前指令之后的地址).从本质上讲,它是一个原子,push后跟一个jmp.
这意味着,如果您手动push然后jmp,您跳转到的函数可以稍后,ret并且如果函数中的所有堆栈访问均衡,它将返回到您先前推送的地址.
类似地,您可以push然后ret模拟一个调用返回,但这并不能让您以后再次返回.这种类型的行为通常用于抛弃反汇编程序,使得使用简单的反汇编程序确定代码实际前往哪个地址变得更加困难.