Quantcast
Channel: VBForums
Viewing all articles
Browse latest Browse all 16013

Fish VM

$
0
0
hi,
The last few weeks I been reading about virtual machines and how they work as I always wanted to write my own little language. I have read many books on the subject but never really sat down and tried to do something.

So I decided the other day and try and make my own little VM one day I hope to build something I can use to make programs, but for now I am just starting off small and see how things process.

anyway here what I made so far, this VM supports a small instruction set, you can play around with numbers it supports global only variables and that about it. it’s got some examples with this code at the moment they are hardcoded into integer arrays.

In the next updates I am going to introduce an assembler to convert a more human readable form of language into binary code or also known as byte code Then have the VM execute it.

anyway I hope you like what I done and hope it will help someone. Comments are more than welcome or if you can think of improvements I can make drop me a line.

You will need GCC to compile the code, but I think it should also work in Visual Studio since it just basic C code.

Code:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

#define MAX_STACK 1000
#define MAX_GLOBAL 1000
#define MAX_CODE 65536

//Program counter
int pc = 0;
//Stack pointer always points to the top of the stack.
int sp =-1;

int Stack[MAX_STACK] = {0};

int Global[MAX_GLOBAL] = {0};

//Main program vars
int ProgData[MAX_CODE] = {0};
int ProgCount = 0;

//Instructions
enum TOprands{
    NOP = 0,
    IADD = 1,
    ISUB = 2,
    IMUL = 3,
    IDIV = 4,
    IAND = 5,
    IOR = 6,
    IXOR = 7,
    IMOD = 8,
    DUP = 9,
    ICONST = 10,
    GSTORE = 11,
    GLOAD = 12,
    PRINTI = 13,
    PRINTC = 14,
    HALT = 15
}Operands;

//Testing programs
//Add two numbers and show the result
int testAdd[] = {ICONST,20,ICONST,5,IMOD,PRINTI,HALT};
//Print ABC and make a beep sound
int testChar[] = {ICONST,65,PRINTC, ICONST,66, PRINTC, ICONST,67,PRINTC,ICONST, 7,PRINTC,HALT};
//Test Dup
int testDup[] = {
    ICONST,50,
    DUP,
    IADD,
    PRINTI,
    HALT
};

//Test global variables
int varTest[] = {
    ICONST,25,
    GSTORE,1,
    ICONST,15,
    GLOAD,1,
    IADD,
    PRINTI,
    HALT
};

//End of testing programs

void Push(int v){
    Stack[++sp] = v;
}

int Pop(){
    return Stack[sp--];
}

int Peek(){
    return Stack[sp];
}

void vm_addCode(int code[], int size){
int x = 0;
    while(x < size){
        ProgData[x] = code[x];
        x++;
    }
    ProgCount = x;
}

void vm_free(){
    pc = 0;
    sp =-1;
    ProgCount = 0;
    memset(ProgData,0,sizeof ProgData);
    memset(Stack,0,sizeof Stack);
    memset(Global,0,sizeof Global);
}

int vm_BinaryOp(int op, int a, int b){
    switch(op){
    case IADD:
        return a + b;
    case ISUB:
        return b - a;
    case IMUL:
        return a * b;
    case IDIV:
        return b / a;
    case IAND:
        return a && b;
    case IOR:
        return a || b;
    case IXOR:
        return a ^ b;
    case IMOD:
        return b % a;
    default:
        return 0;
    }
}

void vm_execute(){
int a  = 0;
int b = 0;
int addr = 0;

    while(pc < ProgCount){
        //Fetch opcodes
        int op = ProgData[pc];
        //Execute the opcodes
        switch(op){
        case ICONST:
            //INC program counter to get next index
            pc++;
            //Push the value on the stack top
            Push(ProgData[pc]);
            break;
        case GSTORE:
            pc++;
            //Get variable address
            addr = ProgData[pc];
            //Store the top of the stack in global[address]
            Global[addr] = Pop();
            break;
        case GLOAD:
            pc++;
            //Get variable address
            addr = ProgData[pc];
            //Push the value from global onto the stack
            Push(Global[addr]);
            break;
        case IADD:
        case ISUB:
        case IMUL:
        case IDIV:
        case IAND:
        case IOR:
        case IXOR:
        case IMOD:
            //Pop of the two values on top of the stack
            a = Pop();
            b = Pop();
            //Preform the binary op and push back the result on the stack.
            Push(vm_BinaryOp(op,a,b));
            break;
        case DUP:
            //Duplicate what is on the stack and push the value on the stack.
            Push(Peek());
            break;
        case PRINTI:
            //Pop of the top of the stack value and display to user.
            printf("%d",Pop());
            break;
        case PRINTC:
            //Same as PRINTI but this converts and prints as a char
            printf("%c",Pop());
            break;
        case HALT:
            //Stop the program
            pc = ProgCount;
            break;
        case NOP:
            //Do nothing
            break;
        default:
            break;
        }
        //INC Program counter
        pc++;
    }
}

int main()
{
    //Get the size of the program to execute
    int n = sizeof(varTest) / sizeof(int);
    //Add test code make sure you also include the size
    vm_addCode(varTest,n);

    vm_execute();
    //Clear up vm
    vm_free();

    return 0;
}


Viewing all articles
Browse latest Browse all 16013

Latest Images

Trending Articles



Latest Images

<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>