CALL 指令是否总是将 EIP 指向的地址压入堆栈?

Does CALL instruction ALWAYS push the address pointed by EIP to stack?

在 x86 架构中函数调用期间是否存在 return 地址未被压入堆栈的情况?

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

Volume 2 of the Intel® 64 and IA-32 Architectures Software Developer’s Manual 表示 CALL:

Saves procedure linking information on the stack and branches to the called procedure specified using the target operand.

这包括:

  • Near Call — "A call to a procedure in the current code segment",其中 EIP 被压入堆栈。
  • Far Call — "A call to a procedure located in a different segment than the current code segment",其中CS、EIP入栈。

不推送 return 地址的替代方法是 JMP

我熟悉的每个 C 编译器总是使用 CALL 指令在 x86 上实现函数调用,有一个例外:tail call,它可以用 JMP 实现].当一个函数 return 是另一个函数调用的结果时,尤其会发生这种情况。例如

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
}