分支指令 |
(Branch)
B{条件} <地址>
B
是最简单的分支。一旦遇到一个 B
指令,ARM
处理器将立即跳转到给定的地址,从那里继续执行。注意存储在分支指令中的实际的值是相对当前的
R15
的值的一个偏移量;而不是一个绝对地址。它的值由汇编器来计算,它是
24 位有符号数,左移两位后有符号扩展为 32
位,表示的有效偏移为 26 位(+/- 32 M)。
在其他处理器上,你可能经常见到这样的指令:
OPT 1 LDA &70 CMP #0 BEQ Zero STA &72 .Zero RTS(取自 Acorn Electron User Guide issue 1 page 213)
在 ARM 处理器上,它们将变成下面这些东西:
OPT 1 ADR R1, #&70 LDR R0, [R1] CMP #0 BEQ Zero STR R0, [R1, #2] .Zero MOV PC, R14这不是一个很好的例子,但你可以构想如何更好的去条件执行而不是分支。另一方面,如果你有大段的代码或者你的代码使用状态标志,那么你可以使用条件执行来实现各类分支: 这样一个单一的简单条件执行指令可以替代在其他处理器中存在的所有这些分支和跳转指令。
OPT 1 ADR R1, #&70 LDR R0, [R1] CMP R0, #0 STRNE R0, [R1, #2] MOV PC, R14
(Branch with Link)
BL{条件} <地址>
BL
是另一个分支指令。就在分支之前,在寄存器 14
中装载上 R15 的内容。你可以重新装载 R14 到 R15
中来返回到在这个分支之后的那个指令,它是子例程的一个基本但强力的实现。它的作用在屏幕装载器
2 (例子 4)中得以很好的展现...
.load_new_format BL switch_screen_mode BL get_screen_info BL load_palette .new_loop MOV R1, R5 BL read_byte CMP R0, #255 BLEQ read_loop STRB R0, [R2, #1]!...在这里我们见到在装载器循环之前调用了三个子例程。接着,一旦满足了条件执行就在循环中调用了 read_byte 子例程。