From d52baca7b219933e577d82ce80f006c9d45ec73e Mon Sep 17 00:00:00 2001 From: Toby Jaffey Date: Wed, 10 Dec 2025 01:24:34 +0000 Subject: [PATCH] Move example --- README.md | 135 +++++++++++++++++++++++------------------------------- 1 file changed, 58 insertions(+), 77 deletions(-) diff --git a/README.md b/README.md index 552adb4..3a75310 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,64 @@ uvm32 is a minimalist, dependency-free virtual machine sandbox designed for micr Although based on a fully fledged CPU emulator, uvm32 is intended for executing custom script like logic, not for simulating hardware. +## Example + +A simple VM host from [apps/host-mini](apps/host-mini) + +```c +#include +#include +#include +#include "uvm32.h" +#include "../common/uvm32_common_custom.h" + +uint8_t rom[] = { // mandel.bin + 0x23, 0x26, 0x11, 0x00, 0xef, 0x00, 0xc0, 0x00, 0xb7, 0x08, 0x00, 0x01, + ... + ... +}; + +int main(int argc, char *argv[]) { + uvm32_state_t vmst; + uvm32_evt_t evt; + bool isrunning = true; + + uvm32_init(&vmst); + uvm32_load(&vmst, rom, sizeof(rom)); + + while(isrunning) { + uvm32_run(&vmst, &evt, 100); // num instructions before vm considered hung + + switch(evt.typ) { + case UVM32_EVT_END: + isrunning = false; + break; + case UVM32_EVT_SYSCALL: // vm has paused to handle UVM32_SYSCALL + switch(evt.data.syscall.code) { + case UVM32_SYSCALL_PUTC: + printf("%c", uvm32_getval(&vmst, &evt, ARG0)); + break; + case UVM32_SYSCALL_PRINTLN: { + const char *str = uvm32_getcstr(&vmst, &evt, ARG0); + printf("%s\n", str); + } break; + default: + printf("Unhandled syscall 0x%08x\n", evt.data.syscall.code); + break; + } + break; + case UVM32_EVT_ERR: + printf("UVM32_EVT_ERR '%s' (%d)\n", evt.data.err.errstr, (int)evt.data.err.errcode); + break; + default: + break; + } + } + + return 0; +} +``` + ## Samples * [host](host) vm host which loads a binary and runs to completion, handling multiple syscall types @@ -145,83 +203,6 @@ The following functions are used to access syscall parameters safely: void uvm32_setval(uvm32_state_t *vmst, uvm32_evt_t *evt, uvm32_arg_t, uint32_t val); uvm32_evt_syscall_buf_t uvm32_getbuf(uvm32_state_t *vmst, uvm32_evt_t *evt, uvm32_arg_t argPtr, uvm32_arg_t argLen); -Here is a full example of a working VM host from [apps/host-mini](apps/host-mini) - --- - -```c -#include -#include -#include -#include "uvm32.h" -#include "../common/uvm32_common_custom.h" - -uint8_t rom[] = { // mandel.bin - 0x23, 0x26, 0x11, 0x00, 0xef, 0x00, 0xc0, 0x00, 0xb7, 0x08, 0x00, 0x01, - 0x73, 0x00, 0x00, 0x00, 0x13, 0x01, 0x01, 0xff, 0x23, 0x26, 0x81, 0x00, - 0x37, 0xf5, 0xff, 0xff, 0xb7, 0x15, 0x00, 0x00, 0x37, 0xe6, 0xff, 0xff, - 0x13, 0x07, 0xf0, 0x01, 0xb7, 0x47, 0x00, 0x00, 0xb7, 0x06, 0x00, 0x01, - 0x13, 0x08, 0xd5, 0xcc, 0x93, 0x82, 0x35, 0x33, 0x13, 0x03, 0x76, 0xe6, - 0x93, 0x83, 0x35, 0xb3, 0x13, 0x86, 0x16, 0x00, 0x63, 0xce, 0x02, 0x09, - 0x13, 0x0e, 0x03, 0x00, 0x63, 0xce, 0x63, 0x06, 0x93, 0x0f, 0x00, 0x00, - 0x13, 0x0f, 0x00, 0x00, 0x13, 0x04, 0x00, 0x00, 0x93, 0x0e, 0x00, 0x00, - 0x93, 0x06, 0x00, 0x02, 0x13, 0x85, 0x06, 0xfe, 0x63, 0x64, 0xa7, 0x04, - 0x33, 0x05, 0xff, 0x01, 0x63, 0xe0, 0xa7, 0x04, 0x13, 0x05, 0x00, 0x00, - 0x93, 0x05, 0x00, 0x00, 0x93, 0x08, 0x06, 0x00, 0xb3, 0x8e, 0x8e, 0x02, - 0x33, 0x0f, 0xff, 0x41, 0x13, 0xd4, 0xbe, 0x40, 0xb3, 0x0e, 0xcf, 0x01, - 0x73, 0x00, 0x00, 0x00, 0x33, 0x04, 0x04, 0x01, 0x33, 0x85, 0xde, 0x03, - 0x13, 0x5f, 0xc5, 0x00, 0x33, 0x05, 0x84, 0x02, 0x93, 0x5f, 0xc5, 0x00, - 0x93, 0x86, 0x16, 0x00, 0x6f, 0xf0, 0x9f, 0xfb, 0x13, 0x85, 0x06, 0x00, - 0x93, 0x05, 0x00, 0x00, 0x93, 0x08, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, - 0x13, 0x0e, 0x1e, 0x09, 0xe3, 0xd6, 0xc3, 0xf9, 0x13, 0x05, 0xa0, 0x00, - 0x93, 0x05, 0x00, 0x00, 0x93, 0x08, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, - 0x13, 0x08, 0x98, 0x19, 0xe3, 0xd6, 0x02, 0xf7, 0x37, 0x05, 0x00, 0x80, - 0x13, 0x05, 0x05, 0x10, 0x93, 0x08, 0x30, 0x00, 0x93, 0x05, 0x00, 0x00, - 0x73, 0x00, 0x00, 0x00, 0x03, 0x24, 0xc1, 0x00, 0x13, 0x01, 0x01, 0x01, - 0x67, 0x80, 0x00, 0x00, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, - 0x72, 0x6c, 0x64, 0x00 -}; - -int main(int argc, char *argv[]) { - uvm32_state_t vmst; - uvm32_evt_t evt; - bool isrunning = true; - - uvm32_init(&vmst); - uvm32_load(&vmst, rom, sizeof(rom)); - - while(isrunning) { - uvm32_run(&vmst, &evt, 100); // num instructions before vm considered hung - - switch(evt.typ) { - case UVM32_EVT_END: - isrunning = false; - break; - case UVM32_EVT_SYSCALL: // vm has paused to handle UVM32_SYSCALL - switch(evt.data.syscall.code) { - case UVM32_SYSCALL_PUTC: - printf("%c", uvm32_getval(&vmst, &evt, ARG0)); - break; - case UVM32_SYSCALL_PRINTLN: { - const char *str = uvm32_getcstr(&vmst, &evt, ARG0); - printf("%s\n", str); - } break; - default: - printf("Unhandled syscall 0x%08x\n", evt.data.syscall.code); - break; - } - break; - case UVM32_EVT_ERR: - printf("UVM32_EVT_ERR '%s' (%d)\n", evt.data.err.errstr, (int)evt.data.err.errcode); - break; - default: - break; - } - } - - return 0; -} -``` ## Configuration