JSFiddle - React, Tailwind, and code Playground

HTML

<!-- JSVM Demo 

=== SOURCE CODE ===

var i = 0;
function render() {
    txt.value = i++;
    if (i <= 255) {
        requestAnimationFrame(render);
    }
}
render();

=== BYTE CODE ===
0000    05 03 00 00             MOV Z, 0
0004    01 00 00 00  L_TIMER:   LDR A, 0
0008    01 01 00 01             LDR X, 1
000C    02 02 00 01             GET Y, A, X
0010    01 01 00 02             LDR X, 2
0014    03 02 01 03             SET Y, X, Z
0018    06 03 00 00             INC Z
001C    05 01 00 ff             MOV X, 255
0020    07 03 01 10             JG  Z, X, L_END
0024    01 01 00 03             LDR X, 3
0028    08 02 00 04             FUN Y, L_TIMER
002C    04 00 01 02             CAL A, X, Y
0030    00 00 00 00  L_END:     BRK
-->
<textarea id="txtBin">
05 03 00 00 01 00 00 00 01 01 00 01 02 02 00 01
01 01 00 02 03 02 01 03 06 03 00 00 05 01 00 ff
07 03 01 10 01 01 00 03 08 02 00 04 04 00 01 02
00 00 00 00
</textarea>
<button id="btnRun">Run</button>

<fieldset>
  <legend>Demo</legend>
  <input id="txt">
  <script>
    // TODO: 序列化成二进制数据
    var CONST_DATA = [
      window, 'txt', 'value', 'requestAnimationFrame',
    ];
  </script>
</fieldset>

CSS

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

JavaScript

var BASE = 1000;
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:    // MOV
        r1 = readPC8();
        imm = readPC16();
        REG[r1] = imm;
        break;

      case 0x06:    // INC
        r1 = readPC8();
        REG[r1]++;
        pc += 2;
        break;

      case 0x07:    // JG
        r1 = readPC8();
        r2 = readPC8();
        imm = readPC8();

        if (REG[r1] > REG[r2]) {
          pc = pc + imm - 3;
        }
        break;

      case 0x08:    // FUN
        r1 = readPC8();
        r2 = readPC16();
        REG[r1] = makeCallback(r2);
        break;

        // ...

      default:      // Unknown
        debugger;
    }
  }
}

function makeCallback(i) {
  return function() {
    pc = BASE + i;
    return run();
  };
}