【问题标题】:Difference between JUMP and CALLJUMP 和 CALL 的区别
【发布时间】:2010-10-06 03:07:42
【问题描述】:

JUMP 和 CALL 指令有何不同?它与 GOTO 或过程调用等更高级别的概念有何关系? (我在比较中是否正确?)

这是我的想法:

JUMP 或 GOTO 是将控件转移到另一个位置,并且控件不会自动返回到调用它的位置。

另一方面,CALL 或过程/函数调用返回到调用它的位置。由于它们本质上的这种差异,语言通常使用堆栈,并且堆栈帧被推送以“记住”每个调用过程返回的位置。这种行为也适用于递归过程。然而,在尾递归的情况下,没有必要为 each 调用“推送”一个堆栈帧。

我们将不胜感激您的回答和 cmets。

【问题讨论】:

    标签: functional-programming recursion computer-science


    【解决方案1】:

    如果您在谈论 x86 汇编中的 CALL/JMP 或类似的东西,那么您基本上是对的。主要区别在于:

    • JMP 执行跳转到某个位置,而不执行任何其他操作
    • CALL 将当前指令指针压入堆栈(更确切地说:在当前指令之后的一个),然后 JMP 到该位置。使用 RET,您可以回到原来的位置。

    通常,CALL 只是一个使用 JMP 实现的便利函数。你可以做类似的事情

              movl $afterJmp, -(%esp)
              jmp location
    afterJmp:
    

    而不是 CALL。

    【讨论】:

    • 当您说:“CALL 只是一个使用 JMP 实现的便利功能。”这是否意味着 CALL 不是原子的(一条处理器指令)?
    • 你的意思是在一个线程中可能会在movl之间中断,但是在jmp本身之前,如果一个CALL会被实现为两条指令?查看文档:intel.com/Assets/PDF/manual/253666.pdf,它说该过程确实首先移动堆栈上的地址,然后跳转,清楚地说明这是一个序列。我不明白为什么它应该是原子的,另外,这有什么关系?这就像你在 jmp 之后立即被打断一样,因为 jmp 是无条件的。
    • 如果CALL 记得你从哪里跳转,这意味着太多的CALLs 会溢出堆栈(如果你没有RETurn),而使用JMP 这是不可能的破坏堆栈,但另一方面,除非您存储了您自己跳的位置,否则您不能跳回去。那是对的吗?在这种情况下,C 的 goto 应该等于 JMP
    【解决方案2】:

    您对跳转和呼叫之间的区别完全正确。

    在带有尾递归的单个函数的示例情况下,编译器可能能够重用现有的堆栈帧。但是,使用相互递归的函数可能会变得更加复杂:

    void ping() { printf("ping\n"); pong(); }
    void pong() { printf("pong\n"); ping(); }
    

    考虑 ping() 和 pong() 是采用不同数量参数的更复杂函数的情况。 Mark Probst's paper 详细讨论了 GCC 的尾递归实现。

    【讨论】:

      【解决方案3】:

      我想你已经大致了解了。

      这取决于架构,但通常在硬件级别:

      • 跳转指令将更改program counter 以在程序的不同部分继续执行。

      • 调用指令会将当前程序位置(或当前位置+1)推送到call stack 并跳转到程序的另一部分。然后返回指令会将该位置从调用堆栈中弹出并跳回原始位置(或原始位置 + 1)。

      因此,跳转指令接近于GOTO,而调用指令接近于过程/函数调用。

      另外,由于在进行函数调用时使用了调用堆栈,通过递归将太多返回地址压入调用堆栈会导致stack overflow

      在学习汇编时,我发现处理RISC 处理器比处理 x86 处理器更容易,因为它往往指令更少且操作更简单。

      【讨论】:

        【解决方案4】:

        对您的想法的一个更正:不仅使用尾递归,而且通常使用尾调用,我们不需要堆栈帧,因此只需JMP 那里(前提是参数设置正确)。

        【讨论】:

          【解决方案5】:

          根据微处理器,首先检查条件,然后执行跳转操作(转到其他代码)并且不返回。 调用操作类似于c 语言中的函数调用,当函数执行时,它会返回以完成其执行。

          【讨论】:

          • 由于CALL不做任何条件检查,唯一有效的比较跳转指令是JMP,它无条件地跳转
          猜你喜欢
          • 2015-09-04
          • 1970-01-01
          • 2013-07-10
          • 2012-11-07
          • 2011-05-22
          • 1970-01-01
          • 2019-02-04
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多