Writing inline assembly in KCC is fairly simple.
Let’s say we have a function in plain z80 assembly called getRandom that returns a single random byte in register a (an apt example as such a function exists in the knightos kernel). How can we make this function accessible to C?
Well first, we need to have a C function. Since C functions are prefixed with an
_) when turned into assembly, the name
getRandom is perfectly
In KCC (and SDCC, which KCC is derived from), functions that are written purely
in inline assembly should be postfixed with
__naked to indicate that the
compiler shouldn’t “dress” the function with the bits of assembly it normally
At this point, the function should look like this:
There are two styles you can use to write inline assembly in KCC. The first is
__asm__("inline assembly here")_ format. A simple example of this
__asm__("nop"); which just injects a nop.
The second style is better suited to multiple lines, and is used like this:
To call the assembly function getRandom, you could just do the following:
There are, however, multiple small problems with this. First, the
ret that is
normally generated by KCC is part of the function’s “epilogue,” which is removed
due to the
__naked attribute. Just adding
call getRandom is
enough to fix that though. A second issue is that this is KnightOS, so the call
needs to be a
pcall. The third and arguably most important problem is the KCC
ABI, or Application Binary Interface. When a function in KCC returns a
(signage is irrelevant), it has to return it in the
l register (16-bit values
must be returned in
hl). The asm getRandom function returns its value in
Obviously, that means
ld l, a is needed before returning.
However, there’s one more small issue:
pcall is a macro KnightOS provides for
assembly code only. To make
pcalls in C bindings, you need to use a different
macro, PCALL, which KnightOS provides for C.
Furthermore, all kernel functions, when used in C, need to be in all caps.
The final function, then, is as follows:
The KCC libc uses the name
get_random for the C binding to the
function, but if you check system.c, you’ll see this:
Normal instructions (such as ld and ret) are not case-sensitive, so both functions are valid.