Functions, the Stack & the Calling Convention
AAPCS64: argument and result registers, bl/ret, saving registers, stack frames, recursion and function pointers.
For assembly and C to call each other, both must follow the same rules: the Procedure Call Standard (AAPCS64 on 64-bit ARM). It says where arguments and results go, which registers a function may freely change, and how the stack is used.
Recursion, function pointers and arguments
bl factorial stores the return address in x30 (the link register) and jumps; ret jumps back to x30.
Because factorial calls itself, it must save x30 (and x29) first: stp x29, x30, [sp, #-32]! pushes them and moves sp down.
x19 is callee-saved: a function that uses it must restore it, so it survives across the recursive call.
blr x19 calls through a register — how C function pointers work; apply_twice calls the C function triple.
sum8 receives all eight arguments in x0–x7; a ninth would be passed on the stack.
AAPCS64 summary
my_func: bl helper ret // x30 was overwritten by bl my_func: stp x29, x30, [sp, #-16]! bl helper ldp x29, x30, [sp], #16 ret bl overwrites x30 with its own return address; without saving it, ret returns to the wrong place (an infinite loop or crash).
Which registers must a function preserve under AAPCS64?
x19–x28, x29 (frame pointer), sp, and the low 64 bits of v8–v15.