%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
我有几个问题以确保我理解:
我们第一次进入main
的框架时return address
实际上是rbp
的值吗?
如果是这样,为什么不像其他人那样叫old rbp
?如果 f 调用另一个函数,我们应该称它为 return address 还是 rbp 呢?
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 作为指向数据的指针,特别是堆栈数据(虽然它不使用它) .
- Is return address actually the value of rbp the very first time we entered main's frame?
没有。 rbp一般用作栈指针,称为帧指针,它与return地址分开。
- 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 是另一回事,如果 main
和 f
使用帧指针(并且 f
调用另一个函数)那么将至少有一个帧指针(main
s 作为f
也放在堆栈上。
- return address is the return address for main and has nothing to do with f() right?
我们不能从这个片段中说 main
调用了 f
。 f
应该可以被几乎任何调用者调用。如果 main
确实调用了 f
,那么 return 地址代表 main
调用 f
的动态链接。例如,main
在 main
的实现中从两个不同的地方调用 f
是可以的。在 main
中的每个不同的调用站点,一个不同的代码地址将作为 return 地址传递给 f
,并且 f
将使用传递的 return 地址参数动态 return 到正确的调用者和调用站点。
return 地址应该被认为是一个附加的(但对 C 隐藏的)参数,因此它由调用者传递,但 属于 给被调用者像其他(在 C 中明确看到的)参数一样。我们不能在不传递 return 地址参数的情况下调用 f
— 如果我们不传递 f
会在查找其其他参数时以及在 returning 完成时感到困惑.
建议您在调试器中尝试一个小示例和单步操作。密切关注堆栈推送(以及推送的值)和弹出,并观察控制流从调用方到被调用方的转换,然后再返回。
我对我的书有点困惑,看看这个:
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
我有几个问题以确保我理解:
我们第一次进入
main
的框架时return address
实际上是rbp
的值吗?如果是这样,为什么不像其他人那样叫
old rbp
?如果 f 调用另一个函数,我们应该称它为 return address 还是 rbp 呢?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 作为指向数据的指针,特别是堆栈数据(虽然它不使用它) .
- Is return address actually the value of rbp the very first time we entered main's frame?
没有。 rbp一般用作栈指针,称为帧指针,它与return地址分开。
- 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 是另一回事,如果 main
和 f
使用帧指针(并且 f
调用另一个函数)那么将至少有一个帧指针(main
s 作为f
也放在堆栈上。
- return address is the return address for main and has nothing to do with f() right?
我们不能从这个片段中说 main
调用了 f
。 f
应该可以被几乎任何调用者调用。如果 main
确实调用了 f
,那么 return 地址代表 main
调用 f
的动态链接。例如,main
在 main
的实现中从两个不同的地方调用 f
是可以的。在 main
中的每个不同的调用站点,一个不同的代码地址将作为 return 地址传递给 f
,并且 f
将使用传递的 return 地址参数动态 return 到正确的调用者和调用站点。
return 地址应该被认为是一个附加的(但对 C 隐藏的)参数,因此它由调用者传递,但 属于 给被调用者像其他(在 C 中明确看到的)参数一样。我们不能在不传递 return 地址参数的情况下调用 f
— 如果我们不传递 f
会在查找其其他参数时以及在 returning 完成时感到困惑.
建议您在调试器中尝试一个小示例和单步操作。密切关注堆栈推送(以及推送的值)和弹出,并观察控制流从调用方到被调用方的转换,然后再返回。