Functions and BL
Functions in ARM64
Functions (also called subroutines or procedures) let you organize code into reusable blocks. ARM64 implements function calls using two key concepts: the BL instruction and the link register.
BL -- Branch with Link
BL does two things in one instruction:
- Saves the address of the next instruction into
X30(the Link Register, also calledLR) - Jumps to the target label
Think of
BLas sending an away team on a mission: it saves the ship's coordinates (the return address) in the Link Register so the team can beam back when the mission is complete.
BL my_function // X30 = address of next instruction, then jump
// execution continues here when my_function returns
RET -- Return
RET branches to the address in X30, returning to the caller:
my_function:
// ... function body ...
RET // Jump to address in X30 (back to caller)
BL vs B
| Instruction | Saves return address? | Use for |
|---|---|---|
B label | No | One-way jump (loops, goto) |
BL label | Yes (in X30) | Function calls (expects RET) |
A Simple Function
Here is a function that doubles a value in X0:
double:
ADD X0, X0, X0 // X0 = X0 + X0
RET
_start:
MOV X0, #21
BL double // Call double, X0 = 42 on return
Function Arguments and Return Values
By convention, function arguments are passed in X0 through X7, and the return value is in X0:
// add(a, b) -- returns a + b
add:
ADD X0, X0, X1 // X0 = X0 (a) + X1 (b)
RET
_start:
MOV X0, #3 // first argument
MOV X1, #4 // second argument
BL add // X0 = 7 on return
Important: After
BL, the function can freely modify X0-X15 (caller-saved registers). If you need a value to survive a function call, save it first. The return value always comes back in X0.
Function Placement
Functions must be placed before _start (or jumped over). If you put a function after _start without a branch around it, the CPU will fall through into the function code unexpectedly:
// Good: function before _start
square:
MUL X0, X0, X0
RET
_start:
MOV X0, #7
BL square // Calls square, returns here
Your Task
Write a function called square that takes a number in X0 and returns its square (X0 * X0) in X0. Call it from _start with the value 7, then print the result (49) followed by a newline.