2015-11-13 68 views

回答

9

编号CALL根据定义,将返回地址推入堆栈之前跳转到目标地址。该返回地址是EIP(或RIP)+ sizeof(call instruction)

Volume 2 of the Intel® 64 and IA-32 Architectures Software Developer’s Manual指出CALL(通常为5个字节):

保存程序链接堆栈,分支到被调用过程的信息使用所述目标 指定操作数。

这包括:

  • 近呼叫 - ,其中EIP被压入堆栈“中的当前代码段至程序调用”。
  • 远程调用 - “位于与当前代码段不同的段中的过程的调用”,其中CS,EIP被压入堆栈。

替代方案,不推送返回地址,是JMP

我熟悉的每个C编译器都将使用CALL指令始终在x86上实现函数调用,但有一个例外:tail call,它可以用JMP实现。尤其是当一个函数返回另一个函数调用的结果时。例如。

int bar(int a, int b); 

int foo(int a, int b) 
{ 
    if (a < b) 
     return 0; 

    return bar(a, b); // Will probably be: jmp bar 
} 
+0

任何编译器是否使用汇编语言(例如JMP)中的CALL - RET指令以外的其他方式实现函数调用(以C语言)? – balajimc55

+0

@ balajimc55更新的答案。 –

+1

@ balajimc55如果函数调用标记为内联和/或优化器已打开,则生成的汇编代码可能会完全删除调用指令,并且函数的主体(被调用的函数)正好放在函数内部称它。 –