5

在 x86 架构中的函数调用期间,是否存在返回地址没有被压入堆栈的情况?

4

1 回答 1

11

CALL,根据定义,在跳转到目标地址之前将返回地址压入堆栈。该返回地址是EIP(或RIP)+ sizeof(call instruction)(通常是 5 个字节。)

英特尔® 64 位和 IA-32 架构软件开发人员手册第 2 卷指出CALL

将过程链接信息保存在堆栈上并分支到使用目标操作数指定的调用过程。

这包括:

  • Near Call — “对当前代码段中的过程的调用”,其中 EIP 被压入堆栈。
  • Far Call — “对位于与当前代码段不同的段中的过程的调用”,其中 CS、EIP 被压入堆栈。

不推送返回地址的替代方法是JMP.

我熟悉的每个 C 编译器都将始终使用CALL指令在 x86 上实现函数调用,但有一个例外:尾调用,它可以用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
}
于 2015-11-13T02:54:28.683 回答