Ubuntu系统下编译的x86_64可执行文件为何仅pushq %rbp被使用?
为什么x86_64编译的C程序里很少看到除
pushq %rbp外的push指令? - 现代编译器(比如GCC、Clang)会优先用寄存器处理参数和临时变量,x86_64的System V调用约定里,前6个整数/指针参数直接通过
%rdi、%rsi、%rdx、%rcx、%r8、%r9这几个寄存器传递,根本不需要压栈。只有参数超过6个时才会用到栈,但如果你的测试程序参数不多,自然看不到push的影子。 - 编译器默认会开优化(比如O2级别),这时候会启用
-fomit-frame-pointer选项,连pushq %rbp都可能消失。你能看到pushq %rbp大概率是用O0(无优化)编译的,这时候编译器会保留传统栈帧结构,用rbp做栈帧指针,所以才会有这条指令。 - 编译器更倾向用
subq $xx, %rsp直接分配栈空间,再用movq把数据写入栈,而非push。比如要保存寄存器值到栈,先调整rsp腾出空间再mov,比单独用push更灵活——可以一次性分配多个变量的栈空间,不用多次调用push。 - 对于不调用其他函数的叶函数,编译器能把所有变量都放在寄存器里,完全不用碰栈。就算是非叶函数,也会尽量用寄存器传递数据,进一步减少push的使用场景。
内容的提问来源于stack exchange,提问作者alessio solari
相关产品推荐
相关产品推荐

