The B
instruction will branch. It jumps to another instruction, and there is no return expected. The Link Register (LR) is not touched.
The BL
instruction will branch, but also link. LR will be loaded with the address of the instruction after BL
in memory, not the instruction executed after BL
. It will then be possible to return from the branch using LR.
Example :
start:
01: MOV r0, r2 ; some instruction
02: B there ; go there and never return !
there:
11: MOV r1, r0 ; some instruction
12: BL some_function ; go to some_function, but hope to return !
; this BL will load 13 into LR
13: MOV r5, r0
14: BL some_function ; this BL will load 15 into LR
15: MOV r6, r0
some_function:
MOV r0, #3
B LR ; here, we go back to where we were before
If you want to call another function inside a function, LR will be overwritten, so you won’t be able to return. The common solution is to save LR on the stack with PUSH {LR}
, and restore it before returning with POP {LR}
. You can even restore and return in a single POP {PC}
: this will restore the value of LR, but in the program counter, effectively returning of the function.
Courtesy: https://stackoverflow.com/questions/34091898/bl-instruction-arm-how-does-it-work
Leave a comment