Compiler theory actual entry: use JavaScript to write a simple four operations compiler (c) simulation execution

Now look at the CPU to simulate the execution of machine instructions, because the assembly code and machine instructions correspondence, so we can create a direct implementation of simulator assembly code.
Before creating a simulator, first to explain the operation of the relevant directive.

  • Stack

In memory, the stack is characterized by insertion and deletion can only be operated at the same end, that is, only two operations push and pop.

  • push

Effect of a push instruction is to push the stack operand.

  • pop

Action pop instruction is to pop an operand stack.

  • add

Action add instruction operation is performed twice pop, pop two operands a and B, and then performs a + b, then push the result onto the stack.

  • sub

Action instruction is performed twice sub pop operation, a pop two operands and B, and then performs a - b, then push the result onto the stack.

  • I have

Action mul instruction operation is performed twice pop, pop two operands a and B, and then performs a * b, and then push the result onto the stack.

  • div

Action instruction is performed twice sub pop operation, a pop two operands and B, and then performs a / b, and then push the result onto the stack.

All four instructions explain operation has finished, it is not that simple?

Code

Note: The first two articles lexical analysis and parsing code that need to be introduced

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

Guess you like

Origin www.cnblogs.com/woai3c/p/11110653.html