浅析ARMv8体系结构:Aarch64过程调用标准

前言

Aarch64过程调用标准(AAPCS64)描述了在ARM 64位体系结构下应用程序二进制接口(ABI)在过程调用中应遵循的调用约束,涉及寄存器使用规则、堆栈布局、函数参数传递以及返回值保存等内容。

函数调用过程

Aarch64架构定义了多种跳转指令,其中函数调用主要使用BL指令,BL指令为分支与链接指令,链接的意思是包含了调用者的地址,以便子函数返回到正确的地址继续执行。与BL指令对应的返回指令是RET。

当调用过程执行BL指令时,处理器执行以下操作:

  1. 把当前程序执行的地址(PC寄存器值)加上4,保存到LR(X30寄存器)中;
  2. 加载被调用过程的指令地址到PC寄存器;
  3. 执行被调用过程。

被调用过程处理完成,调用RET指令返回,处理器执行以下操作:

  1. 把LR寄存器保存的返回地址加载到PC寄存器;
  2. 恢复调用过程执行。

这里可以和x86处理器的函数调用过程做个简单对比,x86处理器在执行函数调用时,会将返回地址等信息直接存放到堆栈中,然后从堆栈弹出返回地址到PC寄存器,完成函数调用返回;ARM则使用了独立的LR寄存器存储返回地址。

基本程序执行寄存器

ARM 64位处理器中包含了31个64位通用寄存器,依次为r0-r30:在64位上下文中,使用x0-x30的命名引用寄存器;在32位上下文中,则使用w0-w30的命名来使用寄存器。此外,处理器还提供了栈指针寄存器(SP)。对于所有基本程序执行寄存器在过程调用中的作用描述如下表所示:

寄存器名功能描述
SP栈指针寄存器,指向当前堆栈的栈顶
r30链接寄存器,用于保存过程调用的返回地址,可使用LR别名引用
r29帧指针寄存器,存放当前过程调用栈帧的起始地址,可使用FP别名引用
r19…r29遵循被调用者保存原则
r18平台预留寄存器。必要时可作为临时寄存器使用
r17IP1,内部过程调用寄存器,常用于动态链接中的plt寻址等指令
r16IP2,内部过程调用寄存器,常用于动态链接中的plt寻址等指令
r9…r15临时寄存器,理论上遵循调用者保存原则
r8间接结果寄存器,一般用来传递间接结果的地址
r0…r7用于参数传递以及保存函数调用的返回值

运行时堆栈

对于大多数现代处理器架构,基本都是用堆栈来实现过程调用。堆栈是内存的连续区域,可用于存储过程调用中的寄存器状态、局部变量,并在没有足够的参数寄存器可用时传递多余的其它参数。如下是典型ARM程序运行时的堆栈布局:
在这里插入图片描述

参数传递

Aarch64同时支持使用寄存器或堆栈进行参数传递。Aarch64标准提供了8个通用寄存器(r0-r7)用于传递函数参数,依次对应于参数1、参数2、参数3…。一般来说,对于只带有少量参数的函数,仅使用寄存器就足够了;超过8个的参数会存放在堆栈中用于传递给子例程。

返回值

用于参数传递的寄存器同时也可用来保存函数的返回值,对于C语言这种函数返回类型基本都是整型数的,r0寄存器足够使用。

过程调用示例

考虑一个简单的函数调用示例:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int do_foo_func(int arg1, int arg2)
{
    int result = 0;
    int val1 = arg1, val2 = arg2;

    result = val1 + val2;
    printf("The result is %ld.\n", result);

    return result;
}

int main(int argc, char *argv[])
{
    int result = 0;

    result = do_foo_func(4, 9);

    return result;
}

在此,我们关注do_foo_func函数的栈帧形成,查看do_foo_func的反汇编实现:
在这里插入图片描述

顺着函数do_foo_func的汇编指令代码,我们可以总结出x86_64体系下过程调用实现的一些基本步骤:

  1. 将x29、x30寄存器的值备份到栈上,同时调整sp栈指针的位置,等价于预留栈空间,预留的大小由编译器进行计算。然后,设置帧指针的值为当前栈指针
  400684:       a9bd7bfd        stp     x29, x30, [sp, #-48]!
  400688:       910003fd        mov     x29, sp
  1. 使用栈帧中保存的数据,继续后续指令的执行
  2. 恢复栈指针,完成当前过程调用栈帧的释放,并从栈中恢复x29、x30寄存器的值
 4006cc:       a8c37bfd        ldp     x29, x30, [sp], #48
  1. 过程调用返回
  4006d0:       d65f03c0        ret

相关参考

  • 《Procedure Call Standard for the ARM 64-bit Architecture (AArch64)》
  • 6
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
【1】项目代码完整且功能都验证ok,确保稳定可靠运行后才上传。欢迎下载使用!在使用过程中,如有问题或建议,请及时私信沟通,帮助解答。 【2】项目主要针对各个计算机相关专业,包括计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网等领域的在校学生、专业教师或企业员工使用。 【3】项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 【4】如果基础还行,或热爱钻研,可基于此项目进行二次开发,DIY其他不同功能,欢迎交流学习。 【注意】 项目下载解压后,项目名字和项目路径不要用中文,否则可能会出现解析不了的错误,建议解压重命名为英文名字后再运行!有问题私信沟通,祝顺利! 基于联邦学习和深度残差网络实现的网络入侵检测python源码+实验说明.zip基于联邦学习和深度残差网络实现的网络入侵检测python源码+实验说明.zip基于联邦学习和深度残差网络实现的网络入侵检测python源码+实验说明.zip基于联邦学习和深度残差网络实现的网络入侵检测python源码+实验说明.zip基于联邦学习和深度残差网络实现的网络入侵检测python源码+实验说明.zip基于联邦学习和深度残差网络实现的网络入侵检测python源码+实验说明.zip基于联邦学习和深度残差网络实现的网络入侵检测python源码+实验说明.zip基于联邦学习和深度残差网络实现的网络入侵检测python源码+实验说明.zip基于联邦学习和深度残差网络实现的网络入侵检测python源码+实验说明.zip 基于联邦学习和深度残差网络实现的网络入侵检测python源码+实验说明.zip
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值