【发布时间】:2015-05-11 22:45:37
【问题描述】:
我可以像使用CALL 和RET 一样使用JMP 和RET 从标签跳回吗?
【问题讨论】:
-
尾调用可以用
jmp代替call。
我可以像使用CALL 和RET 一样使用JMP 和RET 从标签跳回吗?
【问题讨论】:
jmp代替call。
当您使用 CALL 时,指令指针的当前值保存在堆栈中……当相应的 RET 执行时,它从堆栈中获取地址并跳转到那里。如果您只是 JMP 而不将当前地址保存在堆栈中,则相应的 RET 将不出所料地找不到它期望的正确地址。它可能会找到一些数据,但是,它会尝试跳转到这些位表示的地址。在任何体面的处理器上,这都会导致某种形式的违规。
只有在模仿 CALL 指令的作用时,才能跳转到一个过程并返回一个 RET。
【讨论】:
没有。 JMP 更改指令指针。 CALL将当前IP压栈并更新指令指针。
如果您将RET 与JMP 一起使用,您将根据当时堆栈中发生的情况返回到某个未知位置。
【讨论】:
如果您想使用JMP 替换CALL,但仍使用RET 或作为RET 的替换,更好的答案:
PUSH WORD CS:Call_Return
JMP My_Method
Call_Return:
... (cont)
My_Method:
...(some code)
RET
或者
My_Method:
...(some code)
POP DX
JMP DX
这只是证明可以通过多种不同的方式来做同样的事情。 这假设 16 位寻址(实模式)在这种情况下确实有所不同。在 32 位/64 位寻址模式下,您需要相应地更改 push、pop 和 JMP 命令。
【讨论】:
也许如果你使用这样的东西:
MOV BX,IP
ADD BX,10 ;If I am not mistaken mov=3bytes,add=3bytes jmp=3 bytes,push=1 byte
PUSH BX
JMP
然后:
RET
【讨论】:
MOVIP注册。此外,如果您使用标签,请确保引用它CS relative。 x86 是基于 16 位和 32 位模式的段。