ARM到C调用约定,注册保存

从我上次编码的arm汇编程序起,我已经有一段时间了,对细节有点生疏。 如果我从arm调用C函数,我只需要担心保存r0-r3和lr,对吧? 如果C函数使用任何其他寄存器,它是否负责将这些保存在堆栈中并恢复它们? 换句话说,编译器会为C函数生成代码。 例如,如果我在汇编函数中使用r10,我不必将它的值推入堆栈或内存,并在C调用后弹出/恢复它,是吗?

这是为arm-eabi-gcc 4.3.0。

我意识到我可以阅读整个EABI,但是然后缩写RTFM就是为了什么,对吧? :-)


它取决于您正在编译的平台的ABI。 在Linux上,有两个ARM ABI; 旧的和新的。 AFAIK,新的(EABI)实际上是ARM的AAPCS。 目前完整的EABI定义位于ARM的信息中心。

从AAPCS,§5.1.1:

  • r0-r3是参数和暂存寄存器; r0-r1也是结果寄存器
  • r4-r8是被调用者保存寄存器
  • r9可能是一个被调用者保存寄存器或不是(在AAPCS的某些变体上它是一个特殊的寄存器)
  • r10-r11是被调用者保存寄存器
  • r12-r15是特殊寄存器
  • 被叫保存寄存器必须由被叫保存(与主叫保存寄存器相反,主叫保存寄存器); 因此,如果这是您正在使用的ABI,则在调用另一个函数(另一个函数负责保存它)之前,不必保存r10。

    编辑:你使用的编译器没有区别; 特别是可以为几个不同的ABI配置gcc,甚至可以在命令行上更改gcc。 查看它生成的序言/结语代码并不是很有用,因为它是针对每个函数量身定制的,并且编译器可以使用其他方式保存寄存器(例如,将其保存在函数中)。


    在NEON寄存器中添加缺失的信息:

    从AAPCS,§5.1.1核心寄存器:

  • r0-r3是参数和暂存寄存器; r0-r1也是结果寄存器
  • r4-r8是被调用者保存寄存器
  • r9可能是一个被调用者保存寄存器或不是(在AAPCS的某些变体上它是一个特殊的寄存器)
  • r10-r11是被调用者保存寄存器
  • r12-r15是特殊寄存器
  • 从AAPCS,§5.1.2.1VFP注册使用约定:

  • 必须保留s16-s31(d8-d15,q4-q7)
  • s0-s15(d0-d7,q0-q3)d16-d31(q8-q15)不需要保存
  • 原文:
    手臂到C-调用约定氖寄存器对保存


    对于64位ARM,A64 (来自ARM 64位体系结构的过程调用标准)

    对于A64指令集有三十一个64位通用(整数)寄存器可见; 这些被标记为r0-r30 。 在64位环境中,这些寄存器通常使用名称x0-x30 ; 在32位上下文中,寄存器通过使用w0-w30指定。 此外,堆栈指针寄存器SP可以与有限数量的指令一起使用。

  • SP堆栈指针
  • r30 LR链接寄存器
  • r29 FP帧指针
  • r19 ... r28被保存的寄存器
  • r18平台登记册,如有需要; 否则是临时注册。
  • r17 IP1第二个程序内呼叫临时登记簿(可由单板和PLT代码使用); 在其他时候可以用作临时登记册。
  • r16 IP0第一个程序内呼叫暂存寄存器(可被单板和PLT代码使用); 在其他时候可以用作临时登记册。
  • r9 ... r15临时寄存器
  • r8间接结果位置寄存器
  • r0 ... r7参数/结果寄存器
  • 前8个寄存器r0-r7用于将参数值传递给子例程并返回函数的结果值。 它们也可以用于保存例程中的中间值(但通常只在子例程调用之间)。

    寄存器r16(IP0)r17(IP1)可以被链接器用作例程和它调用的任何子程序之间的临时寄存器。 它们也可以在例程中用于保存子程序调用之间的中间值。

    注册r18的作用是平台特定的。 如果平台ABI需要专用的通用寄存器来承载程序间的状态(例如线程上下文),那么它应该使用该寄存器来达到该目的。 如果平台ABI没有这样的要求,那么它应该使用r18作为附加的临时注册。 平台ABI规范必须记录该寄存器的用法。

    SIMD

    ARM 64位架构还有另外32个寄存器v0-v31 ,SIMD和浮点操作可以使用这些寄存器。 寄存器的确切名称将改变,表明访问的大小。

    注意:与AArch32不同,在AArch64中,SIMD和浮点寄存器的128位和64位视图与较窄视图中的多个寄存器不重叠, 因此q1,d1和s1都指向寄存器中的相同条目银行。

    前8个寄存器v0-v7用于将参数值传递给子例程并返回函数的结果值。 它们也可以用于保存例程中的中间值(但通常只在子例程调用之间)。

    通过子程序调用,寄存器v8-v15必须由被调用者保存; 其余的寄存器( v0-v7,v16-v31 )不需要保存(或者应该由调用者保存)。 此外,只需要保存v8-v15中存储的每个值的底部64位; 调用者有责任保留更大的值。

    链接地址: http://www.djcxy.com/p/72555.html

    上一篇: ARM to C calling convention, registers to save

    下一篇: Why was the carry flag set here?