ARM V8A体系结构-第九章 ARM64平台的ABI(Application Binary Interface )

概述

ARM体系结构的应用程序二进制接口(ABI)指定了所有可执行本机代码模块必须遵守的基本规则,以便它们能够正确地协同工作。这些基本规则由特定编程语言(例如C++)的附加规则补充。单个操作系统或执行环境(例如Linux)可能会指定附加规则以满足其自身的特定需求,而不是ARM ABI指定的规则。
AArch64体系结构的ABI有许多组件:

  • 可执行和可链接格式(ELF):ARM 64位体系结构(AArch64)的ELF指定对象和可执行格式。
  • 程序调用标准(PCS):ARM 64位体系结构(AArch64)ABI发行版的过程调用标准规定了如何单独编写、编译和组装子例程,以便协同工作。它指定调用例程和被调用方之间的约定,或例程与其执行环境之间的约定,例如,调用例程或堆栈布局时的规定。
  • DWARF:这是一种广泛使用的标准化调试数据格式。AArch64 DWARF基于DWARF 3.0,但有一些附加规则。有关详细信息,请参阅ARM 64位体系结构(AArch64)的DWARF。
  • c、c++库:ARM编译器ARM C和C++库和浮点支持用户指南描述了ARM C和C++库。
  • c++ ABI:ARM 64位体系结构的C++应用二进制接口标准描述了通用C++ ABI。

1、在AArch64过程调用标准中使用寄存器

了解参数的传递过程可以给你提供一下帮助:

  • 编写更高效的C代码
  • 理解反汇编代码
  • 编写汇编代码
  • 调用用不同语言编写的函数

1.1 通用寄存器中的参数

出于函数调用的目的,通用寄存器分为四组:

  • 参数寄存器(X0-X7):它们用于将参数传递给函数并返回结果。它们可以用作暂存寄存器,也可以用作调用方保存的寄存器变量,这些变量可以在函数内、调用其他函数之间保存中间值。与AArch32相比,8个寄存器可用于传递参数这一事实减少了用堆栈来存储参数时压栈出栈的消耗。
  • 调用方保存的临时寄存器(X9-X15):如果调用方要求在调用另一个函数时保留这些寄存器中的值,则调用方必须将受影响的寄存器保存在自己的堆栈帧中。被调用的子例程可以修改它们,而无需在返回调用方之前保存和恢复它们。
  • 被调用方保存的寄存器(X19-X29):这些寄存器保存在被调用方栈帧中。只要在返回之前保存并还原它们,被调用的子例程就可以修改它们。
  • 具有特殊用途的寄存器(X8、X16-X18、X29、X30):
    X8是间接结果寄存器。用于传递间接结果的地址,例如,函数返回一个较大结构体
    X16和X17是IP0和IP1,即过程内调用临时寄存器。这些被veneers或类似的代码调用,或者作为子例程调用之间中间值的临时寄存器。它们可以被函数修改。veneers是链接器自动插入的小块代码,例如当分支目标超出分支指令的范围时。
    X18是平台寄存器,保留供平台ABI使用。这是平台上的一个附加临时注册,没有赋予它特殊意义。
    X29是帧指针寄存器(FP)
    X30是链路寄存器(LR)

在这里插入图片描述

1.2 间接结果位置 X8

X8(XR)寄存器用于传递间接结果位置。如下代码:
在这里插入图片描述
注:此代码在编译时未进行优化以演示所涉及的机制和原理。通过优化编译器可能会删除这些。
在这里插入图片描述
在本例中,结构包含超过16个字节。根据AArch64的AAPCS,返回的对象将写入XR指向的内存。
生成的代码显示:

  • W0、W1、D0和D1用于传递整数和双参数
  • bar()在堆栈上为foo()的返回结构体留出空间,并将sp放入X8
  • bar()将X8与W0、W1、D0和D1中的参数一起传递到foo()中,然后foo()获取进一步操作的地址
  • foo()可能损坏X8,因此bar()使用SP访问返回结构
    使用X8(XR)的优点是它不会降低用于传递函数参数的寄存器的可用性。

AAPC64堆栈框架如图9-2所示。帧指针(X29)应该指向保存在堆栈上的上一个帧指针,保存的LR(X30)存储在它之后。链中的最后一个帧指针应设置为0。堆栈指针必须始终在16字节边界上对齐。堆栈帧的精确布局可能会有一些变化,特别是在可变或无帧函数的情况下。有关详细信息,请参阅AAPCS64文档。
在这里插入图片描述
图9-2显示了一个使用两个被调用方保存的寄存器(X19和X20)和一个临时变量的帧,布局如下(左侧的数字是以字节为单位的FP偏移量):
在这里插入图片描述
在这里插入图片描述

1.3 NEON和浮点寄存器中的参数

ARM 64位体系结构还具有32个寄存器v0-v31,可用于NEON和浮点操作。引用寄存器的名称不同指示访问的大小。
AArch32不同,在AArch64中,NEON和浮点寄存器的128位和64位视图在更窄的视图中不重叠多个寄存器,因此q1、d1和s1都引用寄存器组中的同一条目。
在这里插入图片描述

  • V0-V7用于将参数值传递到子例程,并从函数返回结果值。它们也可用于保存例程内的中间值(但通常仅在子例程调用之间)
  • 被调用方必须在子例程调用中保留V8-V15。只需保留V8-V15中存储的每个值的底部64位
  • V16-V31不需要保留(或者应该由调用者保留)
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值