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:
被叫保存寄存器必须由被叫保存(与主叫保存寄存器相反,主叫保存寄存器); 因此,如果这是您正在使用的ABI,则在调用另一个函数(另一个函数负责保存它)之前,不必保存r10。
编辑:你使用的编译器没有区别; 特别是可以为几个不同的ABI配置gcc,甚至可以在命令行上更改gcc。 查看它生成的序言/结语代码并不是很有用,因为它是针对每个函数量身定制的,并且编译器可以使用其他方式保存寄存器(例如,将其保存在函数中)。
在NEON寄存器中添加缺失的信息:
从AAPCS,§5.1.1核心寄存器:
从AAPCS,§5.1.2.1VFP注册使用约定:
原文:
手臂到C-调用约定氖寄存器对保存
对于64位ARM,A64 (来自ARM 64位体系结构的过程调用标准)
对于A64指令集有三十一个64位通用(整数)寄存器可见; 这些被标记为r0-r30 。 在64位环境中,这些寄存器通常使用名称x0-x30 ; 在32位上下文中,寄存器通过使用w0-w30指定。 此外,堆栈指针寄存器SP可以与有限数量的指令一起使用。
前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