我有一条跟踪指令,想要提取函数调用并返回。
我发现除call
指令外,push
+ jmp
和push
+ ret
可以用于函数调用吗?起初我想确定是正确的吗?如果是,它们之间有什么区别?
如果push
+ ret
是一种调用,那么函数的结束或返回是什么?只看到ret
之前没有push
指令?
答案 0 :(得分:7)
是的,你是对的。
当发出call
时,推送到堆栈的返回地址是继续执行的下一个地址(紧跟当前指令之后的地址)。本质上它是一个原子push
,后跟一个jmp
。
这意味着如果您手动push
然后jmp
,您跳转到的函数可以稍后ret
,并且如果函数中的所有堆栈访问都是平衡的,它将返回到你之前推送的地址。
同样,您可以push
然后ret
来模拟回复,但这并不能让您以后再次返回。这种类型的行为通常用于抛弃反汇编程序,使得使用简单的反汇编程序确定代码实际前往哪个地址变得更加困难。
答案 1 :(得分:4)
简化术语:
致电地址
这会将更新的程序计数器(指向call
之后的指令)推入堆栈,然后跳转到指示的地址(寻址模式可能适用)。
<强>保留强>
此指令在内部弹出并从堆栈中寻址并跳转到它。这与call
非常匹配,因此它可以返回到前一个call
之后的指令。
jmp 地址
这只是跳转到给定的地址(寻址模式可能适用)。它根本不对堆栈做任何事情。
<小时/> 所以,你也可以这样做:
push address
ret
如上所述,它将弹出并跳转到被压入堆栈的地址。在跳转指令中不支持间接寻址模式的微处理器中进行间接跳转是一种聪明的方法。
序列:
push address
jmp someplace
只需跳转到 someplace ,不会影响堆栈或使用压入堆栈的地址。如果地址是jmp
之后的指令,则大致相当于call someplace
。
对于不支持间接寻址跳转的指令集,我已经看到了这个很好的小解决方法:
push address
ret
将跳转到address
的任何内容。