2

我想知道哪个负责清理堆栈

假设你有一个 fun 函数,可以这样说:

var = fun(int x, int y, float z, char x);

什么时候fun被调用,它将与参数一起进入堆栈,然后当函数返回时,负责清理堆栈的人是它自己的函数还是将保存返回值的“var”。

还有一件事,任何人都可以解释调用约定的概念吗?

4

3 回答 3

9

您自己提到了答案:调用约定

调用约定类似于合约。它决定以下事项:

  • 谁负责清理参数。
  • 参数如何以及以何种顺序传递给被调用函数。
  • 返回值的存储位置。

根据平台和编程环境,有许多不同的调用约定。x86 平台上的两个常见调用约定是:

标准调用

参数从右到左传递到堆栈上。被调用的函数清理堆栈。

cdecl

参数从右到左传递到堆栈上。调用函数清理堆栈。

在这两种情况下,返回值都在EAX寄存器中(或ST0浮点值)

x86 平台的许多编程语言都允许指定调用约定,例如:

德尔福

function MyFunc(x: Integer): Integer; stdcall;

微软 C/C++

int __stdcall myFunc(int x)

一些使用说明:

创建一个简单的应用程序时,很少需要更改或了解调用约定,但有两种典型情况需要您关注调用约定:

  • 调用外部库时,例如 Win32 API:您必须使用兼容的调用约定,否则堆栈可能会损坏。
  • 创建内联汇编代码时:您必须知道在哪些寄存器中以及在堆栈的哪个位置可以找到变量。

有关更多详细信息,我推荐这些 Wikipedia 文章:

于 2009-09-22T07:08:22.913 回答
5

调用约定是指谁在清理堆栈;调用者或被调用者。

调用约定可能在以下方面有所不同:

  • 参数和返回值的放置位置(在寄存器中;在调用堆栈上;两者的混合)
  • 传递参数的顺序(或单个参数的一部分)
  • 设置和清理函数调用的任务如何在调用者和被调用者之间分配。
  • 被调用者可以直接使用的寄存器有时也可能包括在内

架构几乎总是有不止一种可能的调用约定。

于 2009-09-22T07:04:18.913 回答
0

到该行完成时,var 将保存 fun() 返回的值,并且 fun 使用的堆栈上的任何内存都将消失:“push”、“pop”都整齐。

调用约定:编译器组织的所有东西,以便 fun 可以完成它的工作。考虑这些参数 x、y、z。它们被压入堆栈的顺序是什么(实际上它们是通过堆栈传递的)?只要调用者和被调用者同意就没有关系!这是一个约定。

于 2009-09-22T07:07:44.613 回答