ARM - AArch64 - 通用寄存器

说明

  • 在深入一点了解了系统调用以及非安全world(REE)/安全world(TEE)切换时参数传递和结果返回的实现原理(通过通用寄存器实现),对通用寄存器的使用有了一个全新的认识,对知识做个总结。

简介

  • Arm AArch64状态下提供了31个64位通用寄存器:X0 ~ X30。

通用体现

  1. 不同于特殊寄存器(每一bit可能都有特殊作用),通用寄存器本身没有任何作用(就是一个64位存储器),其作用是由使用体现。
  2. 任意时间任意环境(任意特权等级,任意安全等级,用户态/内核态)都可以使用这些通用寄存器,没有任何访问限制。
    1. 应用层调用系统调用(应用态和内核态切换),参数传递和结果返回等都是使用通用寄存器实现。
    2. 应用层程序执行,函数调用时参数传递,也是使用通用寄存器实现。
    3. REE与TEE通信,需要做非安全world和安全world切换,异常等级切换等也是使用通用寄存器传递参数和运行结果。
    4. 任何异常等级中函数执行也是使用这些通用寄存器,切换异常等级也不会丢失。
  • 重点:通用寄存器是参数传递,返回结果等一些通用行为使用的寄存器,在任何场景,环境下(用户态/内核态切换,安全world/非安全world切换)都是一样,没有其它寄存器。

32位形态

  • X0 ~ X30是64位寄存器,也可以作为32位寄存器使用,其32位形态(W0 ~ W30)取自相应64位寄存器(X0 ~ X30)的低32位,例如:W0映射到X0的低32位,W1映射到X1的低32位。
  • 读写其32位形态行为如下:
  1. 读取,从32位寄存器(W0-W30)读取时,忽略相应64位寄存器(X0-X30)高32位,并保持其它不变。
  2. 写入,将数据写入32位寄存器(W0-W30)时,会将其对应的64位寄存器(X0-X30)的高32位设置为零,例如:将0xFFFFFFFF写入W0会将X0设置为0x00000000FFFFFFFF。

用途

  • 通用寄存器的用途更多的是一种使用规范,并没有什么强制限制。
  • 不同使用场景会有些细微区别。

规范

  • 根据用途,通用寄存器可以分为四组。

x0 ~ x7

  1. 传递参数
  • 应用层函数调用,传递子函数的参数,超出的参数用堆栈传递。
  • 应用层调用系统调用,传递系统调用的参数,系统调用只支持6个参数,因此只用到了x0 ~ x5。
  • REE与TEE通信,SMC请求使用x0 ~ x7 传递参数。
  1. 传递返回值
  • 应用层调用系统调用,函数调用,64位的返回结果保存在x0中。
  • REE与TEE通信,ERET使用x0 ~ x3 传递TEE运行结果。
  1. 临时存储器
  • 在函数中也可以用作临时寄存器,可以保存中间值或调用者的寄存器变量。

X9-X15:调用者寄存器

  • 网上描述:如果调用者需要在调用另一个函数时保留一些寄存器中的任何值,则调用者必须将受影响的寄存器保存在自己的堆栈帧中。 也可以修改子例程,而不需要在返回调用函数时保存值到堆栈和从堆栈中恢复它们。
  • 后续体会较深时,再修正。

X19-X29:被调用寄存器

  • 网上描述:这些寄存器保存在被调用者内部。 只要在返回前保存并恢复,就可以在被调用的子程序中修改。
  • 后续体会较深时,再修正。

X8, X16-X18, X29, X30:特殊目的寄存器

  • X8 是间接结果寄存器。用于传递间接结果的地址位置,例如,函数返回大型结构的位置。
  • x8 在系统调用(syscall)中用于传递系统调用编号。
  • 网上描述:X16 和 X17 分别是 IP0 和 IP1,临时寄存器(intra-procedure-call )可以通过veneers或者类似代码使用,或者作为子程序调用之间的中间值的临时寄存器。它们可以被函数破坏。veneers代码是链接器自动插入的一小段代码,例如当分支(跳转)目标超出分支指令(支持的)范围时。
  • X18 是平台寄存器,保留供平台 ABI 使用。这是平台上的一个附加临时寄存器,没有为其分配特殊含义。
  • X29 是 Frame Pointer 寄存器,指向当前方法栈的底部。用于连接栈帧,使用时必须保存。
  • X30 是链接寄存器,这个寄存器会记录着当前方法的调用方地址 ,即当前方法调用完成时应该返回的位置。我们进行函数调用的时候,会用X30记录当前调用地址,等调用函数执行完毕,会从X30取出地址进行返回。我们遇到 Crash 要获取方法堆栈,其本质就是不断的向上递归每一个 x30 寄存器的记录状态(也就是栈上 X30 寄存器的内容) 来找到上层调用方。
  • 后续体会较深时,再修正。

实际使用

  • 系统调用实现

    // 标准C库(musl)syscall 实现
    #define __asm_syscall(...) do {
    asm volatile ( "svc 0"
    : "=r"(x0) : VA_ARGS : "memory", "cc");
    return x0; \ //使用 x0传递返回值
    } while (0)

    static inline long __syscall0(long n)
    {
    register long x8 asm("x8") = n; //使用 x8传递系统编译编号
    register long x0 asm("x0");
    __asm_syscall("r"(x8));
    }
    ...
    static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f)
    {
    register long x8 asm("x8") = n;
    register long x0 asm("x0") = a; //使用x0 ~ x5传递参数
    register long x1 asm("x1") = b;
    register long x2 asm("x2") = c;
    register long x3 asm("x3") = d;
    register long x4 asm("x4") = e;
    register long x5 asm("x5") = f;
    __asm_syscall("r"(x8), "0"(x0), "r"(x1), "r"(x2), "r"(x3), "r"(x4), "r"(x5));
    }

相关推荐
Tlog嵌入式19 小时前
蓝桥杯【物联网】零基础到国奖之路:十六. 扩展模块之矩阵按键
arm开发·stm32·单片机·mcu·物联网·蓝桥杯·iot
Q8343158191 天前
华为 海思22AP10(SS524)H.265 编解码处理器用户指南
arm开发·人工智能·嵌入式硬件·音视频·硬件工程·h.265·视频编解码
星羽空间1 天前
win11下 keil报错Cannot load driver ‘D:\Keil_v5\ARM\Segger\JL2CM3.dll‘
arm开发·keil
日晨难再2 天前
AMBA:APB的历史(从APB1到APB5)
arm开发·arm·硬件工程·fpga·数字ic
Tlog嵌入式2 天前
蓝桥杯【物联网】零基础到国奖之路:十八. 扩展模块之光敏和AS312
arm开发·stm32·单片机·mcu·物联网·蓝桥杯·iot
汽车电子助手3 天前
【STM32开发环境搭建】-4-在STM32CubeMX中新增Keil(MDK-ARM) 5的工程目录(包含指定路径的C和H文件)
c语言·arm开发·stm32·stm32cubemx·keil
海滩游侠3 天前
ARM Assembly 6: Shift 和 Rotate
arm开发
htx nb3 天前
ARM 架构、cpu
arm开发
极客小张3 天前
基于STM32的远程工业控制系统架构设计:MQTT通信、React界面与FreeRTOS优化的综合应用
c语言·arm开发·stm32·物联网·算法·react.js·毕业设计
勾栏听曲_04 天前
ARM6818开发板画任意矩形,圆形,三角形,五角星,6818开发板画太极,画五星红旗(含码源与思路)
c语言·arm开发·单片机·嵌入式硬件·硬件工程