JSFiddle - React, Tailwind, and code Playground

HTML

<textarea id="txtBin">
01 00 00 00 01 01 00 01 02 01 00 01 01 00 00 02
01 02 00 03 04 01 00 02 01 02 00 04 01 03 00 05
03 00 02 03 01 02 00 06 02 01 01 02 01 02 00 07
04 01 02 00
</textarea>
<button id="btnRun">Run</button>
<script>
  // TODO: 序列化成二进制数据
  var CONST_DATA = [
    window, 'document', 'createElement', 'script',
    'text', 'alert(123)', 'body', 'appendChild'
  ];
</script>

CSS

textarea {
  width: 500px;
  height: 200px;
  font-family: monospace;
}

JavaScript

var BASE = 1024;
var MEM = [];
var REG = [];


btnRun.onclick = function() {
  // 加载常量数据
  MEM = CONST_DATA.concat();

  // 加载指令到存储
  txtBin.value.split(/\s+/).forEach(function(hex, i) {
    MEM[BASE + i] = parseInt(hex, 16);
  });

  pc = BASE;
  run();
};

function readPC8() {
  return MEM[pc++] | 0;
}

function readPC16() {
  var v = (MEM[pc] << 8) | MEM[pc + 1];
  pc += 2;
  return v;
}

function run() {
  var r1, r2, r3, r4;
  var imm;
  var obj, key, val;


  for (;;) {
    var opcode = readPC8();
    if (!opcode) {
      break;
    }

    switch (opcode) {
      case 0x01:    // LDR
        r1 = readPC8();
        imm = readPC16();
        REG[r1] = MEM[imm];
        break;

      case 0x02:    // GET
        r1 = readPC8();
        r2 = readPC8();
        r3 = readPC8();

        obj = REG[r2];
        key = REG[r3];
        REG[r1] = obj[key];
        break;

      case 0x03:    // SET
        r1 = readPC8();
        r2 = readPC8();
        r3 = readPC8();

        obj = REG[r1];
        key = REG[r2];
        val = REG[r3];

        obj[key] = val;
        break;

      case 0x04:    // CAL
        r1 = readPC8();
        r2 = readPC8();
        r3 = readPC8();

        obj = REG[r1];
        key = REG[r2];
        REG[0] = obj[key]( REG[r3] );
        break;

      case 0x05:    // JMP
        imm = readPC16();
        pc = pc + imm - 2;
        break;

        // ...

      default:      // Unknown
        debugger;
    }
  }
}