概述
JUMP和CALL指令有何不同? 它与更高级别的概念(例如GOTO或过程调用)有什么关系? (我比较正确吗?)
我是这样认为的:
JUMP或GOTO是将控件转移到另一个位置,并且控件不会自动返回到调用它的位置。
另一方面,CALL或过程/函数调用返回到其调用点。 由于其本质上的这种差异,语言通常会利用堆栈,并推动堆栈框架以"记住"要调用的每个过程返回的位置。 此行为也适用于递归过程。 但是,在尾部递归的情况下,无需为每个调用"推送"堆栈帧。
您的回答和评论将不胜感激。
如果您谈论的是x86汇编中的CALL / JMP或类似的东西,那几乎是对的。主要区别在于:
JMP无需执行任何其他操作即可跳转到某个位置
CALL将当前指令指针推入堆栈(而不是:在当前指令之后一个),然后将JMP推入该位置。使用RET,您可以回到原来的位置。
通常,CALL只是使用JMP实现的便捷功能。你可以做类似的事情
movl $afterJmp, -(%esp)
jmp location
afterJmp:
而不是致电。
当您说:" CALL只是使用JMP实现的便捷功能"。这是否意味着CALL不是原子的(一个处理器指令)?
您的意思是像在线程中可以在movl之间中断,但是在jmp本身之前,如果将CALL实现为两条指令?查看文档:intel.com/Assets/PDF/manual/253666.pdf,它说该过程确实先将地址移到堆栈上,然后进行跳转,明确地将其表示为一个序列。我不明白为什么它应该是原子的,另外,它有什么关系?就像您在jmp之后立即被打断一样,因为jmp是无条件的。
如果CALL记得您从哪里跳了起来,则意味着太多的CALL可能会使堆栈溢出(如果您没有RET urn),而使用JMP则不可能破坏堆栈,但是另一方面,除非您存储了自己跳楼的位置,否则您不能跳回来。那是对的吗?在这种情况下,Cs goto应等于JMP。
您对跳跃和通话之间的区别完全正确。
在具有尾递归的单个函数的示例情况下,编译器可能能够重用现有的堆栈框架。但是,使用相互递归函数可能会变得更加复杂:
void ping() { printf("ping
"); pong(); }
void pong() { printf("pong
"); ping(); }
考虑ping()和pong()是更复杂的函数,它们带有不同数量的参数的情况。 Mark Probst的论文详细讨论了GCC的尾递归实现。
您的想法的一种更正:不仅使用尾递归,而且通常使用尾调用,我们不需要堆栈框架,因此可以在此处简单地使用JMP(只要参数已正确设置)。
我认为您已经有了大致的想法。
它取决于体系结构,但通常在硬件级别:
跳转指令将更改程序计数器,以在程序的不同部分继续执行。
调用指令会将当前程序位置(或当前位置+1)推入调用堆栈,并跳转到程序的另一部分。然后,一条返回指令将从调用堆栈中弹出该位置,然后跳回到原始位置(或原始位置+ 1)。
因此,跳转指令接近GOTO,而调用指令接近过程/函数调用。
同样,由于在进行函数调用时使用了调用栈,因此通过递归将过多的返回地址推入调用栈将导致栈溢出。
在学习汇编时,我发现使用RISC处理器比使用x86处理器更容易,因为它往往具有较少的指令和更简单的操作。
根据微处理器,首先检查条件,然后执行跳转操作(转到其他代码)并且不返回。
调用操作就像c语言中的函数callig一样,当执行该函数时,它将返回以完成其执行。
由于CALL不执行任何条件检查,因此比较的唯一有效跳转指令是JMP,它无条件跳转。
最后
以上就是痴情大雁为你收集整理的spring和jump区别_关于函数式编程:JUMP与CALL之间的区别的全部内容,希望文章能够帮你解决spring和jump区别_关于函数式编程:JUMP与CALL之间的区别所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复