Call a functionΒΆ
ProblemΒΆ
Factor a piece of code into a reusable routine, like a function call in a normal language.
CodeΒΆ
stl.startup_and_init_all
stl.fcall greet, ret_addr
stl.fcall greet, ret_addr
stl.loop
greet:
stl.output "hi!\n"
stl.fret ret_addr
ret_addr: bit.vec w
Output:
hi!
hi!
WalkthroughΒΆ
stl.startup_and_init_allβstl.fcall/stl.fretuse the stack, so we need the full init.stl.fcall target, ret_addrβ saves the return address intoret_addr, then jumps totarget. On return the runtime jumps back to whatever was saved.stl.fret ret_addrβ jumps to the address stored inret_addr.
Note: ret_addr is a bit.vec w (one word wide β enough to hold a code address). One return slot per call site, NOT a stack of return addresses. For recursive or re-entrant calls youβd need to push/pop the return address onto a real stack.
VariationsΒΆ
Recursive calls require a stack. See stl.stack_init + hex.pointers.push_ret_address β the upstream calc.fj example uses this pattern.
Passing arguments β FlipJump has no calling convention. The conventional pattern is to declare a parameter variable, write into it before fcall, and have the callee read it:
// caller
bit.mov w, arg_buf, my_value
stl.fcall print_value, ret_addr
// callee
print_value:
bit.print_dec_uint w, arg_buf
stl.fret ret_addr
arg_buf: bit.vec w
ret_addr: bit.vec w