|Instruction||B / BL-|
|Function||Branch (/ with Link)|
B / BL : Branch / Branch with Link
B(ranch) and B(ranch with )L(ink) cause the program counter to point to a new address, thus the program continues at the instruction thus pointed to.
A B (Branch) is a jump, and is roughly equivalent to the
JMP instruction on processors such as the 6502 and the x86 family (though due to the use of conditional execution, this one instruction can replace numerous jump instructions on CISC processors).
A BL (Branch with Link) is a jump that additionally writes a return address to R14. This allows for a gosub/return mechanism, akin to
RTS on the 6502 or
CALL on the x86.
The only parameter is a signed 24 bit integer which is shifted two places to the left, thus meaning a signed 26 bit value where the two least significant bits are zero; therefore allowing branches to +/- 32 MiB range.
PC = address
B &8 ; Branch to address +8 (SWI vector!) BL writeline ; Branch with link to "writeline" function
Details and comparisons
As said above, BL provides a gosub/return mechanism. It works by placing the return address into R14 (also known as LR for Link Register).
Returning from the function is achieved simply by writing the contents of R14 back into the Program Counter. This can be achieved by simply performing
MOV PC, R14, or specifying PC instead of R14 in a multiple register load (if you saved R14).
Be aware that every BL will corrupt R14, so you should preserve your copy on the stack if you will be calling another function.
Here is a very simple example of an ARM function:
BL my_func B somewhere_else .my_func ...some code here... MOV PC, R14 .somewhere_else
In this example, the code flow is entry -> my_func -> entry+1 -> somewhere_else.
The same idea in 6502 would be:
JSR my_func JMP somewhere_else .my_func ...some code... RTS .somewhere_else
and in x86 code:
call my_func jmp somewhere_else my_func: ...some code... ret somewhere_else:
Please note that due to how the ARM works, the effective offset is the difference between the current instruction plus eight and the branch target. This is because when the branch is to be executed, PC is two instructions (thus eight bytes) further on.
Thus, for example, if you were to encounter an ARM assembly BNE instruction like this:
address codeword opcode operand 0x0024 1A00002E BNE loc_00E4
You would need to perform the following mental calculation to get the correct branch address (E4) from the codeword 2E.
2E * (4 bytes/word) + 8 bytes (PC is 2 instructions in advance) = B8 + 8 = C0
Thus C0 + 24 = E4.
The instruction bit pattern is as follows:
|31 - 28||27||26||25||24||23 - 0|
|condition||1||0||1||L||signed immediate 24 bit|
The L flag specifies if this is a