当前位置: 首页 > news >正文

A64指令集基本指令(一):分支指令

前言


Alphabetical list of A64 base instructions gives full descriptions of the A64 instructions that are in the following instruction groups:

  • Branch, Exception generation, and System instructions.
  • Loads and stores associated with the general-purpose registers.
  • Data processing (immediate).
  • Data processing (register).

ARM 手册中所说,A64 基本指令包括

  • 分支、异常生成和系统指令
  • 与通用寄存器相关的加载和存储指令
  • 数据处理(立即数)指令
  • 数据处理(寄存器)指令

本文将详细介绍一下分支指令。另外,本系列目前不会涉及 SVE 指令和 SIMD 指令,避免有需要的读者浪费时间。

条件码

这个表格是 ARMv8-A 架构中 A64 指令集的条件码 (Condition code) 表,提供了条件分支指令使用的所有可能条件(手册原表中浮点数相关内容我已删掉)。

条件码助记符含义(整数)条件标志
0000EQ相等Z == 1
0001NE不相等Z == 0
0010CS或HS进位设置C == 1
0011CC或LO进位清除C == 0
0100MI负数N == 1
0101PL正数或零N == 0
0110VS溢出V == 1
0111VC无溢出V == 0
1000HI无符号大于C == 1 && Z == 0
1001LS无符号小于等于!(C == 1 && Z == 0)
1010GE有符号大于等于N == V
1011LT有符号小于N != V
1100GT有符号大于Z == 0 && N == V
1101LE有符号小于等于!(Z == 0 && N == V)
1110AL总是执行任意
1111NV总是执行任意

注:NV 条件码存在仅为提供 0b1111 编码的有效反汇编,其行为与 AL 相同。

标志位及含义对应解释

  • N(Negative):结果是否为负数,N == 1,代表结果为负数
  • Z(Zero):结果是否为零,Z == 1,代表结果为0
  • C(Carry):产生进位/没有借位,C == 0,代表结果为负数
  • V(oVerflow):有符号运算溢出,V == 1,代表结果溢出

注:在这几个标志位中,比较不同的是 C 标志位,C == 0,代表没有发生借位。而 C == 1代表发生了借位,为什么呢?

因为减法实际上是通过加法和补码来实现的。CMP A, B 语义上执行的是 A - B。但我们知道,-B 的补码等于对 B 取反加1,也就是实际上执行的是 A + (~B + 1),也就是 A + (B的二进制补码)

以一个 4bit 数据位宽的具体例子为例:假设比较 53(CMP 5, 3),实际执行: 5 + (~3 + 1) = 5 + 13 = 18 (超出4位,产生进位)。结果为正,且有进位,所以 C=1,表示 5>3

条件指令

条件指令介绍开始之前需要知道,ARM架构对分支指令有严格的使用规则:

  1. 在调用嵌套子程序时,只能使用BLR或BL指令
  2. 从子程序返回时,只能使用RET指令
  3. 对于非子程序调用/返回的控制流转移,应使用B、B.cond等指令

1.条件分支指令

条件分支指令根据条件标志(Condition flags)或通用寄存器中的值改变执行流程。

示例指令:B.cond

  • 用途:根据条件码执行条件跳转
  • 执行过程:检查PSTATE中的条件标志(N、Z、C、V),如果满足条件,则PC += 偏移量(±1MB范围内)
  • 例如:B.EQ label(如果结果为零则跳转)

示例指令:BC.cond

  • 用途:一致性条件分支,保证跳转预测的一致性
  • 执行过程:与B.cond类似,但提供更一致的分支预测行为

cond 所有取值如下所示,具体含义见条件码所示:

编码0000000100100011010001010110011110001001101010111100110111101111
condEQNECSCCMIPLVSVCHILSGELTGTLEALNV

示例指令:CBNZ/CBZ

  • 用途:比较寄存器值并在非零/零时分支
  • 执行过程:将指定寄存器的值与零比较,满足条件则PC += 偏移量(±1MB范围内)
  • 例如:CBZ x0, label(如果x0为零则跳转)

示例指令:TBNZ/TBZ

  • 用途:测试寄存器中的特定位,并在非零/零时分支
  • 执行过程:测试指定寄存器中特定位的值,满足条件则PC += 偏移量(±32KB范围内)
  • 例如:TBZ x0, #5, label(如果x0的第5位为0则跳转)

2.无条件分支(立即数)

无条件分支指令无条件地改变执行流程,使用即时偏移量。

示例指令:B

  • 用途:无条件跳转到目标地址
  • 执行过程:PC += 偏移量(±128MB范围内)
  • 例如:B label(总是跳转到label)

示例指令:BL

  • 用途:带链接的分支,用于调用子程序
  • 执行过程:将下一条指令地址保存到X30寄存器,然后PC += 偏移量(±128MB范围内)
  • 例如:BL function(调用函数并保存返回地址)

3. 无条件分支(寄存器)

无条件分支指令通过寄存器中存储的地址值改变执行流程。

示例指令:BLR

  • 用途:带链接的寄存器分支,用于间接调用子程序
  • 执行过程:将下一条指令地址保存到 X30,然后 PC = 寄存器内容
  • 例如:BLR x0(调用x0中保存的地址,并保存返回地址到X30)

示例指令:BR

  • 用途:寄存器分支,无条件跳转到寄存器中的地址
  • 执行过程:PC = 寄存器内容
  • 例如:BR x0(跳转到x0中保存的地址)

示例指令:RET

  • 用途:从子程序返回
  • 执行过程:PC = X30(或指定寄存器)
  • 例如:RET(返回到X30中保存的地址)

直接条件分支和间接条件分支指令

ARM 手册中还对分支指令做了直接分支和间接分支指令的区分。这里手册中另外介绍了很多关于地址认证的指令。不经常使用,不会详细展开。这部分其实也可以不看。

直接分支指令

直接分支指令中,跳转目标地址直接编码在指令中:

1. B (无条件分支)

  • 用途:无条件跳转到指定地址
  • 执行过程:PC直接设置为指令中的目标地址
  • 示例B label1 —— 程序无条件跳转到label1处执行

2. B.cond (条件分支)

  • 用途:根据条件标志位决定是否分支
  • 执行过程:检查NZCV标志位,如果条件满足则跳转
  • 示例B.EQ label2 —— 当结果为零(相等)时跳转到label2

3. BC.cond (条件一致性分支)

  • 用途:带有内存一致性保证的条件分支
  • 执行过程:与B.cond类似,但提供额外的一致性保证
  • 示例BC.EQ label3 —— 在多处理器系统中提供一致性保证的条件分支

4. BL (带链接的分支)

  • 用途:跳转到子程序并保存返回地址
  • 执行过程:将返回地址保存在LR寄存器(X30)中,然后跳转
  • 示例BL subroutine —— 调用子程序并在完成后可返回

5. CBZ/CBNZ (比较并分支)

  • 用途:将寄存器与零比较,根据结果分支
  • 执行过程
    • CBZ:如果寄存器值为零则分支
    • CBNZ:如果寄存器值非零则分支
  • 示例
    • CBZ X0, label4 —— 如果X0为0则跳转到label4
    • CBNZ X1, label5 —— 如果X1不为0则跳转到label5

6. TBZ/TBNZ (测试位并分支)

  • 用途:测试寄存器中特定位的值并分支
  • 执行过程
    • TBZ:如果指定位是0则分支
    • TBNZ:如果指定位是1则分支
  • 示例
    • TBZ X2, #3, label6 —— 如果X2的第3位是0则跳转
    • TBNZ X3, #7, label7 —— 如果X3的第7位是1则跳转

间接分支指令

间接分支指令中,跳转目标地址存储在寄存器中:

1. BLR (带链接到寄存器的分支)

  • 用途:跳转到寄存器指定的地址并保存返回地址
  • 执行过程:将返回地址保存在LR中,然后跳转到寄存器指定的地址
  • 示例BLR X4 —— 跳转到X4寄存器中存储的地址并保存返回地址

2. BLRAA/BLRAAZ/BLRAB/BLRABZ (带指针认证的链接到寄存器的分支)

  • 用途:提供指针认证的间接调用
  • 执行过程:验证跳转地址的完整性,如果通过,则设置返回地址并跳转
  • 示例BLRAA X5, X6 —— 使用X6作为认证修饰符跳转到X5中的地址

3. BR (分支到寄存器)

  • 用途:无条件跳转到寄存器中的地址
  • 执行过程:PC设置为指定寄存器的值
  • 示例BR X7 —— 跳转到X7寄存器包含的地址

4. BRAA/BRAAZ/BRAB/BRABZ (带指针认证的分支到寄存器)

  • 用途:带指针认证的无条件间接跳转
  • 执行过程:验证地址,如通过则执行跳转
  • 示例BRAA X8, X9 —— 使用X9作为认证修饰符跳转到X8中的地址

5. ERET/ERETAA/ERETAB (异常返回)

  • 用途:从异常处理返回
  • 执行过程:从ELR_ELx寄存器加载PC并从SPSR_ELx还原处理器状态
  • 示例ERET —— 从异常处理返回到中断点

6. RET/RETAA/RETAB (子程序返回)

  • 用途:从子程序返回
  • 执行过程:将PC设置为LR寄存器(X30)中的返回地址
  • 示例RET —— 从子程序返回到调用点

7. RETAA/RETAB (带指针认证的返回)

  • 用途:带指针认证的子程序返回
  • 执行过程:验证LR中的返回地址,如通过则返回
  • 示例RETAA —— 使用A密钥认证LR并返回

8. RETAASPPC/RETABSPPC (使用偏移的带指针认证的返回)

  • 用途:使用即时偏移的带指针认证的返回
  • 执行过程:使用即时偏移进行指针认证并返回
  • 示例RETAASPPC #16 —— 使用16字节偏移进行认证并返回

9. RETAASPPCR/RETABSPPCR (使用寄存器的带指针认证的返回)

  • 用途:使用寄存器值进行指针认证的返回
  • 执行过程:使用寄存器值作为修饰符进行指针认证并返回
  • 示例RETAASPPCR X10 —— 使用X10寄存器值进行认证并返回

总结

完结撒花!!!

参考

a_a-profile_architecture_reference_manual.pdf

相关文章:

  • Apache Doris:一款高性能的实时数据仓库
  • 实现 Leaflet 多类型点位标记与聚合功能的实战经验分享
  • python-leetcode-最长有效括号
  • 蓝桥杯15届JavaB组6题
  • C/C++语言知识点一
  • 提示学习(Prompting)
  • 算法与数据结构(二叉树中的最大路径和)
  • 深入了解 Python 中的 MRO(方法解析顺序)
  • Docker搭建基于Rust语言的云原生可观测平台OpenObserve
  • sklearn中的决策树-分类树:剪枝参数
  • PMP项目管理—整合管理篇—7.结束项目或阶段
  • 【Kubernetes】API server 限流 之 maxinflight.go
  • 跨AWS账户共享SQS队列以实现消息传递
  • SQL Server 视图的更新排查及清除缓存
  • Protobuf原理与序列化
  • 高数1.1 函数
  • 深度学习-11.用于自然语言处理的循环神经网络
  • Spring Boot集成Spring Security之HTTP请求授权
  • C++11智能指针
  • 细说 Java GC 垃圾收集器
  • 北京航空航天大学首个海外创新研究院落户巴西
  • 7月打卡乐高乐园,还可以去千年古镇枫泾参加这个漫画艺术季
  • 宝妈称宝宝在粽子中吃出带血创可贴,来伊份:已内部排查
  • 视频丨习近平同普京在主观礼台出席红场阅兵式
  • 欧洲史上最严重停电事故敲响警钟:能源转型如何保证电网稳定?
  • 中俄元首今年首次面对面会谈,达成哪些新的重要共识?