This video will talk about how to call a subroutine in assembly.
A subroutine may be called a routine, function, or procedure.
For Arm Cortex-M, register r15 holds the program counter (PC).
It stores the memory address of the instruction that is being fetched from the memory.
Due to pipelining, PC points to the address of the instruction being fetched from memory,
rather than the instruction being executed.
Register r14 is the link register.
It holds the return address when a subroutine is called.
It stores the memory address of the instruction that should be executed immediately after
a subroutine completes.
The link register allows a program to continue its execution after a subroutine call is completed.
In assembly, we can make a subroutine call by using the instruction Branch with Link (BL)
Suppose we have a subroutine foo, the instruction BL foo calls the subroutine foo.
This BL instruction performs two operations.
First, it saves the return address in the link register LR.
Specifically, it saves the memory address of this add instruction into the Link Register.
Second, it sets the program counter PC to the memory address of the foo subroutine.
The second operation directly transfers the control to this subroutine.
In the binary executable, the compiler translates the subroutine label, such as foo, to a PC-relative
offset, and encodes this offset value in the 32-bit BL instruction.
In a subroutine, we can use the branch and exchange instruction (BX) to exit from this
subroutine, and return to the caller.
The instruction BX LR will branch to the address stored in the Link Register (LR).
Specifically, it copies the value of LR to PC.
Let me use another example to illustrate how BL and BX work.
When the main program calls the foo function, the control is transferred to the callee.
Here, we say the main function is the caller, and the foo function is the callee.
When the foo function returns, the control is transferred back to the caller so that
the main function can resume the execution.
In assembly, the instruction BL foo is used to transfer the control to the callee, and
the BX LR instruction is used to return the control to the caller.
Suppose the memory address of the instruction BL foo is 800210 in hex and the subroutine
foo is stored at the memory location 8000280.
Since the BL instruction takes four bytes in the memory, the memory address of the instruction
immediately after the BL instruction is 800214 in hex.
Suppose PC current points to the BL instruction.
When the BL instruction runs, it first sets the Link Register to the value 8000214, which
is equal to the PC current plus 4.
In fact, the LR register should have a value of 8000215, rather than 8000214.
This is because bit 0 of the link register is always 1 during a function call.
The least significant bit is used to indicate whether the processor will run in the Thumb
state or in the Arm state when the function returns.
Since Arm Cortex-M only supports the Thumb state, the least significant bit of the link
register is always 1 during a function call.
Then, the BL instruction sets the PC to 800280, which is the memory address of the subroutine foo.
When the subroutine foo returns, it executes the instruction BX LR . This instruction will
copy the value of LR to PC.
Therefore, the value of PC becomes 8000214.
The bit 0 of the PC is always 0 because compilers always ensure that instructions are word aligned
or half-word aligned.
After the function call is completed, PC points to the instruction immediately after the BL
instruction.
Accordingly, the caller can continue to execute the rest of the code.
Thank you for watching.