Skip to content

Instantly share code, notes, and snippets.

@DreamVB
Last active April 9, 2023 16:25

Revisions

  1. DreamVB revised this gist Jul 15, 2019. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion vm.c
    Original file line number Diff line number Diff line change
    @@ -15,7 +15,7 @@
    15/7/2019
    + Added NEG, NOT , LT (Less Than),JF (Jump False)
    + Added simple example
    + Added simple IF example
    */

    #include <stdio.h>
  2. DreamVB revised this gist Jul 15, 2019. 1 changed file with 85 additions and 8 deletions.
    93 changes: 85 additions & 8 deletions vm.c
    Original file line number Diff line number Diff line change
    @@ -2,20 +2,25 @@
    Simple stack Virtual Machine
    Version 1.0
    by DreamVB
    This is a simple example of how to code a simple VM in C
    At the moment this vm only supports a small amount of instruction I hope to add more as I learn more.
    This version has some hard coded example that you can test in the vm. Next version I plan to load the examples from files.
    If you like this code, or if you have some improvements I can make drop me a message below:
    dreamvb@outlook.com
    Happy-Coding
    15/7/2019
    + Added NEG, NOT , LT (Less Than),JF (Jump False)
    + Added simple example
    */

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>

    #define MAX_PROG 65535
    #define MAX_STACK 256
    @@ -32,10 +37,16 @@ typedef enum {
    AND,
    OR,
    XOR,
    NEG,
    NOT,
    MOD,
    GSTORE,
    GLOAD,
    JMP,
    LT,
    GT,
    JT,
    JF,
    HLT,
    }OP_CODES;

    @@ -69,6 +80,41 @@ int Adder[] = {
    HLT
    };

    int Neg[] = {
    PUSH,
    124,
    NEG,
    PRTI,
    PUSH,
    -120,
    NEG,
    PRTI,
    HLT
    };

    int Not[] = {
    PUSH,
    1,
    NOT,
    PRTI,
    HLT
    };

    int JumpTrue[] = {
    PUSH,8,
    PUSH, 6,
    LT,
    //True
    JF,10,
    PUSH,'T',
    PRTC,
    HLT,
    //False
    PUSH,'F',
    PRTC,
    HLT
    };

    int Hello[] = {
    PUSH,
    1234,
    @@ -155,8 +201,7 @@ void vm_execute(){
    int r = 0;
    int l = 0;
    int r_idx = 0;
    int jp = 0;


    //Loop while we still have code to execute
    while(pc < p_len){
    //Read Instruction
    @@ -231,7 +276,39 @@ void vm_execute(){
    l = STACK[sp--];
    STACK[++sp] = (r ^ l);
    break;
    case NEG:
    r = -STACK[sp--];
    STACK[++sp] = r;
    break;
    case NOT:
    r = !STACK[sp--];
    STACK[++sp] = r;
    break;
    //Save the top of the stack into a global variable address.
    case LT:
    r = STACK[sp--];
    l = STACK[sp--];
    //test the two values on the stack
    if(l < r){
    //Flag is true
    STACK[++sp] = 1;
    }else{
    //Flag is false
    STACK[++sp] = 0;
    }
    break;
    //Jump False
    case JF:
    pc++;
    //Get the top of the stack
    r = STACK[sp--];
    //Check for zero flag
    if(r == 0){
    //Jump to code address.
    pc = pcode[pc];
    }
    break;

    case GSTORE:
    pc++;
    //Get reg address.
    @@ -259,13 +336,13 @@ void vm_execute(){
    }

    void vm_free(){
    free(pcode);
    memset(pcode,0,sizeof(pcode));
    }

    int main()
    {
    //Add code to VM
    vm_init(BasicVar,sizeof(BasicVar) / sizeof(int));
    vm_init(JumpTrue,sizeof(JumpTrue) / sizeof(int));
    //Execute code
    vm_execute();
    //Free the program code.
  3. DreamVB created this gist Jul 14, 2019.
    275 changes: 275 additions & 0 deletions vm.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,275 @@
    /*
    Simple stack Virtual Machine
    Version 1.0
    by DreamVB
    This is a simple example of how to code a simple VM in C
    At the moment this vm only supports a small amount of instruction I hope to add more as I learn more.
    This version has some hard coded example that you can test in the vm. Next version I plan to load the examples from files.
    If you like this code, or if you have some improvements I can make drop me a message below:
    dreamvb@outlook.com
    Happy-Coding
    */

    #include <stdio.h>
    #include <stdlib.h>

    #define MAX_PROG 65535
    #define MAX_STACK 256
    #define MAX_GLOBALS 8

    typedef enum {
    PUSH = 0,
    PRTI,
    PRTC,
    ADD,
    SUB,
    MUL,
    DIV,
    AND,
    OR,
    XOR,
    MOD,
    GSTORE,
    GLOAD,
    JMP,
    HLT,
    }OP_CODES;

    //Program code to execute
    int pcode[MAX_PROG];
    //Stack
    int STACK[MAX_STACK];
    //Global variables pool
    int Globals[MAX_GLOBALS];
    //Stack pointer
    int sp = -1;
    //Program counter
    int pc = 0;
    //Length of the current program to execute
    int p_len = 0;

    //Examples are shown below.
    int Adder[] = {
    PUSH,
    150,
    PUSH,
    150,
    ADD,
    PRTI,
    PUSH,
    128,
    PUSH,
    4,
    DIV,
    PRTI,
    HLT
    };

    int Hello[] = {
    PUSH,
    1234,
    PRTI,
    HLT
    };

    int Logic[] = {
    PUSH,
    5,
    PUSH,
    14,
    XOR,
    PRTI,
    HLT
    };

    int BasicVar[] = {
    PUSH,
    150,
    PUSH,
    120,
    ADD,
    GSTORE,
    1,
    PUSH,
    15,
    PRTI,
    GLOAD,
    1,
    PRTI,
    HLT
    };

    int Beep[] = {
    PUSH,
    0x7,
    PRTC,
    HLT
    };

    int Jump[] = {
    JMP,
    4,
    PUSH,
    20,
    PRTI,
    //Don't output the above
    PUSH,
    141,
    PRTI,
    HLT
    };

    int ModTest[] = {
    PUSH,
    14,
    PUSH,
    3,
    MOD,
    PRTI,
    HLT
    };

    void vm_init(const int *code,int code_len){
    int x = 0;
    p_len = code_len;
    //Load code into program code array.
    while(x < code_len){
    pcode[x] = code[x];
    //INC counter
    x++;
    }
    //Reset default variables values.
    x = 0;
    while(x < MAX_GLOBALS){
    Globals[x] = 0;
    x++;
    }
    }

    void vm_execute(){
    int op = 0;
    int r = 0;
    int l = 0;
    int r_idx = 0;
    int jp = 0;

    //Loop while we still have code to execute
    while(pc < p_len){
    //Read Instruction
    op = pcode[pc];

    //See what Instruction we are dealing with
    switch(op){
    //Push a value to the top of the stack
    case PUSH:
    pc++;
    STACK[++sp] = pcode[pc];
    break;
    //Print the top of the stack as an integer
    case PRTI:
    printf("%d\n",STACK[sp--]);
    break;
    //Print the top of the stack as a char
    case PRTC:
    printf("%c",STACK[sp--]);
    break;
    //Add the two top items on the stack and push back onto the stack.
    case ADD:
    r = STACK[sp--];
    l = STACK[sp--];
    STACK[++sp] = (r + l);
    break;
    //Subtract the two top items on the stack and push back onto the stack.
    case SUB:
    r = STACK[sp--];
    l = STACK[sp--];
    STACK[++sp] = (l - r);
    break;
    //Multiply the two top items on the stack and push back onto the stack.
    case MUL:
    r = STACK[sp--];
    l = STACK[sp--];
    STACK[++sp] = (r * l);
    break;
    //Divide the two top items on the stack and push back onto the stack.
    case DIV:
    r = STACK[sp--];
    l = STACK[sp--];
    //Check for division by zero error.
    if(r == 0){
    printf("Division by zero");
    //Set program counter to the end of the program code length.
    pc = p_len;
    }else{
    STACK[++sp] = (l / r);
    }
    break;
    case MOD:
    r = STACK[sp--];
    l = STACK[sp--];
    STACK[++sp] = (l % r);
    break;
    case HLT:
    pc = p_len;
    break;
    case AND:
    r = STACK[sp--];
    l = STACK[sp--];
    STACK[++sp] = (r & l);
    break;
    case OR:
    r = STACK[sp--];
    l = STACK[sp--];
    STACK[++sp] = (r | l);
    break;
    case XOR:
    r = STACK[sp--];
    l = STACK[sp--];
    STACK[++sp] = (r ^ l);
    break;
    //Save the top of the stack into a global variable address.
    case GSTORE:
    pc++;
    //Get reg address.
    r_idx = pcode[pc];
    //Get the tack value and put into reg
    Globals[r_idx] = STACK[sp--];
    //Get what is on the stack.
    break;
    //Load a global variable and place on the stack
    case GLOAD:
    pc++;
    //Get reg index
    r_idx = pcode[pc];
    STACK[++sp] = Globals[r_idx];
    break;
    case JMP:
    pc++;
    //Jump to address
    pc = pcode[pc];
    break;
    }
    //INC program counter
    pc++;
    }
    }

    void vm_free(){
    free(pcode);
    }

    int main()
    {
    //Add code to VM
    vm_init(BasicVar,sizeof(BasicVar) / sizeof(int));
    //Execute code
    vm_execute();
    //Free the program code.
    vm_free();
    //Return back to the operating system.
    return 0;
    }