編譯原理實戰入門:用 JavaScript 寫一個簡單的四則運算編譯器(三)模擬執行

如今來模擬一下 CPU 執行機器指令的狀況,因爲彙編代碼和機器指令一一對應,因此咱們能夠建立一個直接執行彙編代碼的模擬器。
在建立模擬器前,先來說解一下相關指令的操做。git

在內存中,棧的特色是隻能在同一端進行插入和刪除的操做,即只有 push 和 pop 兩種操做。github

  • push

push 指令的做用是將一個操做數推入棧中。this

  • pop

pop 指令的做用是將一個操做數彈出棧。prototype

  • add

add 指令的做用是執行兩次 pop 操做,彈出兩個操做數 a 和 b,而後執行 a + b,再將結果 push 到棧中。code

  • sub

sub 指令的做用是執行兩次 pop 操做,彈出兩個操做數 a 和 b,而後執行 a - b,再將結果 push 到棧中。token

  • mul

mul 指令的做用是執行兩次 pop 操做,彈出兩個操做數 a 和 b,而後執行 a * b,再將結果 push 到棧中。ip

  • div

sub 指令的做用是執行兩次 pop 操做,彈出兩個操做數 a 和 b,而後執行 a / b,再將結果 push 到棧中。內存

四則運算的全部指令已經講解完畢了,是否是以爲很簡單?get

代碼實現

注意:須要引入前兩篇文章詞法分析和語法分析的代碼編譯器

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

參考資料:計算機系統要素

相關文章
相關標籤/搜索