嵌入式Linux ARM汇编(五)——ARM体系结构过程调用标准

2019-07-13 08:22发布



一、AAPCS简介

    AAPCS --Procedure Call Standard for the ARM Architecture,提供了紧凑的编写例程的一种机制,定义的例程可以与其他例程交织在一起。最显著的一点是对这些例程来自哪里没有明确的限制。它们可以编译自 C、 Pascal、也可以是用汇编语言写成的。 APCS 定义了: A、对寄存器使用的限制。 B、使用栈的惯例。 C、在函数调用之间传递/返回参数。 D、可以被回溯的基于栈的结构的格式,用来提供从失败点到程序入口的函数(和给予的参数)的列表。 APCS 不单一的给定标准,而是一系列类似但在特定条件下有所区别的标准。如果要写用来与编译后的C 连接的汇编代码,则必须使用 APCS基本过程调用标准可以确保分别编译或汇编的子程序能够协同工作。

二、AAPCS的标准规范

    AAPCS不是一个强制的标准,只是一个对于ARM编程的推荐标准。以下从编程的基本数据类型、寄存器的使用规范、内存的分配、子函数的调用、函数的参数传递等方面解读。

1基本数据类型

类型 机器类型 所占字节数 字符型 无符号字节(Unsigned byte) 1 有符号字节(Signed byte) 1 整数型 无符号半(Unsigned half-word) 2 有符号半字(Signed half-word) 2 无符号字(Unsigned word) 4 有符号字(Signed word) 4 无符号双字(Unsigned double-word) 8 有符号双字(Signed double-word) 8 浮点型 单精度浮点(Single precision) 4 双精度浮点(Double precision) 8 指针型 数据指针(Data pointer) 4 代码指针(Code pointer) 4

2、寄存器的使用规范

寄存器的特定角 {MOD}   寄存器编号 可选寄存器名 特殊寄存器名 寄存器用法 R0 a1   函数调用时的参数寄存器,用来存放前4个函数参数并存放返回值。在函数内如果将这些寄存器用作其他用途,将破坏其值。 R1 a2   R2 a3   R3 a4   R4 v1   通用变量寄存器 R5 v2   R6 v3   R7 v4   R8 v5   R9   v6SBTR 平台寄存器,不同的平台对该寄存器的定义不同 R10 v7   通用变量寄存器。在使用堆栈边界检测的情况下,r10保存堆栈边界地址 R11 v8   通用变量寄存器 R12   IP 临时过渡寄存器,函数调用时会破坏其值 R13   SP 堆栈指针 R14   LR 链接寄存器 R15   PC 程序计数器 寄存器r0~r3:子程序之间通过r0~r3来传递参数,当参数个数多于4个时,使用堆栈来传递参数。此时r0~r3可记作A1~A4 寄存器r4~r11:在子程序中使用r4~r11保存局部变量。因此当进行子程序调用时要注意对这些寄存器的保存和恢复。此时r4~r11可记作V1~V8 寄存器r12:用于保存堆栈指针SP,当子程序返回时使用该寄存器出栈,记作IP 寄存器r13:堆栈指针,记作SP 寄存器r14:链接寄存器,记作LR。用于保存子程序的返回地址。 寄存器r15:程序计数器,记作PC 程序状态寄存器CPSR: wKioL1dRXIfBZJxnAAGZm_7OQDw974.png

3、进程、内存和栈

程序执行过程中,将内存划分为以下5种类型: A、代码段 B、只读数据段 C、可读写数据段 D、栈(stack) E、堆(heap) 堆栈采用满递减类型(FD, Full Descending),即堆栈通过减小存储器地址而向下增长,堆栈指针指向内含有效数据项的最低地址。

4、子程序调用标准

子函数的调用使用BL指令,根据返回结果的数据类型大小选择的寄存器如下: A、小于4字节的基本数据类型进行符号扩展成32位,结果保存在r0返回 B、4字节大小的基本数据类型(如int)直接通过r0返回 C、双字大小的数据类型(如long longdouble)通过r0r1返回,其中r0包含返回结果的低32 D、不大于4字节的复合数据类型,结果保存在r0中返回(格式按使用LDR指令按字边界对齐从内存中读取) E、大于4字节的复合数据类型,将结果的内存地址通过r0返回

5、参数传递

A、固定个数自变量的函数 前面的整形参数按顺序分配给r0~r3,其余参数按顺序分配给堆栈 B、可变个数自变量的函数 参数值使用a1~a4R0--R3)传递