4.1. BranchΒΆ
The unconditional branch instruction allows us to skip to a new location to continue executing code from. When the branch executes, the program counter is not increased by 4 bytes as normal, but instead its value is replaced with the address of a new instruction.
B
labelBranch. Change the program counter to the address of the line identified by label.
In this code sample, line number 3 has a branch that will cause execution to skip over the code on lines 4 and 5 and execute the next line
after the label target
, which is line 7.
1 2 3 4 5 6 7 | MOV r1, #1 @random work
MOV r2, #2
B target @branch to target
MOV r3, #3 @skipped
MOV r4, #4 @skipped
target:
MOV r5, #5
|
Note
The assembler calculates the destination address and stores it in the instruction as +/- value to add to the PC
register when the branch executes.
This offset is stored as 24-bits in the instruction:
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
cond | 101 | L | 24-bit offset |
Since instruction addresses in ARM are always multiples of 4, the last two bits of any instruction address are always 00. This fact is used to compress the stored offsets - the value stored in the instruction has been right shifted 2 bits to remove those 0s. To use the stored address, the hardware first shifts it to the left 2 bits and then sign extends it. For example, in the code sample above, the instruction looks like:
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | 1 | 1 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
E | A | 0 | 0 | 0 | 0 | 0 | 1 |
If we mask the last 24 bits and then shift them left 2 and sign extend, we get:
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
The final offset value is 4. To that value, we have to add 8. (This add 8 is due to the historical design of the ARM architecture where the
PC
will already have advanced 2 instructions or 8 bytes before the branch address is actually used). So the final amount for the branch is 12 bytes, or
at 4 bytes per instructions, 3 instructions ahead. Sure enough, the shown branch skips over 2 instructions and runs the third one after the B
.