AAPCS:最新的ARM子程序调用规则

        AAPCS是arm公司发布的ARM架构应用程序二进制(ABI)程序调用接口,该文档由多个版本,博主第一次ARM程序调用规则是在《ARM体系与结构编程》,但书中描述的是ATPCS,AAPCS是ATPCS的升级版。后面去ARM官网看到了AAPCS的文档,遂记录下来。ARM的ABI标准有多个文档,该文档只是其中的一部分。下面的链接里面包含了相关文档,又想去的可以拿来都看看。最新版的链接:GitHub - ARM-software/abi-aa: Application Binary Interface for the Arm® Architecture

1、适用范围

        AAPCS定义了子程序如何编写、如何编译和单独组装以协同工作,它描述了调用例程和被调用例程之间的关系:

  • 调用函数需要创建一个程序状态,在该状态下,被调用例程可以开始执行。

  • 被调用函数有义务在被调用期间保留调用函数的程序状态。

  • 被调用函数有权更改调用函数的程序状态。

        该标准是一系列过程调用标准(PCS)变体的基础,这些变体是通过反映以下替代优先级的选择而生成的:

  • 代码

  • 性能

  • 功能性( 例如,调试的便捷性,运行时检查,对共享库的支持 )

每个变体的某些方面(如R9的使用情况)有执行环境决定,因此:

  • 遵循基本标准的代码可以与每个变体都兼容PCS,这是可能的。

  • 符合某个变体的代码与符合任何其他变体的代码兼容,这是不寻常的。

  • 符合某个变体或基本标准的代码不能保证与要求这些标准的执行环境兼容。执行环境可能对过程调用标准范围之外提出进一步的要求。

该标准分为四个部分:

  • 数据的布局。

  • 具有公共接口的函数之间的堆栈布局和调用方式。

  • 处理器扩展可用的变体,或者在执行环境限制寻址模型时。

  • 用于普通数据类型的C和C++语言绑定。

        本规范不标准化非C语言实体的公共可见性的表示(这些在CPPABI32中描述),并且对不在公共接口上可见的语言实体的表示不提出任何要求。

2、数据类型和对齐方式

2.1 基本数据类型

下表显示了机器的基本数据类型(机器类型),NULL指针总是由全为0表示。

2.1.1 半精度浮点

ARM架构的可选扩展为半精度值提供硬件支持,目前支持三种格式:

  • IEEE754-2008标准的半精度格式

  • ARM的替代格式,提供额外的范围,但没有无穷大(NaN)

  • Brain浮点格式,提供了类似于32位浮点格式的动态范围,但精度更少。

2.1.2 容器化向量

        容器化向量的内容对大多数调用标准来说都是不透明的:其布局的唯一定义方面是内存格式(基本类型在内存中储存的方式),与调用时不同寄存器之间的映射。

2.2 字节顺序

从软件的角度看,内存就是一个数组,每个字节都有自己的地址。

ABI支持由底层硬件实现的两种内存视图:

  • 大端视图(大端模式)

  • 小端视图(小端模式)

2.3 复合类型

        复合类型是一个或多个基本数据类型的集合,在调用过程中作为单个实体进行处理。可以是以下任意一种:

  • 顺序,其成员按照顺序排列在内存中(其实就是C的结构体)

  • 联合体,每个成员都有相同的地址

  • 数组

该定义是递归的,也就是说,每个类型都可以包含复合类型(结构体套结构体)。

3 基本过程调用标准

        该部分定义了ARM和Thumb通用的机器级、仅核心寄存器调用标准指令集。应用于没有浮点硬件的系统, 或者需要与Thumb代码高度互操作的情况。

3.1 机器寄存器

        ARM架构定义了一个核心指令集,以及协处理器附加的指令。核心指令集可以访问核心寄存器,协处理器可以提供额外操作的寄存器。

3.1.1 核心寄存器

        ARM和Thumb指令集有16个32位寄存器,R0--R15,还有一个状态寄存器(CPSR),下表是各个寄存器的功能。

        前四个寄存器r0-r3(a1-a4)用于将参数值传递到子例程,并从函数返回结果值。它们也可以用于在例程内部保存中间值(但通常仅在子例程调用之间)。

        寄存器r12(IP)可以由链接器在例程和调用的任何子例程之间用作临时寄存器(有关详细信息,请参阅链接器使用IP)。它还可以在例程内部用于保存子例程调用之间的中间值。

        在某些变体中,寄存器r11(FP)可能被用作帧指针,以便将帧激活记录链接成链表。

        寄存器r9的角色取决于平台。虚拟平台可以为该寄存器分配任何角色,并必须记录此用法。例如,它可以将其指定为无位置相关数据模型中的静态基址(SB),或者在具有线程局部存储的环境中将其指定为线程寄存器(TR)。对该寄存器的使用可能需要保持其值在所有调用之间持久。没有对这种特殊寄存器的需求的虚拟平台可以将r9指定为附加的被调用保存变量寄存器v6。

        通常,寄存器r4-r8,r10和r11(v1-v5,v7和v8)用于保存例程的局部变量的值。其中,只有v1-v4可以由整个Thumb指令集统一使用,但AAPCS并不要求Thumb代码仅使用这些寄存器。

        子例程必须保留寄存器r4-r8,r10,r11和SP的内容(在PCS变体中,将r9指定为v6时也要保留r9)。

        在过程调用标准的所有变体中,寄存器r12-r15都具有特殊角色。在这些角色中,它们被标记为IP,SP,LR和PC。

CPSR是一个具有以下属性的全局寄存器:

  • 在进入或从公共接口返回时,N、Z、C、V和Q位(位27-31)以及GE[3:0]位(位16-19)是未定义的。只有在执行支持这些特性的处理器上时,才可以修改Q和GE[3:0]位。

  • 在Arm架构6上,E位(位8)可用于在执行小端模式的应用程序中,或在大端-8模式中暂时更改对内存的数据访问的字节序。应用程序必须具有指定的字节序,并且在进入和退出任何公共接口时,E位的设置必须与应用程序的指定字节序匹配。

  • T位(位5)和J位(位24)是执行状态位。只有专为修改这些位而指定的指令才能更改它们。

  • A、I、F和M[4:0]位(位0-7)是特权位,只能由专为在特权模式下明确运行的应用程序修改。

  • 所有其他位都是保留位,不得修改。未定义这些位是读作零还是一,或者它们是否在公共接口间保持不变。

3.1.1.1 处理大于32位的值

        大于32位的基本类型可以作为参数传递给函数调用,或作为函数调用的结果返回。当这些类型位于核心寄存器中时,应用以下规则:

  • 双字大小的类型以两个连续的寄存器传递(例如,r0和r1,或r2和r3)。寄存器的内容就像使用单个LDM指令从内存表示中加载该值一样。

  • 一个128位的容器化向量以四个连续的寄存器传递。寄存器的内容就像使用单个LDM指令从内存中加载该值一样。

3.2 进程、内存和堆栈

        AAPCS适用于单个执行线程或进程(以下统称为进程)。进程具有由底层机器寄存器和其可以访问的内存内容定义的程序状态。在进程执行期间,进程能够访问的内存,而不会导致运行时故障,可能会有所变化。 进程的内存通常可分为五个类别:

  • 代码(正在执行的程序),必须对进程可读,但不必对其可写。

  • 只读静态数据。

  • 可写静态数据。

  • 堆。

  • 堆栈。

        可写的静态数据可以进一步分为已初始化、零初始化和未初始化数据。除了堆栈外,没有要求每个内存类都必须占据内存的单个连续区域。进程始终必须有一些代码和一个堆栈,但不必拥有任何其他内存类别。

        堆是由进程自身管理的内存区域(例如,使用C的malloc函数)。通常用于创建动态数据对象。

        符合规范的程序必须只执行在被指定为包含代码的内存区域中的指令。

3.2.1 堆栈

        堆栈是一块连续的内存区域,可用于存储局部变量和在参数寄存器不足时向子例程传递附加参数。

        堆栈实现是完全降序的,当前堆栈的范围保存在寄存器SP(r13)中。堆栈通常会有基地址和限制地址,尽管在实践中应用可能无法确定任何一个值的具体数值。

        堆栈可能具有固定大小,也可能是动态可扩展的(通过向下调整堆栈限制)。

        关于堆栈的维护规则分为两部分:一组必须始终遵守的约束条件和一个必须在公共接口中遵守的附加约束条件。

3.2.1.1 通用堆栈约束

始终需要满足以下基本约束条件:

  • 堆栈限制 ≤ SP ≤ 堆栈基址。堆栈指针必须位于堆栈的范围内。

  • SP mod 4 = 0。堆栈始终必须对齐到字边界。

  • 进程只能将数据存储在整个堆栈的封闭区间内,由[SP,堆栈基址 - 1](其中SP是寄存器r13的值)限定。

3.2.1.2 公共接口的堆栈约束

在公共接口处,堆栈还必须符合以下约束: SP mod 8 = 0。堆栈必须是双字对齐的。

3.2.1.3 堆栈探查

        为了确保堆栈的完整性,进程可能在分配额外的堆栈空间(从SP_old移动到SP_new)之前立即发出堆栈探查。堆栈探查必须位于[SP_new, SP_old - 1]的区域内,并且可以是读或写操作。堆栈探查的最小间隔由目标平台定义,但必须至少为4K字节。在当前分配的堆栈区域下面不能保存可恢复的数据。

3.2.1.4 帧指针

        平台可能要求构建描述程序中当前调用层次结构的堆栈帧列表。 每个帧应通过在堆栈上使用两个32位值的帧记录与其调用者的帧链接。最内层帧(属于最近例程调用)的帧记录应由帧指针寄存器(FP)指向。最低地址的字应指向上一个帧记录,最高地址的字应包含在进入当前函数时传递给LR的值。帧记录链的结束由前一帧的地址为零来表示。在堆栈帧中的帧记录位置未指定。帧指针寄存器在新的帧记录完全构建之前不能更新。

3.3 子例程调用

        Arm和Thumb指令集都包含一个基本的子例程调用指令BL,执行分支带链接操作。执行BL的效果是将程序计数器的下一个顺序值,即返回地址,传送到链接寄存器(LR),并将目标地址传送到程序计数器(PC)。如果从Thumb状态执行BL指令,则链接寄存器的第0位将设置为1,如果从Arm状态执行,则设置为0。结果是将控制权转移到目标地址,将LR中的返回地址作为附加参数传递给被调用的子例程。

        当返回地址被加载回PC时(请参见交互操作),控制将返回到BL后面的指令。

3.4 返回结果

函数返回结果的方式取决于该结果的类型。对于基本标准:

  1. 半精度浮点类型返回在r0的最低有效16位。

  2. 小于4字节的基本数据类型被零扩展或符号扩展为一个字,并返回在r0中。

  3. 字大小的基本数据类型(例如,int、float)在r0中返回。

  4. 双字大小的基本数据类型(例如,longlong、double和64位容器化向量)在r0和r1中返回。

  5. 128位容器化向量在r0-r3中返回。

  6. 不大于4字节的复合类型在r0中返回。其格式就像将结果存储在内存中的字对齐地址,然后使用LDR指令加载到r0中一样。r0中超出结果范围的任何位都具有未指定的值。

  7. 大于4字节的复合类型,或其大小无法由调用方和被调用方静态确定的,将存储在内存中,其地址作为调用函数时传递的额外参数(参数传递,基本PCS,规则A.4)。结果使用的内存在函数调用期间的任何时刻都可以进行修改。

3.5 参数传递

        基本标准提供了在核心寄存器(r0-r3)和堆栈上传递参数的机制。对于需要少量参数的子例程,仅使用寄存器,大大降低了调用的开销。 参数传递被定义为一个两级概念模型:

  1. 从源语言参数映射到机器类型。

  2. 编排机器类型以生成最终的参数列表。

        从源语言到机器类型的映射对于每种语言都是特定的,并在单独的文档中描述(C和C++语言绑定在Arm C和C++语言映射中描述)。结果是一个有序的参数列表,将传递给子例程。

        在下面的描述中,假设有许多协处理器可用于传递和接收参数。协处理器寄存器分为不同的类别。一个参数最多可以是一个协处理器寄存器类的候选项。适合分配给协处理器寄存器的参数称为协处理器寄存器候选项(CPRC)。 在基本标准中,没有适合于协处理器寄存器类的参数。

        一个变参函数始终按照基本标准的方式进行编排。

        对于调用方,假定在进行编排之前已分配足够的堆栈空间以容纳堆叠的参数:实际上,只有在参数编排完成后,才能知道所需的堆栈空间量。被调用方可以修改用于接收来自调用方的参数值的任何堆栈空间。

        当将复合类型参数分配给核心寄存器时(完全或部分),其行为就好像参数已存储到内存中的字对齐(4字节)地址,然后使用适当的加载多寄存器指令加载到连续的寄存器中。

4.总结

        本篇文章属于笔记性质的,在文章中,博主只是挑选了其中的一部分记录,奈何英文不太行,理解和翻译的水平怕是不够的,有兴趣的同学可以看原版。博主上传到自己的码云仓库里面,码云链接:https://gitee.com/zichuanning520/htq_library

最新版的链接:GitHub - ARM-software/abi-aa: Application Binary Interface for the Arm® Architecture

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/114157.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

自然语言处理基础——词表示

词表示 把自然语言中最基本的语言单元——词转换为机器能够理解的 词表示能完成以下两个能力 词相似度计算 词与词之间语义的关系 近义词&上位词 使用近义词或上位词表示的问题 遗漏差异 遗漏新的释义 带有主观性 数据吸收 需要大量人工构建 One-Hot Representation …

Kafka学习(最新版3.6.0)

文章目录 一、初识MQ1.1 什么是MQ1.2 同步和异步通讯1.1.1 同步通讯1.1.2 异步通讯 1.3 技术对比1.4 MQ的两种模式 二、初识Kafka2.1 Kafka的使用场景2.2 Kafka基本概念2.3 Topic与Partition 三、Kafka基本使用3.1 部署前的准备3.2 启动kafka服务器3.3 Kafka核心概念之Topic3.4…

059:mapboxGL监听键盘事件,通过eastTo控制左右旋转

第059个 点击查看专栏目录 本示例是介绍演示如何在vue+mapbox中监听键盘事件,通过eastTo控制左右旋转。 本例通过easeTo方法来加减一定数值的bearing角度,通过.addEventListener的方法来监听键盘的按键动作。这里一定要设置interactive: false, 否则展现不出来旋转效果。 直…

机械设备经营小程序商城的作用是什么

由于机械设备厂商品牌需要各地招商代理,因此在管理方面也需要工具进行高效管理。如今各个行业都在开展数字化转型解决行业所遇难题或通过线上销售解决传统三公里难题及品牌扩张难题、用户消费渠道少等难题,构建会员体系精细化管理,同时还需要…

MySQL 主从复制原理

文章目录 1.主从复制方式1.1 异步复制1.2 半同步复制1.3 全同步复制 2.主从复制原理3.主从复制时推还是拉?参考文献 主从复制是 MySQL 高可用(备份)和高性能(读写分离)的基础,有了这个基础,MySQ…

【Ascend C算子开发(入门)】——Ascend C编程模式与范式

Ascend C编程模型与范式 1.并行计算架构抽象 Ascend C编程开发的算子是运行在AI Core上的,所以我们需要了解一下AI Core的结构。AI Core主要包括计算单元、存储单元、搬运单元。 计算单元包括了三种计算资源:Scalar计算单元(执行标量计算&…

外骨骼机器人和人形机器人概览

前言:一点思考 外骨骼机器人和人形机器人都曾随着一些爆品的出现火热过一段时间,但总感觉当前技术条件还不成熟,真正能落地的应用场景不多。马斯克在擎天柱发布会上被问到人形机器人的落地与前景问题时并没有给出明确答案,只是用…

c++ pcl点云变换骨架枝干添加树叶源码实例

程序示例精选 c pcl点云变换骨架枝干添加树叶源码实例 如需安装运行环境或远程调试,见文章底部个人QQ名片,由专业技术人员远程协助! 前言 这篇博客针对《c pcl点云变换骨架枝干添加树叶源码实例》编写代码,代码整洁,…

自然语言处理---Tr ansformer机制详解之Transformer结构

1 Encoder模块 1.1 Encoder模块的结构和作用 经典的Transformer结构中的Encoder模块包含6个Encoder Block.每个Encoder Block包含一个多头自注意力层,和一个前馈全连接层. 1.2 Encoder Block 在Transformer架构中,6个一模一样的Encoder …

【JavaScript】深入浅出理解事件循环

1. 浏览器的进程模型 1.1 进程 程序运行需要有它自己专属的内存空间,可以把这块内存空间简单的理解为进程。 每个应用至少有一个进程,进程之间相互独立,即使要通信,也需要双方同意。 1.2 线程 有了进程后,就可以运…

【广州华锐互动】VR营销心理学情景模拟培训系统介绍

在高度竞争的汽车市场中,销售人员需要具备强大的专业知识、引人入胜的销售技巧,以及敏锐的市场洞察力。然而,传统的培训方式往往无法满足这些需求,因为它们往往忽略了实践的重要性。 为了解决这个问题,许多公司开始采用…

TCP/IP(十九)TCP 实战抓包分析(三)TCP 第一次握手 SYN 丢包

一 TCP 三次握手异常情况实战分析 说明: 本文是TCP 三次握手异常系列之一 ① 异常场景 接下里我用三个实验案例,带大家一起探究探究这三种异常关注: 如何刻意练习模拟上述场景 以及 wireshark现象 ② 实验环境 ③ 实验一:TCP 第一次握…

Python —— UI自动化之使用JavaScript进行元素点亮、修改、点击元素

1、JavaScript点亮元素 在控制台通过JavaScript语言中对元素点亮效果如下: 将这个语句和UI自动化结合,代码如下: locator (By.ID,"kw") # 是元组类型 web_element WebDriverWait(driver,5,0.5).until(EC.visibility_of_eleme…

Arduino驱动BMA220三轴加速度传感器(惯性测量传感器篇)

目录 1、传感器特性 2、硬件原理图 3、驱动程序 BMA220的三轴加速度计是一款具有I2C接口的超小型三轴低g加速度传感器断路器,面向低功耗消费市场应用。它可以测量3个垂直轴的加速度,从而在手机、手持设备、计算机外围设备、人机界面、虚拟现实功能和游戏控制器中感知倾斜、…

王道计算机考研 操作系统学习笔记 + 完整思维导图篇章五: IO管理

目录 IO设备的基本概念和分类 IO设备的分类 按使用特性分类 按传输速率分类 按信息交换单位分类 IO控制器 l/O设备的电子部件(I/O控制器) l/O控制器的组成 内存映像I/o vs.寄存器独立编址 IO控制方式 程序直接控制方式 中断驱动方式 DMA方式 ​编辑通…

java1.8流的新特性使用

案例描述 今天跟着黑马程序员的视频&#xff0c;完成“瑞吉外卖”项目的菜品信息管理模块的时候&#xff0c;遇到了一个比较陌生的写法 用到了Java8的新特性 stream().map((item) -> {}).collect() List<DishDto> collect records.stream().map((item) -> {DishDt…

10.17七段数码管单个多个(部分)

单个数码管的实现 第一种方式 一端并接称为位码&#xff1b;一端分别接收电平信号以控制灯的亮灭&#xff0c;称为段码 8421BCD码转七段数码管段码是将BCD码表示的十进制数转换成七段LED数码管的7个驱动段码&#xff0c; 段码就是LED灯的信号 a为1表示没用到a&#xff0c;a为…

文件读取结束的判定

大家好啊&#xff0c;我们今天来补充文件操作的读取结束的判定。 被错误使用的feof 牢记&#xff1a;在文件读取过程中&#xff0c;不能用feof函数的返回值直接用来判断文件的是否结束而是应用于当文件读取结束的时候&#xff0c;判断是读取失败结束&#xff0c;还是遇到文件尾…

Qt第六十五章:自定义菜单栏的隐藏、弹出

目录 一、效果图 二、qtDesigner 三、ui文件如下&#xff1a; 四、代码 一、效果图 二、qtDesigner 原理是利用属性动画来控制QFrame的minimumWidth属性。 ①先拖出相应的控件 ②布局一下 ③填上一些样式 相关QSS background-color: rgb(238, 242, 255); border:2px sol…

量子力学期末复习--1

量子力学解题技巧--1 基础知识 薛定谔方程 Ehrenfest 定理 不确定性原理&#xff1a;正则对易关系&#xff1a;自由粒子&#xff1a;对于自由粒子&#xff0c;分离变量解不代表物理上可实现的态。但其含时薛定谔方程的一般解仍旧是分离变量解的线性组合 典型题目 自由粒子…