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();
};
}