Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion

A small stack-based virtual machine

A few days before, I have read an article - write a very small stack-based virtual machine in C, It is very interesting, so I try to write it in Codea, please see the code below:

-- miniVM

-- Use this function to perform your initial setup
function setup()
    print("Hello World! Welcome to miniVM")

    step = false
    running = true

    -- instruction set
    InstructionSet = {"PSH","ADD","POP","SET","HLT"}
    Register = {A, B, C, D, E, F,NUM_OF_REGISTERS}

    --  test program code
    program = {"PSH", "5", "PSH", "6", "ADD", "POP", "HLT"}

    -- instruction pointer, top of stack pointer, stack
    IP = 1
    SP = 0
    stack = {0,0,0,0,0}

end

-- fetch the instruction
function fetch()
    return program[IP]
end

-- evaluate
function eval(instr)
    if instr == "HLT" then
        running = false
    elseif instr == "PSH" then
        --  deal with PSH
        SP = SP + 1
        -- instruction pointer point to the next
        IP = IP + 1
        stack[SP] = program[IP]
    elseif instr == "POP" then
        -- deal with POP 
        local val_popped = stack[SP]
        -- table.remove(stack)
        SP = SP - 1
    elseif instr == "ADD" then
        -- deal with ADD
        -- POP a value from stack
        local a = stack[SP]
        stack[SP] = 0
        SP = SP - 1

        -- POP a value from stack again
        local b = stack[SP]
        stack[SP] = 0
        SP = SP - 1

        -- add two value
        local result = a + b

        -- push the sum into the stack
        SP = SP + 1
        stack[SP] = result

        -- print the status of the stack
        print(stack[SP])
    end

end

-- virtual machine main loop
function main()
    running = true
    while running do
        eval(fetch())
        IP = IP + 1
    end
end

-- main()


-- This function gets called once every frame
function draw()
    -- This sets a dark background color
    background(40, 40, 50)

    if running then
        if step then
            step = false
            eval(fetch())
            IP = IP + 1         
        end               
    end

    drawInstr()
    drawStack()
end

function touched(touch)
    if touch.state == ENDED then step = true end
end

VM = {}

-- draw the status of the instruction in the memory
function drawInstr()
    local x,y=500,600
    textMode(CORNER)
    fontSize(30)
    strokeWidth(2)
    stroke(0, 21, 255, 255)

    for k,v in ipairs(program) do
        -- draw the instruction which will execute
        local w,h = textSize(k)
        fill(54, 61, 50, 255)
        rect(x,y-(k-1)*h,w+80, h)
        fill(95, 255, 0, 255)
        text(v,x+10,y-(k-1)*h)

        -- draw the memory address
        fill(54, 61, 50, 255)
        rect(x-w-20,y-(k-1)*h,w+20, h)
        fill(0, 50, 255, 255)
        text(k,x-w-20+10,y-(k-1)*h)

        -- draw IP
        fill(228, 11, 11, 255)
        text("IP".."["..IP.."] ->",x-w-20+10-120,y-(IP-1)*h)
    end
end

-- draw the status of stack
function drawStack()
    local x,y=200,600
    textMode(CORNER)
    fontSize(30)
    strokeWidth(2)
    stroke(0, 21, 255, 255)

    for k,v in ipairs(stack) do
        -- draw the instruction pushed into the stack
        local w,h = textSize(k)
        fill(54, 61, 50, 255)
        rect(x,y-(k-1)*h,w+80, h)
        fill(95, 255, 0, 255)
        text(v,x+10,y-(k-1)*h)

        -- draw stack adress
        fill(54, 61, 50, 255)
        rect(x-w-20,y-(k-1)*h,w+20, h)
        fill(0, 50, 255, 255)
        text(k,x-w-20+10,y-(k-1)*h)

        -- draw SP
        fill(216, 210, 210, 255)
        text("SP".."["..SP.."] ➡️",x-w-20+10-120,y-(SP-1)*h+5)
    end
end

Here is the screenshot:

image

It is very simple, only to show the basic principle of a stack-based virtual machine, I am learning an more complex virtual system - Forth, and will post a more complex virtual machine code soon.

Comments

Sign In or Register to comment.