今すぐアセンブリコードと機械の指示対応するので、機械語命令の実行をシミュレートするために、CPUを見て、私たちは、シミュレータのアセンブリコードの直接の実装を作成することができます。
シミュレータを作成する前に、最初に関連するディレクティブの動作を説明します。
- スタック
メモリにおいて、スタックは、挿入および欠失によって特徴付けられるだけであり、2つだけの操作はプッシュとポップ、同じ端部で動作させることができます。
- 押す
プッシュ命令の効果は、スタックオペランドをプッシュすることです。
- ポップ
アクションポップ命令は、オペランドスタックをポップすることです。
- 加えます
アクションは、指示操作を二回スタックに結果をプッシュし、次いで、二つのオペランドAおよびBをポップアップ、ポップ、次いで+ bを行う行われる加えます。
- サブ
スタックに結果をプッシュし、次いで、B - アクション命令を2回サブポップ操作を行っポップ二つのオペランド及びB、及び次いで行います。
- 私に
アクションMUL命令操作を2回、ポップ二つのオペランドAおよびBをポップし、次に* bを実行し、スタックに結果をプッシュ行われます。
- DIV
動作指示を2回サブポップ操作を行っポップ二つのオペランドおよびB、次いで/ Bを実行し、スタックに結果をプッシュします。
すべての4つの命令は、操作が終了した説明、それはそれほど単純ではないのですか?
コードの実装
注:導入する必要がある最初の二つの記事字句解析や構文解析コード
function CpuEmulator(instructions) {
this.ins = instructions.split('\r\n')
this.memory = []
this.re = /^(push)\s\w+/
this.execute()
}
CpuEmulator.prototype = {
execute() {
this.ins.forEach(i => {
switch (i) {
case 'add':
this.add()
break
case 'sub':
this.sub()
break
case 'mul':
this.mul()
break
case 'div':
this.div()
break
default:
if (this.re.test(i)) {
this.push(i.split(' ')[1])
}
}
})
},
add() {
const b = this.pop()
const a = this.pop()
this.memory.push(a + b)
},
sub() {
const b = this.pop()
const a = this.pop()
this.memory.push(a - b)
},
mul() {
const b = this.pop()
const a = this.pop()
this.memory.push(a * b)
},
div() {
const b = this.pop()
const a = this.pop()
this.memory.push(a / b)
},
push(x) {
this.memory.push(parseInt(x))
},
pop() {
return this.memory.pop()
},
getResult() {
return this.memory[0]
}
}
const tokens = lexicalAnalysis('(100+ 10)* 10-100/ 10 +8* (4+2)')
const writer = new AssemblyWriter()
const parser = new Parser(tokens, writer)
const instructions = parser.getInstructions()
const emulator = new CpuEmulator(instructions)
console.log(emulator.getResult()) // 1138