【问题标题】:JMP vs. CALL in 8086 assembly8086 汇编中的 JMP 与 CALL
【发布时间】:2015-05-11 22:45:37
【问题描述】:

我可以像使用CALLRET 一样使用JMPRET 从标签跳回吗?

【问题讨论】:

标签: assembly x86 x86-16


【解决方案1】:

当您使用 CALL 时,指令指针的当前值保存在堆栈中……当相应的 RET 执行时,它从堆栈中获取地址并跳转到那里。如果您只是 JMP 而不将当前地址保存在堆栈中,则相应的 RET 将不出所料地找不到它期望的正确地址。它可能会找到一些数据,但是,它会尝试跳转到这些位表示的地址。在任何体面的处理器上,这都会导致某种形式的违规。

只有在模仿 CALL 指令的作用时,才能跳转到一个过程并返回一个 RET。

【讨论】:

    【解决方案2】:

    没有。 JMP 更改指令指针。 CALL将当前IP压栈并更新指令指针。

    如果您将RETJMP 一起使用,您将根据当时堆栈中发生的情况返回到某个未知位置。

    【讨论】:

    • 其实是16位模式的IP(8086)。 EIP 用于 32 位模式。
    • @nrz 真的!我没有注意到关键字中的 8086。
    【解决方案3】:

    如果您想使用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 命令。

    【讨论】:

      【解决方案4】:

      也许如果你使用这样的东西:

      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 位模式的段。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-02-17
      • 1970-01-01
      • 1970-01-01
      • 2016-11-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多