我知道C编译器会向函数参数分配一些寄存器,以增强对函数内部参数的访问,从而使代码更快。但是我不确定这些寄存器的数量(我已经读过/听到过的不同数量)。
有4个或5个寄存器用于此目的吗?
还是可能依赖于编译器/硬件?
是否有相关参考?
答案 0 :(得分:7)
这个问题非常笼统,因为并非所有功能都相同(例如:一个编译为在x86上的Windows上运行的函数与一个编译为在ARM上的Linux上运行的函数)
简而言之,取决于:
编译器可以支持多个ABI,或者具有自己的专有调用约定或特定的优化方法。
答案 1 :(得分:0)
这取决于ABI,它是硬件,实现和部分依赖OS的组件。 https://en.wikipedia.org/wiki/Calling_convention
例如:
ARM(A32)
标准的32位ARM调用约定分配了15 通用寄存器为:
r14是链接寄存器。 (在子例程调用中使用的BL指令将返回地址存储在此寄存器中)。 r13是堆栈指针。 (在“ Thumb”操作模式下的Push / Pop指令仅使用该寄存器)。 r12是过程内调用暂存寄存器。 r4至r11:用于保存局部变量。 r0到r3:用于保存传递给子例程的参数值,还保留从子例程返回的结果。
第16个寄存器r15是程序计数器。
如果返回的值的类型太大而无法适合r0到r3,或者 其大小无法在编译时静态确定,则 调用者必须在运行时为此值分配空间,并传递 指向r0中该空间的指针。
子例程必须保留r4到r11的内容以及堆栈 指针。 (也许通过将它们保存到函数中的堆栈中 序幕,然后将它们用作暂存空间,然后从 函数结尾中的堆栈)。特别是, 调用其他子例程必须将返回地址保存在链接中 在调用其他子例程之前,将r14注册到堆栈。 但是,此类子例程无需将该值返回给r14,它们 只需要将该值加载到程序计数器r15中即可 返回。
ARM调用约定要求使用全降序堆栈。[14]
此调用约定使“典型” ARM子例程进入
在序言中,将r4到r11压入堆栈,然后将r14中的返回地址压入堆栈。 (这可以通过一个STM完成 指令)。 将所有传递的参数(在r0至r3中)复制到本地暂存寄存器(r4至r11)。 将其他局部变量分配给其余的局部暂存寄存器(r4至r11)。 假设不保存r0至r3,r12和r14,则使用BL进行计算并根据需要调用其他子例程。 将结果放入r0 在结语中,将r4从堆栈拉到r11,并将返回地址拉到程序计数器r15。 (这可以通过 单个LDM指令)。