You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何编译器选用调用保留寄存器而非栈保存函数调用值?

为什么编译器选择用调用保留寄存器而非栈保存返回值?

C 源代码

void callee(void);
long call_and_ret_saved(long ToSave){
    callee();
    return ToSave;
}

为了保存参数ToSave的值(以便调用callee后返回该值),GCC 和 Clang 生成了如下汇编代码:

编译器生成的汇编

call_and_ret_saved:
    pushq   %rbx
    movq    %rdi, %rbx
    call    callee
    movq    %rbx, %rax
    popq    %rbx
    ret

问题:为何不直接用 push %rdi; call callee; pop %rax; ret; 的实现方式?是因为调用保留寄存器能让返回值更早可用吗?


回答:

核心原因是性能,而非返回值可用时机:

  • 寄存器间的读写操作(movq %rdi, %rbx、movq %rbx, %rax)比内存读写(push %rdi、pop %rax)快得多。寄存器操作的延迟和吞吐量都远优于内存访问,能避免不必要的栈内存读写开销。
  • 从调用约定角度看,%rbx 是 x86-64 架构下的被调用者保留寄存器:callee 函数如果需要使用 %rbx,必须自行保存并恢复其值,因此存在 %rbx 里的参数值不会被破坏,完全符合调用规范。
  • 若采用栈保存的方式,虽然逻辑上可行,但 push/pop 涉及两次内存操作,且栈访问的延迟通常高于寄存器操作,会降低代码执行效率。

另外,返回值可用时机并非关键因素——两种方式都要等到 callee 返回后才能得到返回值,不存在谁更早可用的情况。


内容的提问来源于stack exchange,提问作者Petr Skocik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 09:45:29