在ARM架构下,函数调用的参数传递遵循特定的调用约定,这些调用约定定义了如何在函数调用中传递参数、返回值以及保存寄存器的规则。ARM架构可采用不同的调用约定,但最常用的是ARM的标准调用约定,也称作AAPCS(ARM Architecture Procedure Call Standard)。
AAPCS(ARM Architecture Procedure Call Standard)
根据AAPCS,函数参数传递的规则如下:
-
寄存器传递:前四个整数或指针参数通过通用寄存器 R0 到 R3 传递;如果参数是浮点数或双精度数,则使用浮点/向量寄存器 S0 到 S15/D0到D7。如果函数有超过四个参数,那么会使用堆栈来传递剩余的参数。
-
堆栈传递:超过四个的参数会被压入栈中,并且栈的传递通常从右向左进行,即最后一个参数先压栈。函数调用完成后,由调用者负责清理这些参数。
-
结构体传递:小的结构体通常被视为整数或浮点数并放入寄存器中;如果结构体太大,不能放入寄存器,或寄存器已经用尽,则会将结构体传递到堆栈上。
-
返回值:返回值(如果是整数或指针)通过 R0 寄存器传递,如果是浮点数,则通过 S0/D0 寄存器传递。对于更复杂的返回值(如大型结构体),通常通过隐藏的指针传递,这个指针指向调用者分配的空间,在函数内填充返回值。
-
保存寄存器:R0-R3 和 S0-S15/D0-D7 寄存器在函数调用时不必保存(即调用者保存),它们可以被任何函数自由使用和覆写。R4-R11 是可保存的寄存器,如果在函数中使用,需要在进入函数时保存旧值,并在返回前恢复。R12 通常被作为 intra-procedure-call scratch register。
-
栈对齐:在AAPCS中,栈必须保持8字节对齐。
不同的编译器和操作系统可能有特定的调用约定,因此在混合不同编译器或语言开发的项目中,需要注意调用约定的差异。例如,在Linux上使用GCC编译器时,通常遵循AAPCS。在实际开发中,更多细节需要参考具体的编译器和架构的文档。
标签:调用,函数,传递,参数,AAPCS,寄存器,ARM From: https://www.cnblogs.com/peifx/p/18459997