Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

A basic Virtual Machine for Experimentation

0.00/5 (No votes)
13 May 2003 1  
A basic Virtual Machine for experimentation.

Introduction

A rather QAD mini VM, for experimentation.

using System;
using System.Collections;

public class MiniVM {

   public static void Main(string [] args) {
    AVM vm = new AVM();

    String srcCode = "";
    srcCode += "           loadr 1 1;";
    srcCode += "loop:      cmpt  1 5 exit;";
    srcCode += "           sysPrint msg;";
    srcCode += "           incr  1 1;";
    srcCode += "           jump  loop;";
    srcCode += "exit:      brk;";
    srcCode += "msg:       data.string 'Hello World';";

    vm.asmCode(srcCode);

    vm.execCode();

   }
}

public class AVM {
    private byte []     vmc         = new byte[128];
    private Hashtable     lookupReplace     = new Hashtable();

    public void loadCode(byte [] newcode) {
        for ( int i = 0 ; i < newcode.Length ; i++ )
            vmc[i] = newcode[i];
    }

    private String [] getParms(String cLine) {
        String []     xparms     = cLine.Split(new char []{' '});
        String []     yparms     = new String[xparms.Length];
        int         parmCnt = 0;
        
        for ( int j = 0 ; j < xparms.Length ; j++ ) { // All this crap because String.Split includes extra tokens.

            if ( xparms[j] != String.Empty )
                yparms[parmCnt++] = xparms[j];
        }
        String [] parms = new String[parmCnt];
        Array.Copy(yparms, parms, parmCnt);

        return parms;
    }
    
    private int lookup(String sVal, int pc) {
        int v = -1;
        
        try { 
            v = Int16.Parse(sVal);
        } catch ( Exception e ) {
        }
        if ( v == -1 ) 
            lookupReplace.Add(pc, sVal);

        return v;
    }

    public void asmCode(String src) {
        String [] srcL = src.Split(new char [] {';'});
        asmCode(srcL);
    }
    
    public void asmCode(String [] src) {
        int pc = 0;
        Hashtable labels = new Hashtable();

        for ( int i = 0 ; i < src.Length ; i++ ) {
            if  ( src[i] == String.Empty ) continue;
            
            String         cLine     = src[i];
            String []     parms     = getParms(cLine);
            int         cmdPos     = 0;
            
            if ( parms[cmdPos].EndsWith(":") ) {
                labels.Add(parms[cmdPos].Substring(0, parms[cmdPos].Length-1), pc);
                cmdPos++;
            }
            
            switch ( parms[cmdPos] ) {
                case "sysPrint":
                    vmc[pc++] = 1;
                    int v = lookup(parms[cmdPos+1], pc);
                    vmc[pc++] = (byte)v;
                    break;
                case "brk":
                    vmc[pc++] = 0;
                    break;
                case "loadr":
                    vmc[pc++] = 2;
                    vmc[pc++] = (byte)(lookup(parms[cmdPos+1], pc));
                    vmc[pc++] = (byte)(lookup(parms[cmdPos+2], pc));
                    break;
                case "cmpt":
                    vmc[pc++] = 3;
                    vmc[pc] = (byte)(lookup(parms[cmdPos+1], pc));
                    pc++;
                    vmc[pc] = (byte)(lookup(parms[cmdPos+2], pc));
                    pc++;
                    vmc[pc] = (byte)(lookup(parms[cmdPos+3], pc));
                    pc++;
                    break;
                case "incr":
                    vmc[pc++] = 4;
                    vmc[pc++] = (byte)(lookup(parms[cmdPos+1], pc));
                    vmc[pc++] = (byte)(lookup(parms[cmdPos+2], pc));
                    break;
                case "jump":
                    vmc[pc++] = 5;
                    vmc[pc] = (byte)(lookup(parms[cmdPos+1], pc));
                    pc++;
                    break;
                case "data.string":
                    String x = cLine.Substring(cLine.IndexOf("data.string")+12);
                    //Console.WriteLine("LIT:"+x);

                    char [] c = x.ToCharArray();
                    for ( int j = 1 ; j < c.Length-1 ; j++ ) {
                        vmc[pc++] = (byte)(c[j]    );
                    }
                    vmc[pc++] = 0;
                    break;
            }
        }

        IDictionaryEnumerator myEnumerator = lookupReplace.GetEnumerator();
        while ( myEnumerator.MoveNext() ) {
             int val = (int)(labels[myEnumerator.Value]);
                 //Console.WriteLine("Sub {0} {1}", myEnumerator.Key, myEnumerator.Value+ " ="+val);

             vmc[(int)(myEnumerator.Key)] = (byte)val;
        }   

        //for ( int i = 0 ; i < pc ; i++ )

        //    Console.WriteLine(i+"::"+vmc[i]);

    }

    public void execCode() {
        int     pc     = 0;
        int     ilc     = 1;
        bool     cont     = true;
        int []     regs     = new int[16];
        
        while ( cont ) {
            byte currInst = vmc[pc];
            //Console.WriteLine(pc+":"+currInst+ "  ,  " + vmc[pc+1] + "  , " + vmc[pc+2]+ "  , " + vmc[pc+3]);

            switch ( currInst ) {
                case 0 : // brk

                    cont = false;
                    break;
                case 1 : // sysPrint

                    String p = "";
                    for ( int i = 0 ; vmc[vmc[pc+1]+i] != 0 ; i++ )
                        p += (char)(vmc[vmc[pc+1]+i]);
                    Console.WriteLine(p);
                    ilc = 2;
                    break;
                case 2 : // loadr

                    regs[vmc[pc+1]] = vmc[pc+2];
                    ilc = 3;
                    break;
                case 3 : // cmpt

                    if ( regs[vmc[pc+1]] == vmc[pc+2] ) {
                        pc = vmc[pc+3];
                        ilc = 0;
                    } else {
                        ilc = 4;
                    }
                    break;
                case 4 : // incr

                    regs[vmc[pc+1]] += vmc[pc+2];
                    ilc = 3;
                    break;
                case 5 : // jump

                    pc = vmc[pc+1];
                    ilc = 0;
                    break;
                default :
                    Console.WriteLine("UNK INST");
                    break;    
            }
            pc += ilc;
        }

    }
}

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here