Software¶
Calling convention¶
I use very simple calling convention in my code:
- all arguments are in registers
- first argument in
r0
, second inr1
, ... You get the picture.- if there’s too many arguments, refactor your code or use a stack...
- return value is in
r0
- callee is reponsible for save/restore of registers it’s using, with exception of:
- registers that were used for passing arguments - these are expected to have undefined value when callee returns
r0
if callee returns value back to caller
All virtual interrupt routines, assembler code, any pieces of software I’ve written for this virtual machine follows this calling convention - unless stated otherwise...
Software interrupts¶
Software interrupts provide access to library of common functions, and - in case of virtual interrupts - to internal, complex and otherwise inaccessible resources of virtual machine itself.
For the list for existing interrupts and their numbers, see ducky.irq.IRQList
. However, by the nature of invoking a software interrupt, this list is not carved into a stone. You may easily provide your own EVT
, with entries leading to your own routines, and use e.g. the 33th entry, HALT
, to sing a song.
All values are defined in files in defs/
directory which you can - and should - include into your assembler sources.
BLOCKIO
¶
EVT entry |
33 |
||
Read mode | Write mode | ||
Parameters | r0 |
device id | |
r1 |
bit #0: 0 for read, 1 for write
bit #1: 0 for synchronous, 1 for asynchronous operation |
||
r2 |
block id | src memory address | |
r3 |
dst memory address | block id | |
r4 |
number of blocks | ||
Returns | r0 |
0 for success |
Perform block IO operation - transfer block between memory and storage device. Use the lowest bit of r1
to specify direction:
0
- read mode, blocks are transfered from storage into memory1
- write mode, blocks are tranfered from memory to storage
Current data segment is used for addressing memory locations.
If everything went fine, 0
is returned, any other value means error happened.
IO operation is a blocking action, interrupt will return back to the caller once the IO is finished. Non-blocking (DMA-like) mode is planned but not yet implemented.
This operation is implemented as a virtual interrupt, see ducky.blockio.BlockIOInterrupt
for details.
VMDEBUG
¶
EVT entry |
34 |
|
QUIET mode |
||
Parameters | r0 |
0 |
r1 |
0 for quiet mode, anything else for full mode |
|
Returns | r0 |
0 for success |
VM
interrupt allows control of VM debugging output. Currently, only two levels of verbosity that are available are quiet and full mode. In quiet mode, VM produces no logging output at all.
This interrupt can control level amount of debugging output in case when developer is interested only in debugging only a specific part of his code. Run VM with debugging turned on (-d
option), turn the debugging off at the beggining of the code, and turn it on again at the beggining of the interesting part to get detailed output.