【发布时间】:2021-08-03 17:02:31
【问题描述】:
我目前正在阅读 CSAPP,我偶然发现了这个数字,但有些东西我就是想不通
在第1行,堆栈指针减16,两个8字节的数字分别存储在堆栈0和8字节相对堆栈指针,但在第7行,swap_add的返回地址被压入堆栈,所以堆栈现在应该是这样的:
我的问题是:为什么在第 8 行和第 9 行,堆栈指针仍然能够从偏移量 0 和 8 中检索到正确的值?据我了解,堆栈指针现在指向返回地址,因此为了取回值,它应该是 (%rsp)、%rsi 和 16(%rsp), %rdx,还是返回地址不入栈?请解释一下为什么会这样,谢谢
【问题讨论】:
-
如果您注意到,在第 2 行,堆栈指针被调整为 16 个字节腾出空间。然后参数存储在堆栈中,相对于新的堆栈指针位置。第 8 行和第 9 行引用了新的堆栈指针位置(不是基指针,它在堆栈帧/函数调用期间是恒定的)。此外,您的图表具有误导性。返回地址将存储在
rbp而不是rsp上方的 8 个字节。一些提示:使用 Intel 语法,因为它通常更清晰,并从高地址到低地址绘制堆栈图。 -
"在第 7 行,swap_add 的返回地址被压入堆栈。"它最终归结为使用的调用约定,如果没有更多细节我们无法知道。但是,查看此代码似乎可以安全地假设堆栈帧在
swap_add函数调用之后恢复。也就是说,不用担心call指令弄乱了栈帧,因为函数返回后会恢复。 -
call swap_add确实将返回地址压入堆栈。但随后它分支到swap_add的代码,该代码未显示,但假定以执行ret指令结束,该指令立即弹出该地址。因此,在这个调用约定中,从调用者的角度来看,您可以认为call指令对堆栈没有净影响。