本文编写于 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 判断Rt寄存器中第imm位是否为0,若为0,则跳转到label处,跳转范围是当前PC相对偏移量±32 KB |
TBNZ | 测试位并跳转指令。指令的格式如下。 TBZ R 判断Rt寄存器中第imm位是否不为0,若不为0,则跳转到label处,跳转范围是当前PC相对偏移量±32 KB |
需要注意的是:
在汇编代码里可以使用BL指令来调用子函数,不过处理不当会导致系统崩溃。因为使用BL指令跳转到子函数时会修改LR (X30寄存器)的值,把当前PC+4的值写入LR中。这就把父函数的LR给修改了,导致父函数调用RET指令返回时系统崩溃。
解决办法是在遇到嵌套调用函数时在父函数里把LR的值保存到一个临时寄存器。在父函数返回之前,先从临时寄存器中恢复LR的值,再执行RET指令。