资讯专栏INFORMATION COLUMN

编译原理实战入门:用 JavaScript 写一个简单的四则运算编译器(三)模拟执行

Ku_Andrew / 691人阅读

摘要:栈在内存中,栈的特点是只能在同一端进行插入和删除的操作,即只有和两种操作。指令的作用是将一个操作数推入栈中。指令的作用是执行两次操作,弹出两个操作数和,然后执行,再将结果到栈中。

现在来模拟一下 CPU 执行机器指令的情况,由于汇编代码和机器指令一一对应,所以我们可以创建一个直接执行汇编代码的模拟器。
在创建模拟器前,先来讲解一下相关指令的操作。

在内存中,栈的特点是只能在同一端进行插入和删除的操作,即只有 push 和 pop 两种操作。

push

push 指令的作用是将一个操作数推入栈中。

pop

pop 指令的作用是将一个操作数弹出栈。

add

add 指令的作用是执行两次 pop 操作,弹出两个操作数 a 和 b,然后执行 a + b,再将结果 push 到栈中。

sub

sub 指令的作用是执行两次 pop 操作,弹出两个操作数 a 和 b,然后执行 a - b,再将结果 push 到栈中。

mul

mul 指令的作用是执行两次 pop 操作,弹出两个操作数 a 和 b,然后执行 a * b,再将结果 push 到栈中。

div

sub 指令的作用是执行两次 pop 操作,弹出两个操作数 a 和 b,然后执行 a / b,再将结果 push 到栈中。

四则运算的所有指令已经讲解完毕了,是不是觉得很简单?

代码实现

注意:需要引入前两篇文章词法分析和语法分析的代码

function CpuEmulator(instructions) {
    this.ins = instructions.split("
")
    this.memory = []
    this.re = /^(push)sw+/
    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

编译原理实战入门:用 JavaScript 写一个简单的四则运算编译器(一)词法分析

编译原理实战入门:用 JavaScript 写一个简单的四则运算编译器(二)语法分析

编译原理实战入门:用 JavaScript 写一个简单的四则运算编译器(三)模拟执行

编译原理实战入门:用 JavaScript 写一个简单的四则运算编译器(四)结语

完整源码

参考资料:计算机系统要素

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/105162.html

相关文章

  • 编译原理实战入门 JavaScript 一个简单四则运算编译器(一)词法分析

    摘要:一般的程序,是无法直接执行的,因为只能识别机器指令。所以要想执行一个程序,首先要将高级语言编写的程序翻译为汇编代码,再将汇编代码翻译为机器指令,这样才能识别并执行。 编译器 编译器是一个程序,作用是将一门语言翻译成另一门语言。 一般的程序,CPU 是无法直接执行的,因为 CPU 只能识别机器指令。所以要想执行一个程序,首先要将高级语言编写的程序翻译为汇编代码,再将汇编代码翻译为机器指令...

    wangdai 评论0 收藏0
  • 编译原理实战入门 JavaScript 一个简单四则运算编译器(四)结语

    摘要:四则运算编译器,虽然说功能很简单,只能编译四则运算表达式。再复杂的编译器再简单的编译器,功能上是差不多的,只是复杂的编译器实现上会更困难。每一章都是理论与实践结合的经典,从计算机硬件知识到软件体系,再到编译原理和操作系统。 四则运算编译器,虽然说功能很简单,只能编译四则运算表达式。但是编译原理前端部分几乎都有涉及,词法分析,语法分析,还有代码生成。 再复杂的编译器、再简单的编译器,功能...

    chemzqm 评论0 收藏0
  • 编译原理实战入门 JavaScript 一个简单四则运算编译器(二)语法分析

    摘要:语法分析对输入的文本按照语法规则进行分析并确定其语法结构的一种过程,称为语法分析。递归下降分析法递归下降分析法,也称为自顶向下分析法。表达式代码生成我们通常用的四则运算表达式是中缀表达式,但是对于计算机来说中缀表达式不便于计算。 四则运算的语法规则(语法规则是分层的) x* 表示 x 出现零次或多次 x | y 表示 x 或 y 将出现 ( ) 圆括号,用于语言构词的分组 以下规则...

    hankkin 评论0 收藏0
  • SegmentFault 技术周刊 Vol.40 - 2018,来学习一门新编程语言吧!

    摘要:入门,第一个这是一门很新的语言,年前后正式公布,算起来是比较年轻的编程语言了,更重要的是它是面向程序员的函数式编程语言,它的代码运行在之上。它通过编辑类工具,带来了先进的编辑体验,增强了语言服务。 showImg(https://segmentfault.com/img/bV1xdq?w=900&h=385); 新的一年不知不觉已经到来了,总结过去的 2017,相信小伙们一定有很多收获...

    caspar 评论0 收藏0
  • SegmentFault 技术周刊 Vol.40 - 2018,来学习一门新编程语言吧!

    摘要:入门,第一个这是一门很新的语言,年前后正式公布,算起来是比较年轻的编程语言了,更重要的是它是面向程序员的函数式编程语言,它的代码运行在之上。它通过编辑类工具,带来了先进的编辑体验,增强了语言服务。 showImg(https://segmentfault.com/img/bV1xdq?w=900&h=385); 新的一年不知不觉已经到来了,总结过去的 2017,相信小伙们一定有很多收获...

    nihao 评论0 收藏0

发表评论

0条评论

Ku_Andrew

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<