登录后台

页面导航

本文编写于 481 天前,最后修改于 450 天前,其中某些信息可能已经过时。

编写汇编代码常常会使用跳转指令,A64指令集提供了多种不同功能的跳转指令

指令 描述
B 跳转指令
B label
该跳转指令可以在当前PC偏移量±128MB的范围内无条件的跳转到label处
B.cond 有条件的跳转指令
B.cond label
如B.EQ,该指令可以在当前PC偏移量±1MB的范围内有条件地跳转到label处
BL 带返回地址地跳转指令
和B指令类似,不同的地方是,BL指令即将返回地址设置到LR(X30寄存器)中,保存的值位调用BL指令的当前PC值加上4
BR 跳转到寄存器指定的地址
BR Xn
BLR 跳转到寄存器指定的地址
BLR Xn
和BR指令类似,不同的地方是,BLR指令将返回地址设置到LR (X30寄存器)中

A64指令集提供了两条返回指令。

  • RET指令:通常用于子函数的返回,其返回地址保存在LR里。
  • ERET指令:从当前的异常模式返回。它会把SPSR的内容恢复到PSTATE寄存器中, 从ELR中获取跳转地址并返回到该地址。ERET指令可以实现处理器模式的切换,比 如从EL1切换到EL0。

A64指令集还提供了几个比较并跳转指令

指令 描述
CBZ 比较并跳转指令。指令的格式如下。
CBZ Xt, label
判断Xt寄存器是否为0,若为0,则跳转到label处,跳转范围是当前PC相对偏移±1MB
CBNZ 比较并跳转指令。指令的格式如下。
CBZ Xt, label
判断Xt寄存器是否不为0,若不为0,则跳转到label处,跳转范围是当前PC相对偏移±1MB
TBZ 测试位并跳转指令。指令的格式如下。
TBZ R, #imm, label
判断Rt寄存器中第imm位是否为0,若为0,则跳转到label处,跳转范围是当前PC相对偏移量±32 KB
TBNZ 测试位并跳转指令。指令的格式如下。
TBZ R, #imm, label
判断Rt寄存器中第imm位是否不为0,若不为0,则跳转到label处,跳转范围是当前PC相对偏移量±32 KB

需要注意的是:

在汇编代码里可以使用BL指令来调用子函数,不过处理不当会导致系统崩溃。因为使用BL指令跳转到子函数时会修改LR (X30寄存器)的值,把当前PC+4的值写入LR中。这就把父函数的LR给修改了,导致父函数调用RET指令返回时系统崩溃。

解决办法是在遇到嵌套调用函数时在父函数里把LR的值保存到一个临时寄存器。在父函数返回之前,先从临时寄存器中恢复LR的值,再执行RET指令。