%rbp vs Return 汇编地址?

%rbp vs Return Address in Assembly?

我对我的书有点困惑,看看这个:

f:
    pushl %ebp        # store old ebp
    movl %esp, %ebp   # move ebp to top
    movl , %eax    # make f return 73
    popl %ebp         # restore old ebp from stack
    ret               # pop return address and jump

我有几个问题以确保我理解:

  1. 我们第一次进入main的框架时return address实际上是rbp的值吗?

  2. 如果是这样,为什么不像其他人那样叫old rbp?如果 f 调用另一个函数,我们应该称它为 return address 还是 rbp 呢?

  3. return address 是 main 的 return 地址,与 f() 无关对吧?

return 地址是一个指向代码 的 指针,它被调用者 压入堆栈,通常由call 指令。由于它是由调用者推送的,因此在 f 的第一条机器代码指令运行之前,该值(以及调用者推送的任何其他值)必须在堆栈上。约定要求 return 地址是从调用者到被调用者(控制流)转换时堆栈中的最上面的东西。

因此,就在 f 开始之前,堆栈上有 return 地址。 return 地址有时在旧文本中称为链接。它是调用者传递的一个参数,被调用者使用它来知道去哪里return。将 return 地址作为参数传递给被调用者使用,允许从许多不同的地方(在调用链的许多不同深度)调用函数(这里是 f),并且总是 return 给它的调用者,不管是谁。

return 地址和 rbp 不同。我们不能在这里说调用者如何使用 rbp b/c 我们看不到调用者。但是,根据调用约定,rbp 寄存器需要在从被调用方 return 到调用方 时保留其原始值 。因此,由于此被调用者选择修改 rbp 值(尽管没有明显的原因),因此也有必要在 returning 之前恢复原始 rbp 值,它确实这样做了。

在从调用者转换到被调用者时称为旧的rbp b/c,rbp值属于调用堆栈中更高层的人,而不是属于[=的rbp值11=](而是给 f 的来电者)。

我们不能说 rbp 中的内容属于调用者,但是,f 选择使用 rbp 作为指向数据的指针,特别是堆栈数据(虽然它不使用它) .

  1. Is return address actually the value of rbp the very first time we entered main's frame?

没有。 rbp一般用作栈指针,称为帧指针,它与return地址分开。

  1. If so, why it's not called old rbp as others? what's if f calls another function should we call it return address or rbp?

如果f调用另一个函数,堆栈上至少会有2个return地址。 rbp 是另一回事,如果 mainf 使用帧指针(并且 f 调用另一个函数)那么将至少有一个帧指针(mains 作为f 也放在堆栈上。

  1. return address is the return address for main and has nothing to do with f() right?

我们不能从这个片段中说 main 调用了 ff 应该可以被几乎任何调用者调用。如果 main 确实调用了 f,那么 return 地址代表 main 调用 f 的动态链接。例如,mainmain 的实现中从两个不同的地方调用 f 是可以的。在 main 中的每个不同的调用站点,一个不同的代码地址将作为 return 地址传递给 f,并且 f 将使用传递的 return 地址参数动态 return 到正确的调用者和调用站点。

return 地址应该被认为是一个附加的(但对 C 隐藏的)参数,因此它由调用者传递,但 属于 给被调用者像其他(在 C 中明确看到的)参数一样。我们不能在不传递 return 地址参数的情况下调用 f — 如果我们不传递 f 会在查找其其他参数时以及在 returning 完成时感到困惑.


建议您在调试器中尝试一个小示例和单步操作。密切关注堆栈推送(以及推送的值)和弹出,并观察控制流从调用方到被调用方的转换,然后再返回。