调用函数时堆栈上有什么?

发布于 2024-10-31 03:13:16 字数 68 浏览 1 评论 0原文

我只能想象 1)参数; 2)局部变量;

还有什么?

1)函数返回地址? 2)函数名称?

I can only imagine
1) parameters;
2) local variables;

what else?

1) function return address?
2) function name?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

烟雨凡馨 2024-11-07 03:13:16

它确实取决于平台和体系结构,但通常是:

  • 函数返回地址
  • 调用者 CPU 寄存器的保存值 - 最重要的是调用者的堆栈帧指针值
  • 使用 alloca() 分配的变量。
  • 有时 - 用于异常处理的额外内容,这非常依赖于平台。
  • 用于检测堆栈破坏的保护值函数名称永远不会在堆栈中,除非您的代码将其放置在那里。

有时 -据我所知,

It really depends on platform and architecture, but typically:

  • Function return address
  • Saved values of caller's CPU registers - most importantly, caller's stack frame pointer value
  • Variables allocated with alloca().
  • Sometimes - extra stuff for exception handling, this is VERY platform-dependent.
  • Sometimes - guard values to detect stack clobbering

Function name is never in the stack, to the best of my knowledge, unless your code places it there.

心头的小情儿 2024-11-07 03:13:16

我认为一张图片确实是一千个单词。

I think that a picture really is a thousand words.

伊面 2024-11-07 03:13:16

这取决于调用约定;对于 Unix,您通常在 SYSV ABI(应用程序二进制接口)中查找此信息。

您可能会发现:

  • 返回地址(如果机器是流行的 Intel 架构)。在更现代的架构上,返回地址在寄存器中传递。

  • 被调用者保存寄存器——这些寄存器“属于”被调用者选择借用的调用者,因此必须保存和恢复。

  • 任何无法在寄存器中传递的传入参数。在 IA-32 中,没有参数在寄存器中传递;它们都入栈。在 x86-64 中,最多可以在寄存器中传递六个整数和六个浮点参数,因此很少需要为此目的使用堆栈。

  • 您可能会也可能找不到已保存的堆栈指针或帧指针。大多数现代调用约定都没有帧指针,以节省额外的寄存器。在这个设计中,每个帧的大小在编译时就已知,因此恢复旧的堆栈指针只需添加一个常量即可。但这使得实现 alloca() 变得更加困难。

    较旧的 Intel 调用约定同时使用堆栈指针和帧指针,这会消耗额外的寄存器,但它简化了 alloca() 以及堆栈展开。

  • 存储类别为 auto 的局部变量在堆栈上分配。

  • 如果硬件没有提供足够的寄存器来保存所有计算的中间结果,堆栈可能包含保存“溢出”值的编译器临时值。 (如果在任何时候,实时中间结果的数量(程序稍后需要的结果)超过编译器可用于存储中间结果的寄存器数量,就会发生这种情况。)

  • 您可能会发现用 < 分配的变量code>alloca()。

  • 您可能会找到元数据,说明哪些 PC 范围在哪些异常处理程序的范围内,或者其他非常依赖于平台的异常内容。

  • C 和 C++ 不支持垃圾收集,但在支持垃圾收集的语言中,您经常会找到元数据来标识在堆栈帧中的位置找到指针。

  • 最后,堆栈可能包含“填充”,用于确保堆栈指针在 8 字节或 16 字节边界上对齐。

调用约定是复杂的野兽,堆栈框架布局不适合胆小的人!

It depends on the calling convention; for Unix, you typically look up this information in the SYSV ABI (Application Binary Interface).

You may find:

  • Return address (if the machine is a popular Intel architecture). On more modern architectures, the return address is passed in a register.

  • Callee-saves registers—these are registers that "belong" to the caller which the callee has chosen to borrow and must therefore save and restore.

  • Any incoming parameters that could not be passed in registers. In IA-32, no parameters are passed in registers; they all go on the stack. In x86-64, up to six integer and six floating-point parameters can be passed in registers, so it is seldom necessary to use the stack for that purpose.

  • You may or may not find a saved stack pointer or frame pointer. Most modern calling conventions go without a frame pointer in order to save an extra registers. In this design, the size of each frame is known at compile time, so restoring the old stack pointer is just a matter of adding a constant. But it makes it harder to implement alloca().

    The older Intel calling conventions use both stack pointer and frame pointer, which burns an extra register, but it simplifies alloca() and also stack unwinding.

  • Local variables with storage class auto are allocated on the stack.

  • The stack may contain compiler temporaries that hold values which are "spilled" if the hardware does not provide enough registers to hold all the intermediate results of computations. (This happens if at any point the number of live intermediate results—the ones that will be needed later in the program—exceeds the number of registers available to the compiler for storing intermediate results.)

  • You may find variables allocated with alloca().

  • You may find metadata that says which PC ranges are in scope for which exception handlers, or other very platform-dependent exception stuff.

  • C and C++ do not support garbage collection, but in a language that does, you will often find metadata that identifies where in the stack frame you will find pointers.

  • Finally, the stack may contain "padding" used to ensure that the stack pointer is aligned on an 8-byte or 16-byte boundary.

Calling conventions are complex beasts, and stack-frame layout is not for the faint of heart!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文