程序集 x86-在 return 地址被推入堆栈后,堆栈指针如何保持局部变量的正确位置?

Assembly x86- How does stack pointer keep tack of correct location of local variables after return address is pushed into the stack?

我目前正在阅读 CSAPP 并且看到了这个数字,但有些事情我无法弄清楚

第1行栈指针减16,分别在栈指针相对栈0和8字节存入两个8字节数,而第7行,return地址swap_add 被压入堆栈,所以堆栈现在应该是这样的:

而我的问题是:为什么在第 8 行和第 9 行中,堆栈指针仍然能够从偏移量 0 和 8 中检索到正确的值?据我了解,堆栈指针现在指向 return 地址,因此为了取回值,它应该是 (%rsp)、%rsi16(%rsp), %rdx, 或者 return 地址不被压入堆栈?请解释一下为什么会这样,谢谢

Why in line 8 and 9, the stack pointer is still able to retrieve the correct value from offset 0 and 8?

因为堆栈指针仅在此处修改过:

subq , %rsp

这里:

addq , %rsp

虽然您对 swap_add 进行了函数调用,并且从技术上讲是在内部调整堆栈帧,但堆栈帧会在该函数调用完成后恢复。所以你应该只考虑一个堆栈框架,除非你想深入研究 swap_add 例程(其中的程序集已被省略,因此它超出了范围)。

From what I understand, the stack pointer now points to the return address

这是不正确的。在列出的程序集的开头和结尾,return 地址位于 0(%rsp)。当到达 ret 指令时,技术上会执行 pop %rip,将新指令指针设置为 return 地址。

一些额外的注意事项:

  1. call指令自动将下一条指令的地址(新函数的return地址)压入堆栈。 ret 指令有效地撤销了这个。
  2. 使用的调用约定决定了函数调用前后堆栈帧的调整方式,以及执行调整的责任人。

似乎其他答案和评论没有抓住问题的重点,并提供了许多模糊简单答案的细节:调用将 return 地址压入堆栈,但是当调用 returns,return 弹出 return 地址,所以在调用 returns 之后,堆栈指针的值与调用之前相同。