【问题标题】:Does the prologue of a function can write outside of its frame?函数的序言可以写在它的框架之外吗?
【发布时间】:2021-04-03 22:58:52
【问题描述】:

我目前正在尝试分析 N64 旧视频游戏的组装。为此,我使用了一些 N64 调试器来阅读和理解底层 MIPS 代码。

在我正在查看的其中一个电话中,序言定义如下:

ADDIR SP, SP, -0x030
SW    RA, 0x0024 (SP)
SW    S0, 0x0020 (SP)
SW    A1, 0x0034 (SP)

在这个函数后面,我们还有两个堆栈推送:

SW    V0, 0x002C (SP)
[...]
SW    R0, 0x0010 (SP)

我不明白的是:

  • 为什么序言子 0x030,但没有使用所有空间:我们只存储 5 个寄存器,所以它应该最多子 0x014
  • 为什么,这是我的主要问题,A1 是在 SP 之外存储的?堆栈子 0x030,但 A1 保存到 SP[0x034]

我根本不是 ASM 方面的专家,所以我可能会错过一些关于堆栈如何工作的内容,但对我来说,序言中保存的每个数据都应该保存在 beetwen SP 和 SP - 0x030(在我的情况下)。 如果我理解正确的话,第四行写在另一个函数的堆栈帧上,这似乎很糟糕。

【问题讨论】:

    标签: assembly mips calling-convention stack-frame stack-pointer


    【解决方案1】:

    一个 MIPS 调用约定让调用者为所有参数分配堆栈内存空间,尽管前 4 个参数(至少)实际上是在寄存器中传递的。

    这意味着被调用的函数可以将$a0$a1$a2$a3 存储到堆栈中,期望这些内存位置可用。

    当一个函数调用另一个函数时,作为调用者,它也应该分配相同的 4 个字的堆栈空间。无论如何,调用另一个函数的函数至少需要一个最小的堆栈帧,因此让它分配这 4 个额外的单词在序言和尾声方面是免费的。

    部分较旧的调用约定倾向于包括对 varargs(可变参数函数)的支持,这些可能甚至无法在 C 代码中正确声明。允许函数将其参数存储回调用者分配的内存允许所有参数刷新到内存并且是连续的,这对于可变参数函数很重要。对所有功能都这样做是大材小用,但可以简化一些问题。

    请参阅https://courses.cs.washington.edu/courses/cse410/09sp/examples/MIPSCallingConventionsSummary.pdf 以获取包含寄存器参数的 4 个字的堆栈帧的图片。

    在实践中,我认为在调用者的堆栈空间中为被调用者保留 4 个单词被高度高估了,并且有证据表明这已在 RISC V 中被删除。


    一些英特尔系统使用红色区域代替,这表示系统同意在堆栈指针下方的某个小距离内(即堆栈的未分配空间)不使用您的堆栈空间。这在 intel 上是有意义的,因为返回地址会自动写入内存,因此不需要像 MIPS 上那样单独推送,但是这些系统也受益于一些预先分配的堆栈空间,以便使用简单的函数,而不必设置堆栈框架(即红色区域)。

    【讨论】:

    • “家庭空间”又名“影子空间”的好处是可以更高效地实现可变参数函数(如 printf)。就是这样(相对于红色区域)。而且它吸收更多/更宽的寄存器参数(更多可能浪费的堆栈空间),所以我猜这可能是 RISC-V 的调用约定不使用它的原因。
    • 至于红色区域,通常红色区域仅在叶函数中有用,MIPS 根本不需要溢出返回地址(除非它用完寄存器并且只想释放更多的临时注册)。另请注意,在“英特尔”系统上使用红色区域仅限于 x86-64 System V(即非 Windows,并且仅限 64 位模式)。显然还有 IA-64 Itanium,它也恰好是英特尔!不过,这并不是英特尔独有的。 x86-64 SysV ABI 设计人员(实际上是 GCC 开发人员)从 PowerPC 获得了这个想法。 devblogs.microsoft.com/oldnewthing/20190111-00/?p=100685 涵盖了一些 ISA
    • 所以,如果理解正确,这就像“好的,调用者和我(被调用者),我们隐含地同意设置比需要更多的空间,以防万一”堆栈大小,就像“我(被调用者)将在调用者内存空间上写入,因为稍后调用者会更容易”。对吗?
    • 是的,这就是它的要点。
    猜你喜欢
    • 2018-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多