ARM 汇编指令:B
核心含义
B是Branch的缩写,意思是无条件跳转。它会让程序的执行流程立即、无条件地跳转到指定的目标地址,继续执行。它是最基础、最常用的指令之一。
基本语法
B labellabel: 一个符号(标签),代表程序中某个位置的地址。
工作原理
当执行到B指令时:
- 处理器计算出要跳转的目标地址(基于当前 PC 和标签的偏移量)。
- 将计算出的目标地址直接加载到程序计数器(PC)中。
- 下一条被执行的指令就是目标地址处的指令。
这相当于 C 语言中的goto语句。
示例
_start: MOV R0, #5 ; R0 = 5 B skip_add ; 无条件跳转到 skip_add 标签处 ADD R0, R0, #3 ; 这行指令会被跳过,不会执行 skip_add: MOV R1, #10 ; 跳转后从这里开始执行 ADD R2, R0, R1 ; R2 = R0 + R1 B . ; 跳转到自身,形成无限循环(常用于程序结尾)主要用途
循环控制:跳转到循环开始处。
loop_start: ... ; 循环体 SUBS R1, R1, #1 ; 更新计数器并设置条件标志 BNE loop_start ; 如果 R1 != 0,则继续循环这里
BNE是条件跳转,但循环的闭合需要B或其它分支指令。跳过代码块:用于条件判断中,跳过某些不执行的代码。
CMP R0, #0 BEQ zero_case ; 如果等于0,跳转 ... ; 非零情况的处理 B end_if ; 无条件跳过“zero_case”的代码 zero_case: ... ; 等于0时的处理 end_if:函数/过程调用(简单版):虽然更标准的调用用
BL(带链接的分支,用于函数调用),但在某些简单场景或尾调用优化中,也可能直接用B。; 注意:使用 B 跳转到函数不会保存返回地址到 LR my_function: ... BX LR ; 函数返回 main: ... B my_function ; 跳转到函数,但无法返回!通常这是错误的,应用 BL my_function程序流程的永久转移:例如,在启动代码或状态机中,从一个模式永久跳转到另一个主循环。
与相关指令的对比
| 指令 | 全称 | 行为 | 用途 |
|---|---|---|---|
B | Branch | 无条件跳转 | 单纯的跳转,不打算返回 |
BL | Branch with Link | 跳转前,将返回地址(PC+4)保存到链接寄存器 LR(R14) | 函数调用 |
BX | Branch and eXchange | 跳转,并可切换 ARM/Thumb 指令集 | 用于函数返回(BX LR)或跳转到状态未知的代码 |
Bcond(如BEQ,BNE) | Conditional Branch | 根据条件标志(N,Z,C,V)决定是否跳转 | 条件执行、循环、if-else |
技术细节(针对经典 ARM 模式)
B指令的跳转范围是有限的。它是一个24 位有符号立即数指定的偏移量(以字为单位),因此跳转范围约为±32MB(相对于当前 PC)。- 如果需要在更大范围内跳转,通常需要借助其他指令(如
LDR PC, =address)或通过寄存器间接跳转。 - 在Thumb指令集中,
B指令的编码和跳转范围有所不同(例如,Thumb 的B通常是 16 位指令,跳转范围更小)。
总结
B label就是告诉处理器:“别执行下一条指令了,马上去执行label那里的指令。”
它是控制程序流程最基础的构件,是所有条件分支和函数调用的基础。在阅读或编写汇编时,看到B,你就知道程序的控制流将在这里发生一次直接的、无条件的转移。