Syntax:
usr(<int address> [, <any arg1>, <any arg2>, ...])
usr!(<int address> [, <any arg1>, <any arg2>, ...])
usr%(<int address> [, <any arg1>, <any arg2>, ...])
The USR
function passes an arbitrary length of parameters to a machine language routine and executes it. The function is evaluated to the return value of the ML routine.
Example:
let retval = usr(address, arg1, arg2, ...)
You have to keep in mind a couple of rules when you write a user function in ML:
The caller will push the arguments onto the stack in reverse order, which means they are available for the callee in order. The byte order in which the arguments are pushed on the stack depends on the data type:
Bytes: a single byte pushed
Integers: pushed in LB/HB order
Floats: pushed backwards starting with MANT4, ending with EXP
Strings: the address of the string pushed in LB/HB order
The callee must pull all arguments from the stack and push exactly one return value that matches the required type (or reset the stack pointer likewise)
The return value must be pushed in the byte order just like the arguments are
When the callee has finished, it must return using the opcode JMP ($02FE)
. This is the only valid way to exit a function.
A simple example can be found here.