x86 - CALL指令是否始终将EIP指向的地址推送到堆栈?

bal*_*c55 5 x86 assembly call

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

Jon*_*art 10

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

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

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

这包括:

  • 近调用 - "调用当前代码段中的过程",其中EIP被压入堆栈.
  • 远程调用 - "调用位于与当前代码段不同的段中的过程",其中CS,EIP被压入堆栈.

替代方案,而不是推送返回地址,是一个JMP.

我熟悉的每个C编译器都将使用CALL指令在x86上实现函数调用,但有一个例外:尾调用,可以用a实现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
}
Run Code Online (Sandbox Code Playgroud)

  • 当被调用的目标位于段边界之外时,会引发异常并且不会推送返回地址。 (3认同)