为什么x86-64 System V调用约定在寄存器中而不是仅在堆栈中传递args? [英] Why does the x86-64 System V calling convention pass args in registers instead of just the stack?
问题描述
为什么32位C将所有函数自变量直接推入堆栈,而64位C将前6个参数放到寄存器中,而其余的则放到堆栈中呢?
因此32位堆栈如下所示:
...arg2arg1退货地址旧的%rbp
64位堆栈如下所示:
...arg8arg7退货地址旧的%rbparg6arg5arg4arg3arg2arg1
那么为什么64位C会这样做呢?仅将所有内容压入堆栈而不是将前6个参数放在寄存器中只是将它们移至函数序言中的堆栈中是否容易得多?
不是将前6个参数放在寄存器中只是为了将它们移到函数序言中的堆栈上?
我正在查看gcc生成的一些代码,而这正是它一直在做的事情.
然后您忘记启用优化. gcc -O0
会将所有内容泄漏到内存中,因此您可以在单步执行时使用调试器对其进行修改.这显然对性能而言是可怕的,因此除非您通过使用 -O0
进行编译来强制编译器执行,否则编译器不会这样做.
x86-64系统V允许 int add(int x,int y){return x + y;}
编译为 lea eax,[rdi + rsi]
/ ret
,这是编译器实际上所做的,正如您在以及 解决方案
instead of put the first 6 arguments in registers just to move them onto the stack in the function prologue?
I was looking at some code that gcc generated and that's what it always did.
Then you forgot to enable optimization. gcc -O0
spills everything to memory so you can modify them with a debugger while single-stepping. That's obviously horrible for performance, so compilers don't do that unless you force them to by compiling with -O0
.
x86-64 System V allows int add(int x, int y) { return x+y; }
to compile to
lea eax, [rdi + rsi]
/ ret
, which is what compilers actually do as you can see on the Godbolt compiler explorer.
Stack-args calling conventions are slow and obsolete. RISC machines have been using register-args calling conventions since before x86-64 existed, and on OSes that still care about 32-bit x86 (i.e. Windows), there are better calling conventions like __vectorcall
that pass the first 2 integer args in registers.
i386 System V hasn't been replaced because people mostly don't care as much about 32-bit performance on other OSes; we just use 64-bit code with the nicely-designed x86-64 System V calling convention.
For more about the tradeoff between register args and call-preserved vs. call-clobbered registers in calling convention design, see Why not store function parameters in float registers?, and also Why does Windows64 use a different calling convention from all other OSes on x86-64?.
这篇关于为什么x86-64 System V调用约定在寄存器中而不是仅在堆栈中传递args?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!