被调用者保存的寄存器如何工作?谁应该将原始值压入堆栈?

问题描述 投票:0回答:1

我正在 pg251 上的 CSAPP(第三版)学习被调用者和调用者保存的寄存器,我知道对于被调用者保存的寄存器:

过程 Q(被调用者)可以通过根本不更改寄存器值或通过将原始值压入堆栈,更改它,然后在返回之前从堆栈中弹出旧值来保留寄存器值.

此外,我从

this帖子中了解到:

被调用者保存的寄存器(又名非易失性寄存器,或调用保留的)用于保存应在调用之间保留的长期值。

但是,当我尝试理解 pg252 上的 CSAPP(第三版)中的示例时,我仍然感到困惑。该示例部分说明如下:

long P(long x, long y) { long u = Q(y); // The detail of Q is irrelevant here long v = Q(x); return u + v; }
通过

gcc-11

生成对应的程序集如下:

_P: LFB2: pushq %rbp LCFI2: pushq %rbx LCFI3: subq $8, %rsp LCFI4: movq %rdi, %rbp movq %rsi, %rdi call _Q movq %rax, %rbx movq %rbp, %rdi call _Q addq %rbx, %rax addq $8, %rsp LCFI5: popq %rbx LCFI6: popq %rbp LCFI7: ret
很明显,%rbp 和 %rbx 

被调用者保存的寄存器,我们可以看到 过程 P(调用者) 将 %rbp 和 %rbx 压入堆栈。

    这是否意味着调用者 P(而不是被调用者 Q)实际上保存了两个寄存器的值?
  • 如果是这样,它是否与被调用者保存的寄存器的作用相矛盾?
如果您能帮助我解决上述问题,我将不胜感激。非常感谢!

assembly x86-64 cpu-registers
1个回答
1
投票
您必须记住,

P

不仅是
调用者,而且还是被调用者

_P: LFB2: pushq %rbp LCFI2: pushq %rbx
在这里我们可以看到 

P

 保存 
rbp
rbx
 保存 
its callers 值。


这两行很有趣。

call _Q addq %rbx, %rax
我们可以看到 

P

 调用 
Q
,然后将 
rbx
 添加到其结果(存储在 
rax
 中)。这意味着 
rbx
 未被 
Q
 修改,这意味着 
Q
 必须保留其值,即保存其被调用者。

© www.soinside.com 2019 - 2024. All rights reserved.