首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C虚拟机V2

C虚拟机V2
EN

Code Review用户
提问于 2017-07-07 01:46:36
回答 1查看 173关注 0票数 2

这是我的先前的后续行动的另一个后续,这次我将堆栈和内存分割成字节,以便它更接近大多数机器。正如我在之前的同行评测中所说的,这个虚拟机被设计成作为一个静态库嵌入到一个C++游戏引擎中。我非常应该说,这个VM将支持C的一个子集作为脚本语言,因此许多操作码所做的工作或多或少都是针对C语言设计的。

我仍然意识到,我不应该使用调度表,因为它是非标准和不可移植的,但我忽略了这一点。

我的问题是: VM是否有足够的特性来支持C编程语言的一个子集?

GitHub (如有必要)

代码语言:javascript
复制
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include <inttypes.h>
#include <stdlib.h>


/*  here's the deal ok? make an opcode for each and erry n-bytes!
 * 'l' - int32
 * 's' - int16
 * 'b' - byte | push and pop do not take bytes
 * 'f' - float32
*/

#define INSTR_SET   \
    X(halt) \
    X(pushl) X(pushs) X(pushb) X(pushsp) X(puship)\
    X(popl) X(pops) X(popb) \
    X(wrtl) X(wrts) X(wrtb) \
    X(storel) X(stores) X(storeb) \
    X(loadl) X(loads) X(loadb) \
    X(copyl) X(copys) X(copyb) \
    X(addl) X(uaddl) X(addf) X(subl) X(usubl) X(subf) \
    X(mull) X(umull) X(mulf) X(divl) X(udivl) X(divf) X(modl) X(umodl)\
    X(andl) X(orl) X(xorl) X(notl) X(shl) X(shr) X(incl) X(decl) \
    X(ltl) X(ultl) X(ltf) X(gtl) X(ugtl) X(gtf) X(cmpl) X(ucmpl) X(compf) \
    X(leql) X(uleql) X(leqf) X(geql) X(ugeql) X(geqf) \
    X(jmp) X(jzl) X(jzs) X(jzb) X(jnzl) X(jnzs) X(jnzb) \
    X(call) X(ret) \
    X(nop) \

#define X(x) x,
enum InstrSet{ INSTR_SET };
#undef X

#define X(x) #x ,
const char *opcode2str[] = { INSTR_SET };
#undef X

#define WORD_SIZE       4
#define STK_SIZE        1024*WORD_SIZE  // 4096 4Kb
#define CALLSTK_SIZE    256             // 1024 bytes
#define MEM_SIZE        256*WORD_SIZE   // 1024 bytes

// 'b' for Byte, not bool
struct vm_cpu {
    uint8_t     bStack[STK_SIZE];           // 4096 bytes
    uint32_t    bCallstack[CALLSTK_SIZE];   // 1024 bytes
    uint8_t     bMemory[MEM_SIZE];          // 1024 bytes
    uint32_t    ip, sp, callsp, callbp;     // 16 bytes
};

void debug_print_memory(const struct vm_cpu *restrict vm)
{
    if( !vm )
        return;
    printf("DEBUG ...---===---... Printing Memory...\n");
    uint32_t i;
    for( i=0 ; i<MEM_SIZE ; i++ )
        if( vm->bMemory[i] )
            printf("Memory Index: 0x%x | data: %u\n", i, vm->bMemory[i]);
    printf("\n");
}
void debug_print_stack(const struct vm_cpu *restrict vm)
{
    if( !vm )
        return;
    printf("DEBUG ...---===---... Printing Stack...\n");
    uint32_t i;
    for( i=0 ; i<STK_SIZE ; i++ )
        if( vm->bStack[i] )
            printf("Stack Index: 0x%x | data: %u\n", i, vm->bStack[i]);
    printf("\n");
}
void debug_print_callstack(const struct vm_cpu *restrict vm)
{
    if( !vm )
        return;
    printf("DEBUG ...---===---... Printing Call Stack...\n");
    uint32_t i;
    for( i=0 ; i<CALLSTK_SIZE ; i++ )
        if( vm->bCallstack[i] )
            printf("Call Stack Index: 0x%x | data: %u\n", i, vm->bCallstack[i]);
    printf("\n");
}
void debug_print_ptrs(const struct vm_cpu *restrict vm)
{
    if( !vm )
        return;
    printf("DEBUG ...---===---... Printing Pointers...\n");
    printf("Instruction Pointer: %u\
            \nStack Pointer: %u\
            \nCall Stack Pointer: %u\
            \nCall Stack Frame Pointer: %u\n", vm->ip, vm->sp, vm->callsp, vm->callbp);
    printf("\n");
}

//#include <unistd.h>   // sleep() func
void vm_exec(const uint8_t *code, struct vm_cpu *const vm)
{
    union {
        uint32_t ui;
        int32_t i;
        float f;
        uint16_t us;
        int16_t s;
        uint8_t c[4];
    } conv;
    uint32_t b, a;
    float fa, fb;
    uint16_t usa, usb;

#define X(x) &&exec_##x ,
    static const void *dispatch[] = { INSTR_SET };
#undef INSTR_SET

    if( code[vm->ip] > nop) {
        printf("illegal instruction exception! instruction == \'%" PRIu8 "\' @ %u\n", code[vm->ip], vm->ip);
        goto *dispatch[halt];
        return;
    }
    //printf( "current instruction == \"%s\" @ ip == %u\n", opcode2str[code[vm->ip]], vm->ip );
#ifdef _UNISTD_H
    #define DISPATCH()  sleep(1); goto *dispatch[ code[++vm->ip] ]
#else
    #define DISPATCH()  goto *dispatch[ code[++vm->ip] ]
#endif
    goto *dispatch[ code[vm->ip] ];

exec_nop:;
    DISPATCH();
exec_halt:;
    printf("===================== vm done\n");
    return;

// opcodes for longs
exec_pushl:;    // push 4 bytes onto the stack
    conv.c[0] = code[++vm->ip];
    conv.c[1] = code[++vm->ip];
    conv.c[2] = code[++vm->ip];
    conv.c[3] = code[++vm->ip];
    vm->bStack[++vm->sp] = conv.c[0];
    vm->bStack[++vm->sp] = conv.c[1];
    vm->bStack[++vm->sp] = conv.c[2];
    vm->bStack[++vm->sp] = conv.c[3];
    printf("pushl: pushed %u\n", conv.ui);
    DISPATCH();
exec_pushs:;    // push 2 bytes onto the stack
    conv.c[0] = code[++vm->ip];
    conv.c[1] = code[++vm->ip];
    vm->bStack[++vm->sp] = conv.c[0];
    vm->bStack[++vm->sp] = conv.c[1];
    printf("pushs: pushed %u\n", conv.us);
    DISPATCH();
exec_pushb:;    // push a byte onto the stack
    vm->bStack[++vm->sp] = code[++vm->ip];
    printf("pushb: pushed %u\n", vm->bStack[vm->sp]);
    DISPATCH();
exec_pushsp:;   // push sp onto the stack, uses 4 bytes since 'sp' is uint32
    conv.ui = vm->sp;
    vm->bStack[++vm->sp] = conv.c[0];
    vm->bStack[++vm->sp] = conv.c[1];
    vm->bStack[++vm->sp] = conv.c[2];
    vm->bStack[++vm->sp] = conv.c[3];
    printf("pushsp: pushed sp index: %u\n", conv.ui);
    DISPATCH();
exec_puship:;
    conv.ui = vm->ip;
    vm->bStack[++vm->sp] = conv.c[0];
    vm->bStack[++vm->sp] = conv.c[1];
    vm->bStack[++vm->sp] = conv.c[2];
    vm->bStack[++vm->sp] = conv.c[3];
    printf("puship: pushed ip index: %u\n", conv.ui);
    DISPATCH();
exec_popl:;     // pop 4 bytes to eventually be overwritten
    vm->sp -= 4;
    printf("popl\n");
    DISPATCH();
exec_pops:;     // pop 2 bytes
    vm->sp -= 2;
    printf("pops\n");
    DISPATCH();
exec_popb:;     // pop a byte
    --vm->sp;
    printf("popb\n");
    DISPATCH();
exec_wrtl:; // writes an int to memory, First operand is the memory address as 4 byte number, second is the int of data.
    conv.c[0] = code[++vm->ip];
    conv.c[1] = code[++vm->ip];
    conv.c[2] = code[++vm->ip];
    conv.c[3] = code[++vm->ip];
    a = conv.ui;
    vm->bMemory[a] = code[++vm->ip];
    vm->bMemory[a+1] = code[++vm->ip];
    vm->bMemory[a+2] = code[++vm->ip];
    vm->bMemory[a+3] = code[++vm->ip];
    conv.c[0] = vm->bMemory[a];
    conv.c[1] = vm->bMemory[a+1];
    conv.c[2] = vm->bMemory[a+2];
    conv.c[3] = vm->bMemory[a+3];
    printf("wrote int data - %u @ address 0x%x\n", conv.ui, a);
    DISPATCH();
exec_wrts:; // writes a short to memory. First operand is the memory address as 4 byte number, second is the short of data.
    conv.c[0] = code[++vm->ip];
    conv.c[1] = code[++vm->ip];
    conv.c[2] = code[++vm->ip];
    conv.c[3] = code[++vm->ip];
    a = conv.ui;
    vm->bMemory[a] = code[++vm->ip];
    vm->bMemory[a+1] = code[++vm->ip];
    conv.c[0] = vm->bMemory[a];
    conv.c[1] = vm->bMemory[a+1];
    printf("wrote short data - %u @ address 0x%x\n", conv.us, a);
    DISPATCH();
exec_wrtb:; // writes a byte to memory. First operand is the memory address as 32-bit number, second is the byte of data.
    conv.c[0] = code[++vm->ip];
    conv.c[1] = code[++vm->ip];
    conv.c[2] = code[++vm->ip];
    conv.c[3] = code[++vm->ip];
    vm->bMemory[conv.ui] = code[++vm->ip];
    printf("wrote byte data - %u @ address 0x%x\n", vm->bMemory[conv.ui], conv.ui);
    DISPATCH();
exec_storel:;   // pops 4-byte value off stack and into a memory address.
    conv.c[0] = code[++vm->ip];
    conv.c[1] = code[++vm->ip];
    conv.c[2] = code[++vm->ip];
    conv.c[3] = code[++vm->ip];
    a = conv.ui;
    vm->bMemory[a+3] = vm->bStack[vm->sp--];
    vm->bMemory[a+2] = vm->bStack[vm->sp--];
    vm->bMemory[a+1] = vm->bStack[vm->sp--];
    vm->bMemory[a] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bMemory[a];
    conv.c[1] = vm->bMemory[a+1];
    conv.c[2] = vm->bMemory[a+2];
    conv.c[3] = vm->bMemory[a+3];
    printf("stored int data - %u @ address 0x%x\n", conv.ui, a);
    DISPATCH();
exec_stores:;   // pops 2-byte value off stack and into a memory address.
    conv.c[0] = code[++vm->ip];
    conv.c[1] = code[++vm->ip];
    conv.c[2] = code[++vm->ip];
    conv.c[3] = code[++vm->ip];
    a = conv.ui;
    vm->bMemory[a+1] = vm->bStack[vm->sp--];
    vm->bMemory[a] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bMemory[a];
    conv.c[1] = vm->bMemory[a+1];
    printf("stored short data - %u @ address 0x%x\n", conv.us, a);
    DISPATCH();
exec_storeb:;   // pops byte value off stack and into a memory address.
    conv.c[0] = code[++vm->ip];
    conv.c[1] = code[++vm->ip];
    conv.c[2] = code[++vm->ip];
    conv.c[3] = code[++vm->ip];
    a = conv.ui;
    vm->bMemory[a] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bMemory[a];
    printf("stored byte data - %u @ address 0x%x\n", conv.c[0], a);
    DISPATCH();
exec_loadl:;
    conv.c[0] = code[++vm->ip];
    conv.c[1] = code[++vm->ip];
    conv.c[2] = code[++vm->ip];
    conv.c[3] = code[++vm->ip];
    a = conv.ui;
    conv.c[0] = vm->bStack[++vm->sp] = vm->bMemory[a];
    conv.c[1] = vm->bStack[++vm->sp] = vm->bMemory[a+1];
    conv.c[2] = vm->bStack[++vm->sp] = vm->bMemory[a+2];
    conv.c[3] = vm->bStack[++vm->sp] = vm->bMemory[a+3];
    printf("loaded int data to T.O.S. - %u from address 0x%x\n", conv.ui, a);
    DISPATCH();
exec_loads:;
    conv.c[0] = code[++vm->ip];
    conv.c[1] = code[++vm->ip];
    conv.c[2] = code[++vm->ip];
    conv.c[3] = code[++vm->ip];
    a = conv.ui;
    conv.c[1] = vm->bStack[++vm->sp] = vm->bMemory[a];
    conv.c[0] = vm->bStack[++vm->sp] = vm->bMemory[a+1];
    printf("loaded short data to T.O.S. - %u from address 0x%x\n", conv.us, a);
    DISPATCH();
exec_loadb:;
    conv.c[0] = code[++vm->ip];
    conv.c[1] = code[++vm->ip];
    conv.c[2] = code[++vm->ip];
    conv.c[3] = code[++vm->ip];
    a = conv.ui;
    vm->bStack[++vm->sp] = vm->bMemory[a];
    printf("loaded byte data to T.O.S. - %u from address 0x%x\n", vm->bStack[vm->sp], a);
    DISPATCH();
exec_copyl:;    // copy 4 bytes of top of stack and put as new top of stack.
    conv.c[0] = vm->bStack[vm->sp-3];
    conv.c[1] = vm->bStack[vm->sp-2];
    conv.c[2] = vm->bStack[vm->sp-1];
    conv.c[3] = vm->bStack[vm->sp];
    printf("copied int data from T.O.S. - %u\n", conv.ui);
    vm->bStack[++vm->sp] = conv.c[0];
    vm->bStack[++vm->sp] = conv.c[1];
    vm->bStack[++vm->sp] = conv.c[2];
    vm->bStack[++vm->sp] = conv.c[3];
    DISPATCH();
exec_copys:;
    conv.c[0] = vm->bStack[vm->sp-1];
    conv.c[1] = vm->bStack[vm->sp];
    vm->bStack[++vm->sp] = conv.c[0];
    vm->bStack[++vm->sp] = conv.c[1];
    printf("copied short data from T.O.S. - %u\n", conv.us);
    DISPATCH();
exec_copyb:;
    conv.c[0] = vm->bStack[vm->sp];
    vm->bStack[++vm->sp] = conv.c[0];
    printf("copied byte data from T.O.S. - %u\n", conv.c[0]);
    DISPATCH();
exec_addl:;     // pop 8 bytes, signed addition, and push 4 byte result to top of stack
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    b=conv.ui;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    a=conv.ui;
    conv.i = (int32_t)a + (int32_t)b;
    printf("signed 4 byte addition result: %i == %i + %i\n", conv.ui, a,b);
    vm->bStack[++vm->sp] = conv.c[0];
    vm->bStack[++vm->sp] = conv.c[1];
    vm->bStack[++vm->sp] = conv.c[2];
    vm->bStack[++vm->sp] = conv.c[3];
    DISPATCH();
exec_uaddl:;    // In C, all integers in an expression are promoted to int32, if number is bigger then unsigned int32 or int64
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    b=conv.ui;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    a=conv.ui;
    conv.ui = a+b;
    printf("unsigned 4 byte addition result: %u == %u + %u\n", conv.ui, a,b);
    vm->bStack[++vm->sp] = conv.c[0];
    vm->bStack[++vm->sp] = conv.c[1];
    vm->bStack[++vm->sp] = conv.c[2];
    vm->bStack[++vm->sp] = conv.c[3];
    DISPATCH();
exec_addf:;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    fb=conv.f;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    fa=conv.f;
    conv.f = fa+fb;
    printf("float addition result: %f == %f + %f\n", conv.f, fa,fb);
    vm->bStack[++vm->sp] = conv.c[0];
    vm->bStack[++vm->sp] = conv.c[1];
    vm->bStack[++vm->sp] = conv.c[2];
    vm->bStack[++vm->sp] = conv.c[3];
    DISPATCH();
exec_subl:;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    b=conv.ui;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    a=conv.ui;
    conv.i = (int32_t)a - (int32_t)b;
    printf("signed 4 byte subtraction result: %i == %i - %i\n", conv.ui, a,b);
    vm->bStack[++vm->sp] = conv.c[0];
    vm->bStack[++vm->sp] = conv.c[1];
    vm->bStack[++vm->sp] = conv.c[2];
    vm->bStack[++vm->sp] = conv.c[3];
    DISPATCH();
exec_usubl:;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    b=conv.ui;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    a=conv.ui;
    conv.ui = a-b;
    printf("unsigned 4 byte subtraction result: %u == %u - %u\n", conv.ui, a,b);
    vm->bStack[++vm->sp] = conv.c[0];
    vm->bStack[++vm->sp] = conv.c[1];
    vm->bStack[++vm->sp] = conv.c[2];
    vm->bStack[++vm->sp] = conv.c[3];
    DISPATCH();
exec_subf:;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    fb=conv.f;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    fa=conv.f;
    conv.f = fa-fb;
    printf("float subtraction result: %f == %f - %f\n", conv.f, fa,fb);
    vm->bStack[++vm->sp] = conv.c[0];
    vm->bStack[++vm->sp] = conv.c[1];
    vm->bStack[++vm->sp] = conv.c[2];
    vm->bStack[++vm->sp] = conv.c[3];
    DISPATCH();
exec_mull:;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    b=conv.ui;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    a=conv.ui;
    conv.i = (int32_t)a * (int32_t)b;
    printf("signed 4 byte mult result: %i == %i * %i\n", conv.i, a,b);
    vm->bStack[++vm->sp] = conv.c[0];
    vm->bStack[++vm->sp] = conv.c[1];
    vm->bStack[++vm->sp] = conv.c[2];
    vm->bStack[++vm->sp] = conv.c[3];
    DISPATCH();
exec_umull:;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    b=conv.ui;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    a=conv.ui;
    conv.ui = a*b;
    printf("unsigned 4 byte mult result: %u == %u * %u\n", conv.ui, a,b);
    vm->bStack[++vm->sp] = conv.c[0];
    vm->bStack[++vm->sp] = conv.c[1];
    vm->bStack[++vm->sp] = conv.c[2];
    vm->bStack[++vm->sp] = conv.c[3];
    DISPATCH();
exec_mulf:;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    fb=conv.f;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    fa=conv.f;
    conv.f = fa*fb;
    printf("float mul result: %f == %f * %f\n", conv.f, fa,fb);
    vm->bStack[++vm->sp] = conv.c[0];
    vm->bStack[++vm->sp] = conv.c[1];
    vm->bStack[++vm->sp] = conv.c[2];
    vm->bStack[++vm->sp] = conv.c[3];
    DISPATCH();
exec_divl:;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    b=conv.ui;
    if( !b ) {
        printf("divl: divide by 0 error.\n");
        goto *dispatch[halt];
    }
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    a=conv.ui;
    conv.i = (int32_t)a / (int32_t)b;
    printf("signed 4 byte division result: %i == %i / %i\n", conv.i, a,b);
    vm->bStack[++vm->sp] = conv.c[0];
    vm->bStack[++vm->sp] = conv.c[1];
    vm->bStack[++vm->sp] = conv.c[2];
    vm->bStack[++vm->sp] = conv.c[3];
    DISPATCH();
exec_udivl:;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    b=conv.ui;
    if( !b ) {
        printf("udivl: divide by 0 error.\n");
        goto *dispatch[halt];
    }
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    a=conv.ui;
    conv.ui = a/b;
    printf("unsigned 4 byte division result: %u == %u / %u\n", conv.ui, a,b);
    vm->bStack[++vm->sp] = conv.c[0];
    vm->bStack[++vm->sp] = conv.c[1];
    vm->bStack[++vm->sp] = conv.c[2];
    vm->bStack[++vm->sp] = conv.c[3];
    DISPATCH();
exec_divf:;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    fb=conv.f;
    if( !fb ) {
        printf("divf: divide by 0.0 error.\n");
        goto *dispatch[halt];
    }
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    fa=conv.f;
    conv.f = fa/fb;
    printf("float division result: %f == %f / %f\n", conv.f, fa,fb);
    vm->bStack[++vm->sp] = conv.c[0];
    vm->bStack[++vm->sp] = conv.c[1];
    vm->bStack[++vm->sp] = conv.c[2];
    vm->bStack[++vm->sp] = conv.c[3];
    DISPATCH();
exec_modl:;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    b=conv.ui;
    if( !b ) {
        printf("modl: divide by 0 error.\n");
        goto *dispatch[halt];
    }
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    a=conv.ui;
    conv.i = (int32_t)a % (int32_t)b;
    printf("signed 4 byte modulo result: %i == %i %% %i\n", conv.i, a,b);
    vm->bStack[++vm->sp] = conv.c[0];
    vm->bStack[++vm->sp] = conv.c[1];
    vm->bStack[++vm->sp] = conv.c[2];
    vm->bStack[++vm->sp] = conv.c[3];
    DISPATCH();
exec_umodl:;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    b=conv.ui;
    if( !b ) {
        printf("umodl: divide by 0 error.\n");
        goto *dispatch[halt];
    }
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    a=conv.ui;
    conv.ui = a%b;
    printf("unsigned 4 byte modulo result: %u == %u %% %u\n", conv.ui, a,b);
    vm->bStack[++vm->sp] = conv.c[0];
    vm->bStack[++vm->sp] = conv.c[1];
    vm->bStack[++vm->sp] = conv.c[2];
    vm->bStack[++vm->sp] = conv.c[3];
    DISPATCH();
exec_andl:;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    b=conv.ui;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    a=conv.ui;
    conv.ui = a & b;
    printf("4 byte AND result: %u == %i & %i\n", conv.ui, a,b);
    vm->bStack[++vm->sp] = conv.c[0];
    vm->bStack[++vm->sp] = conv.c[1];
    vm->bStack[++vm->sp] = conv.c[2];
    vm->bStack[++vm->sp] = conv.c[3];
    DISPATCH();
exec_orl:;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    b=conv.ui;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    a=conv.ui;
    conv.ui = a | b;
    printf("4 byte OR result: %u == %i | %i\n", conv.ui, a,b);
    vm->bStack[++vm->sp] = conv.c[0];
    vm->bStack[++vm->sp] = conv.c[1];
    vm->bStack[++vm->sp] = conv.c[2];
    vm->bStack[++vm->sp] = conv.c[3];
    DISPATCH();
exec_xorl:;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    b=conv.ui;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    a=conv.ui;
    conv.ui = a ^ b;
    printf("4 byte XOR result: %u == %i ^ %i\n", conv.ui, a,b);
    vm->bStack[++vm->sp] = conv.c[0];
    vm->bStack[++vm->sp] = conv.c[1];
    vm->bStack[++vm->sp] = conv.c[2];
    vm->bStack[++vm->sp] = conv.c[3];
    DISPATCH();
exec_notl:;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    a=conv.ui;
    conv.ui = ~a;
    printf("4 byte NOT result: %u\n", conv.ui);
    vm->bStack[++vm->sp] = conv.c[0];
    vm->bStack[++vm->sp] = conv.c[1];
    vm->bStack[++vm->sp] = conv.c[2];
    vm->bStack[++vm->sp] = conv.c[3];
    DISPATCH();
exec_shl:;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    b=conv.ui;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    a=conv.ui;
    conv.ui = a << b;
    printf("4 byte Shift Left result: %u == %i >> %i\n", conv.ui, a,b);
    vm->bStack[++vm->sp] = conv.c[0];
    vm->bStack[++vm->sp] = conv.c[1];
    vm->bStack[++vm->sp] = conv.c[2];
    vm->bStack[++vm->sp] = conv.c[3];
    DISPATCH();
exec_shr:;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    b=conv.ui;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    a=conv.ui;
    conv.ui = a >> b;
    printf("4 byte Shift Right result: %u == %i >> %i\n", conv.ui, a,b);
    vm->bStack[++vm->sp] = conv.c[0];
    vm->bStack[++vm->sp] = conv.c[1];
    vm->bStack[++vm->sp] = conv.c[2];
    vm->bStack[++vm->sp] = conv.c[3];
    DISPATCH();
exec_incl:;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    a=conv.ui;
    conv.ui = ++a;
    printf("4 byte Increment result: %u\n", conv.ui);
    vm->bStack[++vm->sp] = conv.c[0];
    vm->bStack[++vm->sp] = conv.c[1];
    vm->bStack[++vm->sp] = conv.c[2];
    vm->bStack[++vm->sp] = conv.c[3];
    DISPATCH();
exec_decl:;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    a=conv.ui;
    conv.ui = --a;
    printf("4 byte Decrement result: %u\n", conv.ui);
    vm->bStack[++vm->sp] = conv.c[0];
    vm->bStack[++vm->sp] = conv.c[1];
    vm->bStack[++vm->sp] = conv.c[2];
    vm->bStack[++vm->sp] = conv.c[3];
    DISPATCH();
exec_ltl:;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    b=conv.ui;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    a=conv.ui;
    conv.ui = (int32_t)a < (int32_t)b;
    printf("4 byte Signed Less Than result: %u == %i < %i\n", conv.ui, a,b);
    vm->bStack[++vm->sp] = conv.c[0];
    vm->bStack[++vm->sp] = conv.c[1];
    vm->bStack[++vm->sp] = conv.c[2];
    vm->bStack[++vm->sp] = conv.c[3];
    DISPATCH();
exec_ultl:;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    b=conv.ui;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    a=conv.ui;
    conv.ui = a < b;
    printf("4 byte Unsigned Less Than result: %u == %u < %u\n", conv.ui, a,b);
    vm->bStack[++vm->sp] = conv.c[0];
    vm->bStack[++vm->sp] = conv.c[1];
    vm->bStack[++vm->sp] = conv.c[2];
    vm->bStack[++vm->sp] = conv.c[3];
    DISPATCH();
exec_ltf:;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    fb=conv.f;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    fa=conv.f;
    conv.ui = fa < fb;
    printf("4 byte Less Than Float result: %u == %f < %f\n", conv.ui, fa,fb);
    vm->bStack[++vm->sp] = conv.c[0];
    vm->bStack[++vm->sp] = conv.c[1];
    vm->bStack[++vm->sp] = conv.c[2];
    vm->bStack[++vm->sp] = conv.c[3];
    DISPATCH();
exec_gtl:;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    b=conv.ui;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    a=conv.ui;
    conv.ui = (int32_t)a > (int32_t)b;
    printf("4 byte Signed Greater Than result: %u == %i > %i\n", conv.ui, a,b);
    vm->bStack[++vm->sp] = conv.c[0];
    vm->bStack[++vm->sp] = conv.c[1];
    vm->bStack[++vm->sp] = conv.c[2];
    vm->bStack[++vm->sp] = conv.c[3];
    DISPATCH();
exec_ugtl:;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    b=conv.ui;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    a=conv.ui;
    conv.ui = a > b;
    printf("4 byte Signed Greater Than result: %u == %u > %u\n", conv.ui, a,b);
    vm->bStack[++vm->sp] = conv.c[0];
    vm->bStack[++vm->sp] = conv.c[1];
    vm->bStack[++vm->sp] = conv.c[2];
    vm->bStack[++vm->sp] = conv.c[3];
    DISPATCH();
exec_gtf:;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    fb=conv.f;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    fa=conv.f;
    conv.ui = fa > fb;
    printf("4 byte Greater Than Float result: %u == %f > %f\n", conv.ui, fa,fb);
    vm->bStack[++vm->sp] = conv.c[0];
    vm->bStack[++vm->sp] = conv.c[1];
    vm->bStack[++vm->sp] = conv.c[2];
    vm->bStack[++vm->sp] = conv.c[3];
    DISPATCH();
exec_cmpl:;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    b=conv.ui;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    a=conv.ui;
    conv.ui = (int32_t)a == (int32_t)b;
    printf("4 byte Signed Compare result: %u == %i == %i\n", conv.ui, a,b);
    vm->bStack[++vm->sp] = conv.c[0];
    vm->bStack[++vm->sp] = conv.c[1];
    vm->bStack[++vm->sp] = conv.c[2];
    vm->bStack[++vm->sp] = conv.c[3];
    DISPATCH();
exec_ucmpl:;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    b=conv.ui;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    a=conv.ui;
    conv.ui = a == b;
    printf("4 byte Unsigned Compare result: %u == %u == %u\n", conv.ui, a,b);
    vm->bStack[++vm->sp] = conv.c[0];
    vm->bStack[++vm->sp] = conv.c[1];
    vm->bStack[++vm->sp] = conv.c[2];
    vm->bStack[++vm->sp] = conv.c[3];
    DISPATCH();
exec_compf:;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    fb=conv.f;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    fa=conv.f;
    conv.ui = fa == fb;
    printf("4 byte Compare Float result: %u == %f == %f\n", conv.ui, fa,fb);
    vm->bStack[++vm->sp] = conv.c[0];
    vm->bStack[++vm->sp] = conv.c[1];
    vm->bStack[++vm->sp] = conv.c[2];
    vm->bStack[++vm->sp] = conv.c[3];
    DISPATCH();
exec_leql:;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    b=conv.ui;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    a=conv.ui;
    conv.ui = (int32_t)a <= (int32_t)b;
    printf("4 byte Signed Less Equal result: %u == %i <= %i\n", conv.ui, a,b);
    vm->bStack[++vm->sp] = conv.c[0];
    vm->bStack[++vm->sp] = conv.c[1];
    vm->bStack[++vm->sp] = conv.c[2];
    vm->bStack[++vm->sp] = conv.c[3];
    DISPATCH();
exec_uleql:;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    b=conv.ui;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    a=conv.ui;
    conv.ui = a <= b;
    printf("4 byte Unsigned Less Equal result: %u == %u <= %u\n", conv.ui, a,b);
    vm->bStack[++vm->sp] = conv.c[0];
    vm->bStack[++vm->sp] = conv.c[1];
    vm->bStack[++vm->sp] = conv.c[2];
    vm->bStack[++vm->sp] = conv.c[3];
    DISPATCH();
exec_leqf:;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    fb=conv.f;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    fa=conv.f;
    conv.ui = fa <= fb;
    printf("4 byte Less Equal Float result: %u == %f <= %f\n", conv.ui, fa, fb);
    vm->bStack[++vm->sp] = conv.c[0];
    vm->bStack[++vm->sp] = conv.c[1];
    vm->bStack[++vm->sp] = conv.c[2];
    vm->bStack[++vm->sp] = conv.c[3];
    DISPATCH();
exec_geql:;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    b=conv.ui;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    a=conv.ui;
    conv.ui = (int32_t)a >= (int32_t)b;
    printf("4 byte Signed Greater Equal result: %u == %i >= %i\n", conv.ui, a,b);
    vm->bStack[++vm->sp] = conv.c[0];
    vm->bStack[++vm->sp] = conv.c[1];
    vm->bStack[++vm->sp] = conv.c[2];
    vm->bStack[++vm->sp] = conv.c[3];
    DISPATCH();
exec_ugeql:;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    b=conv.ui;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    a=conv.ui;
    conv.ui = a >= b;
    printf("4 byte Unsigned Greater Equal result: %u == %u >= %u\n", conv.ui, a,b);
    vm->bStack[++vm->sp] = conv.c[0];
    vm->bStack[++vm->sp] = conv.c[1];
    vm->bStack[++vm->sp] = conv.c[2];
    vm->bStack[++vm->sp] = conv.c[3];
    DISPATCH();
exec_geqf:;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    fb=conv.f;
    conv.c[3] = vm->bStack[vm->sp--];
    conv.c[2] = vm->bStack[vm->sp--];
    conv.c[1] = vm->bStack[vm->sp--];
    conv.c[0] = vm->bStack[vm->sp--];
    fa=conv.f;
    conv.ui = fa >= fb;
    printf("4 byte Greater Equal Float result: %u == %f >= %f\n", conv.ui, fa, fb);
    vm->bStack[++vm->sp] = conv.c[0];
    vm->bStack[++vm->sp] = conv.c[1];
    vm->bStack[++vm->sp] = conv.c[2];
    vm->bStack[++vm->sp] = conv.c[3];
    DISPATCH();
exec_jmp:;  // addresses are 4 bytes.
    conv.c[0] = code[++vm->ip];
    conv.c[1] = code[++vm->ip];
    conv.c[2] = code[++vm->ip];
    conv.c[3] = code[++vm->ip];
    vm->ip = conv.ui;
    printf("jmping to instruction address: %u\n", vm->ip);
    goto *dispatch[ code[vm->ip] ];
exec_jzl:;  // check if the first 4 bytes on stack are zero, if yes then jump it.
    conv.c[3] = vm->bStack[vm->sp];
    conv.c[2] = vm->bStack[vm->sp-1];
    conv.c[1] = vm->bStack[vm->sp-2];
    conv.c[0] = vm->bStack[vm->sp-3];
    a = conv.ui;
    conv.c[0] = code[++vm->ip];
    conv.c[1] = code[++vm->ip];
    conv.c[2] = code[++vm->ip];
    conv.c[3] = code[++vm->ip];
    vm->ip = (!a) ? conv.ui : vm->ip+1 ;
    printf("jzl'ing to instruction address: %u\n", vm->ip);
    goto *dispatch[ code[vm->ip] ];
exec_jzs:;
    conv.c[1] = vm->bStack[vm->sp];
    conv.c[0] = vm->bStack[vm->sp-1];
    a = conv.ui;
    conv.c[0] = code[++vm->ip];
    conv.c[1] = code[++vm->ip];
    conv.c[2] = code[++vm->ip];
    conv.c[3] = code[++vm->ip];
    vm->ip = (!a) ? conv.ui : vm->ip+1 ;
    printf("jzs'ing to instruction address: %u\n", vm->ip);
    goto *dispatch[ code[vm->ip] ];
exec_jzb:;
    conv.c[0] = vm->bStack[vm->sp];
    a = conv.ui;
    conv.c[0] = code[++vm->ip];
    conv.c[1] = code[++vm->ip];
    conv.c[2] = code[++vm->ip];
    conv.c[3] = code[++vm->ip];
    vm->ip = (!a) ? conv.ui : vm->ip+1 ;
    printf("jzb'ing to instruction address: %u\n", vm->ip);
    goto *dispatch[ code[vm->ip] ];
exec_jnzl:;
    conv.c[3] = vm->bStack[vm->sp];
    conv.c[2] = vm->bStack[vm->sp-1];
    conv.c[1] = vm->bStack[vm->sp-2];
    conv.c[0] = vm->bStack[vm->sp-3];
    a = conv.ui;
    conv.c[0] = code[++vm->ip];
    conv.c[1] = code[++vm->ip];
    conv.c[2] = code[++vm->ip];
    conv.c[3] = code[++vm->ip];
    vm->ip = (a) ? conv.ui : vm->ip+1 ;
    printf("jnzl'ing to instruction address: %u\n", vm->ip);
    goto *dispatch[ code[vm->ip] ];
exec_jnzs:;
    conv.c[1] = vm->bStack[vm->sp];
    conv.c[0] = vm->bStack[vm->sp-1];
    a = conv.ui;
    conv.c[0] = code[++vm->ip];
    conv.c[1] = code[++vm->ip];
    conv.c[2] = code[++vm->ip];
    conv.c[3] = code[++vm->ip];
    vm->ip = (a) ? conv.ui : vm->ip+1 ;
    printf("jnzs'ing to instruction address: %u\n", vm->ip);
    goto *dispatch[ code[vm->ip] ];
exec_jnzb:;
    conv.c[0] = vm->bStack[vm->sp];
    a = conv.ui;
    conv.c[0] = code[++vm->ip];
    conv.c[1] = code[++vm->ip];
    conv.c[2] = code[++vm->ip];
    conv.c[3] = code[++vm->ip];
    vm->ip = (a) ? conv.ui : vm->ip+1 ;
    printf("jnzb'ing to instruction address: %u\n", vm->ip);
    goto *dispatch[ code[vm->ip] ];
exec_call:;
    vm->ip++;
    printf("calling address: %u\n", vm->ip);
    vm->bCallstack[++vm->callsp] = vm->ip + 1;
    vm->callbp = vm->callsp;
    vm->ip = code[vm->ip];
    printf("call return addr: %u | frame ptr == %u\n", vm->bCallstack[vm->callsp], vm->callbp);
    goto *dispatch[ code[vm->ip] ];
exec_ret:;
    vm->callsp = vm->callbp;
    printf("callsp set to callbp, callsp == %u\n", vm->callsp);
    vm->ip = vm->bCallstack[vm->callsp--];
    vm->callbp = vm->callsp;
    printf("returning to address: %u\n", vm->ip);
    goto *dispatch[ code[vm->ip] ];
}

uint64_t get_file_size(FILE *pFile)
{
    uint64_t size = 0;
    if( !pFile )
        return size;

    if( !fseek(pFile, 0, SEEK_END) ) {
        size = (uint64_t)ftell(pFile);
        rewind(pFile);
    }
    return size;
}

int main(void)
{
    typedef uint8_t     bytecode[] ;

    /*
    FILE *pFile = fopen("./myfile.cbyte", "rb");
    if( !pFile )
        return 0;

    uint64_t size = get_file_size(pFile);
    uint8_t *program = malloc(sizeof(uint8_t)*size);
    fread(program, sizeof(uint8_t), size, pFile);
    */
    const bytecode test1 = {
        nop,
        //pushl, 255, 1, 0, 0x0,
        //pushs, 0xDD, 0xDD,
        pushb, 0xAA,
        //pushs, 0x0D, 0x0C,
        //pops, popl,
        //wrtl, 4,0,0,0, 0xFF,0xFF,0,0,
        //storeb, 0,0,0,0,
        //stores, 1,0,0,0,
        //storel, 4,0,0,0,
        //loadb, 4,0,0,0,
        //storel, 0,0,0,0,
        //loadl, 0,0,0,0,
        //pushsp, puship, copyl, copys, copyb,
        halt
    };
    const bytecode test2 = {
        nop,
        //jmp, 17,0,0,0,
        // -16776961
        //pushl, 255,0,0,255,
        //pushl, 1,0,0,0,
        // -855637761
        //pushl, 255,0,0,205,
        //pushl, 255,255,0,0,
        //uaddl,
        // 10.f in 4 bytes form
        pushl, 0,0,32,65,
        jzb, 17,0,0,0,
        // 2.f in 4 bytes form
        pushl, 0,0,0,64,
        addf,   // 12.f
        //leqf,
        halt
    };
    const bytecode test3 = {
        nop,
        call, 7,0,0,0,  // 1
        halt,           // 6
    // func1:
        pushl, 9,0,0,0, // 7
        call, 18,0,0,0, // 12
        ret,    // 17
    // func2:
        pushl, 5,0,0,0, // 18
        pushl, 10,0,0,0,    // 23
        mull,   // 28
        mull,
        call, 36,0,0,0, // 30
        ret,    
    // func3:
        pushl, 40,0,0,0,    // 36
        divl,   // 41
        ret,
    };
    struct vm_cpu *p_vm = malloc( sizeof(struct vm_cpu) ); //&(struct vm_cpu){ 0 };
    if( p_vm ) { //printf("size == %u\n", sizeof(struct vm_cpu));
        vm_exec( test3, p_vm );
        debug_print_memory(p_vm);
        debug_print_stack(p_vm);
        //debug_print_callstack(p_vm);
        //debug_print_ptrs(p_vm);
        free(p_vm);
    }
    p_vm=NULL;
    /*
    fclose(pFile); pFile=NULL;
    free(program); program=NULL;
    */
    return 0;
}
EN

回答 1

Code Review用户

发布于 2017-07-07 15:41:51

我看到了一些可以帮助你改进你的程序的东西。

不要使用标签

的地址

标准不支持使用标签的地址,据我所知,这完全是gcc的一个特性。除了这是一个非标准的扩展,它也不是一个很好的方式来表达你想要做的事情。请看下一个更好的建议。

在适当的地方使用switch (

)

对于exec来说,一种更为直接、高效和可移植的方法是使用switch而不是goto。下一个建议中显示了另一种组织事物的方法。

使用适当的数据结构

每条指令都有一个操作码(指定的号码)、一个名称(如"pushl")和执行该操作的相关代码。这些可以很好地被放入这样一个连贯的结构中:

代码语言:javascript
复制
static const struct {
    char *name;
    bool (*evaluate)(struct vm_cpu *);
} Instruction[] = {
    X(halt), X(pushl),   // ...
    X(nop),
};
static const int inst_count = sizeof(Instruction)/sizeof(Instruction[0]);

标签不是

语句

标签不是语句,不需要终止分号。

使用可移植常量打印

在您的机器上,%llu很可能是打印uint64_t的正确printf格式,但在我的64位计算机上,它将是%lu。不必猜测,只需使用<intypes.h>中定义的常量并按如下方式执行:

代码语言:javascript
复制
printf("loaded %" PRIu64 " from reg[%" PRIu64 "]\n", stack[sp], a);

消除了实际

中的全局变量

拥有依赖于全局变量的例程使得理解逻辑变得更加困难,并引入了许多错误的机会。在实用的地方消除全局变量总是一个好主意。在这种情况下,如果像前面的建议那样将所有相关值包装到struct中,那么可以将指向struct的指针传递给exec。这有许多好处,包括能够同时运行多个同时运行的虚拟机。

创建重置函数

真正的CPU有一个复位引脚,它将机器设置为一个已知的定义状态。您还可以为虚拟机实现一个重置函数,该函数可以将一切设置为已知的、可预测的状态。

允许用户控制详细的

几乎所有的指令都包含各种类型的打印函数。这可能对调试很有用,但是当试图跟踪一个更大的程序时,它会很烦人。我建议在虚拟机中创建一个“详细”标志,以控制是否打印此类语句。

允许用户控制范围检查

我建议在VM中添加一个布尔标志"safe“。它将打开范围检查(例如堆栈溢出等)。在调试时,如果您想以牺牲安全为代价寻找最大的VM速度,则可以关闭它。我可能会在默认情况下开着它。没有人喜欢崩溃的快速程序。

把它放在一起

下面是一个小示例,展示了其中一些建议的外观:

代码语言:javascript
复制
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>

#define WORD_SIZE       4
#define STK_SIZE        1024*WORD_SIZE  // 4096 4Kb
#define CALLSTK_SIZE    256             // 1024 bytes
#define MEM_SIZE        256*WORD_SIZE   // 1024 bytes

// 'b' for Byte, not bool
struct vm_cpu {
    const uint8_t *code;
    size_t codesize;
    uint8_t bStack[STK_SIZE];            // 4096 bytes
    uint32_t bCallstack[CALLSTK_SIZE];    // 1024 bytes
    uint8_t bMemory[MEM_SIZE];            // 1024 bytes
    uint32_t ip, sp, callsp, callbp;        // 16 bytes
    bool verbose;
    bool safe;
};

uint32_t as_uint32_t(const void *ptr) {
    uint32_t val;
    memcpy(&val, ptr, sizeof(val));
    return val;
}

bool exec_halt(struct vm_cpu *vm) {
    if (vm->verbose) {
        printf("halted at %4.4x\n", vm->ip);
    }
    return false;
}
bool exec_nop(struct vm_cpu *vm) {
    ++vm->ip;
    return true;
}

bool exec_pushl(struct vm_cpu *vm) {
    if (vm->safe) {
        // check pointers
    }
    ++vm->ip;
    memcpy(&vm->bStack[vm->sp], &vm->code[vm->ip], sizeof(uint32_t));
    if (vm->verbose) {
        printf("pushl: pushed %" PRIu32 "\n", as_uint32_t(&vm->code[vm->ip]));
    }
    vm->ip += sizeof(uint32_t);
    vm->sp += sizeof(uint32_t);
    return true;
}

#define X(x) { #x, exec_##x }

static const struct {
    char *name;
    bool (*evaluate)(struct vm_cpu *);
} Instruction[] = {
    X(halt), X(pushl), // ... etc.
    X(nop),
};

static const int inst_count = sizeof(Instruction)/sizeof(Instruction[0]);

void vm_init(struct vm_cpu *vm, const void *code, size_t code_len) {
    vm->code = code;
    vm->codesize = code_len;
    vm->ip = vm->sp = vm->callsp = vm->callbp = 0;
    vm->verbose = true;
    vm->safe = true;
}

void vm_print(struct vm_cpu *vm) {
    printf("sp = %4.4x, ip = %4.4x, next inst = %s\n", 
            vm->sp, vm->ip, Instruction[vm->code[vm->ip]].name
    );
}

bool vm_eval(struct vm_cpu *vm) {
    if (vm->verbose) {
        vm_print(vm);
    }
    return Instruction[vm->code[vm->ip]].evaluate(vm);
}

int main() {
    struct vm_cpu vm;
    static uint8_t code[] = { 
        1, 1, 2, 3, 4,   // pushl 0x04030201
        2,               // nop
        0,               // halt
    };
    size_t code_len = sizeof(code) / sizeof(code[0]);
    vm_init(&vm, code, code_len);
    while (vm_eval(&vm)
    {} // just execute instructions
}

样本输出

代码语言:javascript
复制
sp = 0000, ip = 0000, next inst = pushl
pushl: pushed 67305985
sp = 0004, ip = 0005, next inst = nop
sp = 0004, ip = 0006, next inst = halt
halted at 0006
票数 3
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/167562

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档