Execute Computer/Zero is an implementation of Computer/zero Assembly.
Other implementations of Computer/zero Assembly.
Task

Create a Computer/zero Assembly emulator. You may consider this webpage as a reference implementation. Output the results of the sample programs "2+2" and "7*8" found there.

   The virtual machine "bytecode" needs to be able to modify itself (or at least act as though it can) while the virtual machine is running, to be consistent with the reference implementation.
   For output, it is sufficient to have the implementation of the STP opcode return the accumulator to your actual language, and then use your standard printing routines to output it.
Bonus Points
 Run all 5 sample programs at the aforementioned website and output their results.


var NOP = 0
var LDA = 1
var STA = 2
var ADD = 3
var SUB = 4
var BRZ = 5
var JMP = 6
var STP = 7
 
var ops = {"NOP": NOP, "LDA": LDA, "STA": STA, "ADD": ADD,
           "SUB": SUB, "BRZ": BRZ, "JMP": JMP, "STP": STP}
 
var load = Fn.new { |prog|
    var mem = List.filled(32, 0)
    var lines = prog.trimEnd().split("\n")
    for (i in 0...lines.count) {
        var line = lines[i].trim()
        var split = line.split(" ")
        var instr = split[0]
        var addr = 0
        if (split.count == 2) addr = Num.fromString(split[1])
        if (ops[instr]) {
            mem[i] = ops[instr] * 32 + addr
        } else {
            var v = Num.fromString(instr)
            if (v) mem[i] = v
        }
    }
    return mem
}
 
var output = Fn.new { |acc|
    System.print(acc)
}
 
var interp = Fn.new { |prog|
    var acc = 0
    var pc = 0
    var mem = load.call(prog)
    while (true) {
        var instr = mem[pc] >> 5
        var addr  = mem[pc] % 32
        pc = pc + 1
        if (instr == LDA) {
            acc = mem[addr]
        } else if (instr == STA) {
            mem[addr] = acc
        } else if (instr == ADD) {
            acc = acc + mem[addr]
            if (acc > 255) acc = acc - 256
        } else if (instr == SUB) {
            acc = acc - mem[addr]
            if (acc < 0) acc = acc + 256
        } else if (instr == BRZ) {
            if (acc == 0) pc = addr
        } else if (instr == JMP) {
            pc = addr
        }
        if (instr == STP || pc > 31) break
    }
    output.call(acc)
}
 
var progs = [
    """
        LDA 3
        ADD 4
        STP
        2
        2
    """,
    """
        LDA 12
        ADD 10
        STA 12
        LDA 11
        SUB 13
        STA 11
        BRZ 8
        JMP 0
        LDA 12
        STP
        8
        7
        0
        1
    """,
    """
        LDA 14
        STA 15
        ADD 13
        STA 14
        LDA 15
        STA 13
        LDA 16
        SUB 17
        BRZ 11
        STA 16
        JMP 0
        LDA 14
        STP
        1
        1
        0
        8
        1
    """,
    """
        LDA 13
        ADD 15
        STA 5
        ADD 16
        STA 7
        NOP
        STA 14
        NOP
        BRZ 11
        STA 15
        JMP 0
        LDA 14
        STP
        LDA 0
        0
        28
        1
 
 
 
        6
        0
        2
        26
        5
        20
        3
        30
        1
        22
        4
        24
    """,
    """
        0
        0
        STP
        NOP
        LDA 3
        SUB 29
        BRZ 18
        LDA 3
        STA 29
        BRZ 14
        LDA 1
        ADD 31
        STA 1
        JMP 2
        LDA 0
        ADD 31
        STA 0
        JMP 2
        LDA 3
        STA 29
        LDA 0
        ADD 30
        ADD 3
        STA 0
        LDA 1
        ADD 30
        ADD 3
        STA 1
        JMP 2
        0
        1
        3
    """
]
for (prog in progs) interp.call(prog)