回答
这是很容易做到的。将返回地址推入堆栈,然后跳转到子例程。 最终的代码如下所示:
PUSH 5
PUSH 4
PUSH offset label1
jmp Function
label1: ; returns here
leas esp, 8[esp]
Function:
...
ret
虽然这工作,你真的不希望这样做。在大多数现代处理器上,保持片上调用堆栈返回地址缓存,这会在调用时推送返回地址,并在RET上弹出返回地址。在处理器上,这具有极短的更新/访问时间,这意味着RET指令可以使用调用栈高速缓存弹出的值来预测PC下一步应该去的位置,而不是等待从实际指向的存储器位置读取实际存储器到ESP。如果你执行“PUSH offset label1”技巧, 这个缓存没有被更新,因此RET分支预测是错误的,并且处理器流水线被烧毁,对性能产生严重的负面影响。 (我认为IBM在特殊指令方面拥有专利,这些指令本质上是“PUSHRETURNADDRESS k”和“POPRETURNADDESS”,允许在他们的某些CPU上使用这种技巧。唉,不是在x86上。
+1用于解释片上调用堆栈。 – xis
这取决于情况。如果返回之前,你的函数做的最后一件事是调用另一个函数,你可以简单地跳转到函数这就是所谓的尾部调用消除,并且是许多编译器进行优化举例:
foo:
call B
call A
ret
尾调用消除用单跳指令代替最后两行:
foo:
call B
jmp A
这是有效的,因为堆栈包含foo
的调用者的返回地址。所以当函数A
返回时,它将返回到调用foo
的函数。
你想要执行到跳转到后恢复,跳跃前推该地址到堆栈中:
foo:
call B
push offset bar
jmp A
bar:
不过,我能想到的任何理由为什么有人会想这样做。
感谢您解释这一点。 +1 – cdonts
- 1. 与JMP指令
- 2. 组装相对JMP/CALL工具/插件的绝对JMP/CALL?
- 3. 添加JMP指令
- 4. 如何使用MOVE模拟LEA指令?
- 5. ATmega8不支持JMP指令
- 6. Flex/bison中的JMP指令
- 7. 短jmp指令的语法
- 8. 如何在Flat Assembler的call指令中使用fs:bx?
- 9. 如何模拟指令$ scope变量?
- 10. Javascript-bind()在ECMAScript 5之前/如何使用apply()或call()模拟?
- 11. 使用jmp-pop-call技术的汇编解码器
- 12. JMP自指令通过gcc4.4.6-3
- 13. 计算JMP指令的地址
- 14. JMP指令 - 十六进制代码
- 15. 使用JMP指令不恒定的TSS段
- 16. 模拟mouseenter的Angular指令?
- 17. 模拟器的IAR指令
- 18. 如何使用.Call
- 19. 在模板中使用js-call的指令 - 不会调用方法
- 20. 如何在angularjs中测试指令时模拟模糊?
- 21. 如何使用call和alloca指令定位llvm字节码中的类名?
- 22. x86汇编指令:CALL *注册
- 23. GCC产生`call`下一条指令
- 24. 使用Ollydbg识别CALL指令中传递的参数
- 25. jmp指令可以跳转到代码的任何部分吗?
- 26. 如何在不使用指针的情况下模拟指针?
- 27. 如何在IDA中使用JMP?
- 28. 模拟AVX-512屏蔽指令
- 29. 如何使用SSE指令?
- 30. 如何使用指令
阅读手册描述呼叫的功能,然后创建一个指令列表,以跳转完成相同的事情,这是呼叫最后一个操作。 –
这个问题似乎是无关紧要的,因为你没有描述你到目前为止所尝试过的,以及为什么这些尝试与你的期望相符或不相符。解决这个问题需要对问题有一个最基本的理解。 –