ILD

AAPCS
作者:Herbert Yuan 邮箱:yuanjp89@163.com
发布时间:2018-1-1 站点:Inside Linux Development

5.1 Machine Registers

r0-r3用于参数传递,r0用于返回值。r12用于Intra-procedure-call scratch register。这几个寄存器是caller-saved register。被调用者可以随意修改它们,在返回前不需要恢复其调用前的原值。

r4-r11, r13-r15均为callee-saved register,被调用者在返回前需要恢复它们。


5.2 Process, Memory and the Stack

程序包含程序状态(由寄存器表示)和它能访问的内存。


程序的内存通常分为下述5种:


可写静态数据又可分为已初始化、初始化为0和未初始化数据。除了栈,其它数据不要求连续。一个程序至少需要有代码和栈,可以不需要其它内存。



栈是连续的内存区用于存储局部变量、传递参数到子程序(寄存器不足够存储所有的参数时)。AACPS要求栈实现为full-descending。栈顶位置存储在寄存器SP (r13).


维护栈的规则分为两部分:所有情况下都要遵守的约束;公共接口需要遵守的约束;


Universal stack constraints

必须小于等于stack-base,大于stack-limit。

栈必须对齐到4字节。

进程只能访问当前的栈,范围:[SP, stack-base-1]。如stack-base为4096,则从4095往下。SP以下的内存,栈还未生长到,不能访问。


stack constraints at a public interface

栈必须对齐到8


5.3 Subroutine Calls

ARM和Thumb指令集均包含一个原始的子程序调用指令:BL。它将PC的下一个值保存到LR,将目标地址拷贝到PC。如果在Thumb状态执行BL,则LR的第0位置为1,在ARM状态则置为0。


链接器使用IP (r12)

BL不能address全部32位地址。链接器可以在calling routine和called subroutine之间插入一个veneer。ARM-Thumb inter-working和动态链接也需要veneer。任何veneer必须保存除IP (r12)之后的所有寄存器和状态标志位。


查看AAELF获取ARM的重定向信息。


5.4 Result Return

不大于4字节的均存到r0。

A Composite Type larger than 4 bytes或者大小不能决定的参数。存到内存中,其地址作为一个额外的参数传递(r0)。函数调用期间,该内存可以修改。


5.5 Parameter Passing

参数传递通过r0-r3和栈,寄存器不够用时,才使用栈。


参数传递定义为一个2层概念模型

映射源语言参数到机器类型

编排机器类型产生参数列表


参数可能放入协处理器寄存器,这类参数叫做:Co-processor Register Candidate (CPRC)


被调用者可以修改从调用者接收参数的栈空间。


Stage A - Initialization

A.1 The Next Core Register Number (NCRN) is set to r0

NCRN指示下一个存储参数的寄存器。首先从r0开始。


A.2 Co-processor argument register initialization is performed.


A.3 The next stacked argument address (NSAA) is set to the current stack-pointer value (SP).

NSAA指示下一个放入栈的参数的地址。首先从SP开始。


A.4 If the subroutine is a function that returns a result in memory, then the address for the result is placed in r0, and the NCRN is set to r1.

如果返回值需要放入内存,则r0存储返回值的地址,NCRN设置为r1。


Stage B - Pre-padding and extension of arguments

这里只列一些汇编代码代码中常用的情况:


- 如果参数是一个大小不能静态决定的复合类型,则参数被拷贝到内存,参数被替换为一个指向内存的指针。


- 如果参数是小于4字节的整数基本类型,其被零扩展或符号扩展位4字节。


- 如果参数是复合类型,其size round到最近的4的倍数。


Stage C - Assignment of arguments to registers and stack

- 如果参数是一个CPRC,且有足够的协处理器寄存器,则参数分配到协处理器。


- 如果参数是一个CPRC,且没有可用的协处理器参数,则NSAA向上增长到满足参数的对齐要求,将参数放入内存,NSAA在增大参数的大小。


- 如果参数要求双字(8字节)对齐,则NCRN round为下一个偶数寄存器号。


- 如果参数可以放入寄存器(r0-r3),则放入寄存器。NCRN往后移。只允许一个复合参数一部分放到寄存器,一部分放到栈。


- 寄存器不够放了,放入NSAA的位置,放入后NSAA增加参数的大小。


思考:

ARM的fp (frame pointer) 是可选的,每个函数在返回时,自己负责把栈指针恢复到父函数的栈顶。没有fp使得栈回溯变的异常复杂。使用GCC的-fomit-frame-pointer选项设置为不使用fp。


arm使用r11作为fp。


参考

【1】Procedure Call Standard for the ARM ® Architecture. ARM IHI 0042D, current through ABI release 2.08. 2009


Copyright © linuxdev.cc 2017-2024. Some Rights Reserved.