VicturalMachine(1)javscript code Simple execute with bench instructionsMemory const createMemory = (sizeInBytes) => { const ab = new ArrayBuffer(sizeInBytes) const dv = new DataView(ab) return dv } export default createMemory instructions set const MOVE_LIT_REG = 0x10 const MOVE_REG_REG = 0x11 const MOVE_REG_MEM = 0x12 const MOVE_MEM_REG = 0x13 const ADD_REG_REG = 0x14 const JMP_NOT_EQ = 0x15 export { MOVE_LIT_REG, MOVE_REG_REG, MOVE_REG_MEM, MOVE_MEM_REG, ADD_REG_REG, JMP_NOT_EQ, } CPU use cpu to similar execution to the instructions to define the register from machine constructor(memory){ this.memory = memory this.registerNames = [ 'ip','acc', 'r1','r2','r3','r4', 'r5','r6','r7','r8', 'sp','fp' ] // 16bits means every register need 2 bits this.registers = createMemory(this.registerNames.length * 2) this.registerMap = this.registerNames.reduce((map,name,i) => { map[name] = i*2 return map },{}) } we cannot immediation to get the address from memory, so we need create the fucntion to see the address which near the target address viewMemoryAt(address) { // 0x0f01: 0x04 0x05 0xA3 0xFE 0x13 0x0D 0x44 0x0F const nextEightBytes = Array.from({length: 8}, (_, i) => this.memory.getUint8(address + i) ).map(v => `0x${v.toString(16).padStart(2, '0')}`); console.log(`0x${address.toString(16).padStart(4, '0')}: ${nextEightBytes.join(' ')}`); } the full code import createMemory from "./create-memory.js" import { MOVE_LIT_REG, MOVE_REG_REG, MOVE_REG_MEM, MOVE_MEM_REG, ADD_REG_REG, JMP_NOT_EQ } from "./instruction.js" class CPU { constructor(memory){ this.memory = memory this.registerNames = [ 'ip','acc', 'r1','r2','r3','r4', 'r5','r6','r7','r8', 'sp','fp' ] // 16bits means every register need 2 bits this.registers = createMemory(this.registerNames.length * 2) this.registerMap = this.registerNames.reduce((map,name,i) => { map[name] = i*2 return map },{}) } debug(){ this.registerNames.forEach(name => { console.log(`${name}: 0x${this.getRegister(name).toString(16).padStart(4,'0')}`) }) console.log() } viewMemoryAt(address) { // 0x0f01: 0x04 0x05 0xA3 0xFE 0x13 0x0D 0x44 0x0F const nextEightBytes = Array.from({length: 8}, (_, i) => this.memory.getUint8(address + i) ).map(v => `0x${v.toString(16).padStart(2, '0')}`); console.log(`0x${address.toString(16).padStart(4, '0')}: ${nextEightBytes.join(' ')}`); } getRegister(name){ if(!(name in this.registerMap)){ throw new Error(`getRegister: No such register '${name}' `) } return this.registers.getUint16(this.registerMap[name]) } setRegister(name,value){ if(!(name in this.registerMap)){ throw new Error(`setRegister: No such register '${name}' `) } return this.registers.setUint16(this.registerMap[name],value) } fetch(){ const nextInstructionAddress = this.getRegister('ip') const instruction = this.memory.getUint8(nextInstructionAddress) this.setRegister('ip',nextInstructionAddress + 1) return instruction } fetch16(){ const nextInstructionAddress = this.getRegister('ip') const instruction = this.memory.getUint16(nextInstructionAddress) this.setRegister('ip',nextInstructionAddress + 2) return instruction } excute(instruction){ switch (instruction){ case MOVE_LIT_REG: { const literal = this.fetch16() const register = (this.fetch() % this.registerNames.length) * 2 this.registers.setUint16(register,literal) return } case MOVE_REG_REG : { const registerFrom = (this.fetch() % this.registerNames.length) * 2 const registerTo = (this.fetch() % this.registerNames.length) * 2 const value = this.registers.getUint16(registerFrom) this.registers.setUint16(registerTo,value) return } case MOVE_REG_MEM: { const registerFrom = (this.fetch() % this.registerNames.length) * 2 const address = this.fetch16() const value = this.registers.getUint16(registerFrom) this.memory.setUint16(address,value) return } case MOVE_MEM_REG: { const address = this.fetch16() const registerTo = (this.fetch() % this.registerNames.length) * 2 const value = this.memory.getUint16(address) this.registers.setUint16(registerTo,value) return } case ADD_REG_REG: { const r1 = this.fetch() const r2 = this.fetch() const registerValue1 = this.registers.getUint16(r1 * 2) const registerValue2 = this.registers.getUint16(r2 * 2) this.setRegister('acc',registerValue1 + registerValue2) return } case JMP_NOT_EQ: { const value = this.fetch16() const address = this.fetch16() if (value !== this.getRegister('acc')){ this.setRegister('ip',address) } return } } } step(){ const instruction = this.fetch() return this.excute(instruction) } } export default CPU