ARM64的函数调用标准和栈布局

Posted 奔跑吧Linux社区

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ARM64的函数调用标准和栈布局相关的知识,希望对你有一定的参考价值。

欢迎订阅奔跑吧linux社区微信公众号
本文节选自《奔跑吧Linux内核》第二版卷1第1.6章

函数调用标准(Procedure Call Standard,PCS)用来描述父/子函数是如何编译、链接的,特别是父函数和子函数之间调用关系的约定,如栈的布局、参数的传递等。每个处理器架构都有不同的函数调用标准,本章重点介绍ARM64的函数调用标准。

ARM公司有一份描述ARM64架构函数调用的标准和规范文档,这份文档是《Procedure Call Standard for ARM 64-Bit Architecture》。

ARM64架构的通用寄存器如表1.25所示。

ARM64的函数调用标准和栈布局_寄存器

在ARM64体系结构中,栈是从高地址往低地址生长。栈的起始地址称为栈底,而栈从高地址往低地址延伸到某个点称为栈顶。栈在函数调用过程中起到非常重要的作用,包括存储函数使用的局部变量、传递参数等。在函数调用过程中,栈是逐步生成的。为单个函数分配的栈空间,即从该函数栈底(高地址)到栈顶(低地址)这段空间称为栈帧(Stack Frame)。

例如父函数main()调用子函数func1(),那么在准备执行子函数func1()时,栈指针SP会向低地址延伸一段(从父函数的栈框最低地址往下延伸),为func1()创建一个栈帧。func1()使用到的一些局部变量会存储在这个栈帧里。当从func1()返回时,栈指针SP会调整回父函数的栈顶,此时func1()的栈空间就被释放了。

假设函数调用关系是main()→func1()→func2(),图1.31所示为栈的布局。

ARM64的函数调用标准和栈布局_寄存器_02

ARM64架构的函数栈布局的关键点如下。

  1. 所有的函数调用栈都会组成一个单链表。

  2. 每个栈由两个地址来构成这个链表,这两个地址都是64位宽的,并且它们都位于栈的底部。
    2.1 低地址存放:指向上一个栈帧(父函数的栈帧)的栈基地址FP,类似于链表的prev指针。本书把这个地址称为P_FP(Previous FP),以区别于处理器内部的FP寄存器。
    2.2 高地址存放:当前函数的返回地址,也就是进入该函数时LR的值,本书把这个地址称为P_LR(Previous LR)。

  3. 处理器的FP和SP寄存器相同。在函数执行时FP和SP寄存器会指向该函数栈空间的FP处,即栈底。

  4. 函数返回时,ARM64处理器先把栈中的P_LR的值载入当前LR寄存器,然后执行ret指令。



以上是关于ARM64的函数调用标准和栈布局的主要内容,如果未能解决你的问题,请参考以下文章

inline hook 之 ARM64 汇编基础

图解 Google V8 # 11:堆和栈:函数调用是如何影响到内存布局的?

面试题:堆和栈的区别

Xcode 12 Beta 2 - 无法为目标“arm64-apple-ios14.0-simulator”加载标准库

arm基础1

调用约定