如何用 Lua 实现一个微型虚拟机?有点意思

用 Lua 实现一个微型虚拟机-基本篇 用 Lua 实现一个微型虚拟机-基本篇 目录 介绍 机器指令模拟 最终核心代码 虚拟机内部状态可视化 完整项目代码 后续计划 参考 介绍 在网上看到一篇文章 使用 C 语言实现一个虚拟机, 这里是他的代码 Github示例代码, 觉得挺有意思, 作者用很少的一些代码实现了一个可运行的虚拟机, 所以打算尝试用 Lua 实现同样指令集的虚拟机, 同时也仿照此文写一篇文章, 本文中大量参 阅读详情

目录

  1. 介绍
  2. 机器指令模拟
  3. 最终核心代码
  4. 虚拟机内部状态可视化
  5. 完整项目代码
  6. 后续计划
  7. 参考

介绍

在网上看到一篇文章 使用 C 语言实现一个虚拟机, 这里是他的代码 Github示例代码, 觉得挺有意思, 作者用很少的一些代码实现了一个可运行的虚拟机, 所以打算尝试用 Lua 实现同样指令集的虚拟机, 同时也仿照此文写一篇文章, 本文中大量参考引用了这位作者的文章和代码, 在此表示感谢.

准备工作:

  • 一个 Lua 环境
  • 文本编辑器
  • 基础编程知识

为什么要写这个虚拟机?

原因是: 很有趣, 想象一下, 做一个非常小, 但是却具备基本功能的虚拟机是多么有趣啊!

指令集

谈到虚拟机就不可避免要提到指令集, 为简单起见, 我们这里使用跟上述那篇文章一样的指令集, 硬件假设也一样:

  • 寄存器: 本虚拟机有那么几个寄存器: A,B,C,D,E,F, 这些也一样设定为通用寄存器, 可以用来存储任何东西.
  • 程序: 本虚拟机使用的程序将会是一个只读指令序列.
  • 堆栈: 本虚拟机是一个基于堆栈的虚拟机, 我们可以对这个堆栈进行压入/弹出值的操作.

这样基于堆栈的虚拟机的实现要比基于寄存器的虚拟机的实现简单得多.

示例指令集如下:

PSH 5       ; pushes 5 to the stack
PSH 10      ; pushes 10 to the stack
ADD         ; pops two values on top of the stack, adds them pushes to stack
POP         ; pops the value on the stack, will also print it for debugging
SET A 0     ; sets register A to 0
HLT         ; stop the program

注意,POP 指令将会弹出堆栈最顶层的内容, 然后把堆栈指针, 这里为了方便观察, 我们会设置一条打印命令,这样我们就能够看到 ADD 指令工作了。我还加入了一个 SET 指令,主要是让你理解寄存器是可以访问和写入的。你也可以自己实现像 MOV A B(将A的值移动到B)这样的指令。HTL 指令是为了告诉我们程序已经运行结束。

说明: 原文的 C语言版 在对堆栈的处理上不太准确, 没有把 stack 的栈顶元素 "弹出", 在 POP 和 ADD 后, stack 中依然保留着应该弹出的数据,,

虚拟机工作原理

这里也是本文的核心内容, 实际上虚拟机很简单, 遵循这样的模式:

  • 读取: 首先,我们从指令集合或代码中读取下一条指令
  • 解码: 然后将指令解码
  • 执行: 执行解码后的指令

为聚焦于真正的核心, 我们现在简化一下这个处理步骤, 暂时忽略虚拟机的编码部分, 因为比较典型的虚拟机会把一条指令(包括操作码和操作数)打包成一个数字, 然后再解码这个数字, 因此, 典型的虚拟机是可以读入真实的机器码并执行的.

项目文件结构

正式开始编程之前, 我们需要先设置好我们的项目. 我是在 OSX 上写这个虚拟机的, 因为 Lua 的跨平台特性, 所以你也可以在 Windows 或 Linux 上无障碍地运行这个虚拟机.

首先, 我们需要一个 Lua 运行环境(我使用Lua5.3.2), 可以从官网下载对应于你的操作系统的版本. 其次我们要新建一个项目文件夹, 因为我打算最终把这个项目分享到 github 上, 所以用这个目录 ~/GitHub/miniVM, 如下:

Air:GitHub admin$ cd ~/GitHub/miniVM/
Air:miniVM admin$

如上,我们先 cd 进入 ~/GitHub/miniVM,或者任何你想放置的位置,然后新建一个 lua 文件 miniVM.lua。 因为现在项目很简单, 所以暂时只有这一个代码文件。

运行也很简单, 我们的虚拟机程序是 miniVM.lua, 只需要执行:

lua miniVM.lua

机器指令集

现在开始为虚拟机准备要执行的代码了. 首先, 我们需要定义虚拟机使用的机器指令集.

指令集数据结构设计

我们需要用一种数据结构来模拟虚拟机中的指令集.

C语言版

在 C语言版 中, 作者用枚举类型来定义机器指令集, 因为机器指令基本上都是一些从 0 到 n 的数字, 我们就像在编辑一个汇编文件, 使用类似 PSH 之类的助记符, 再翻译成对应的机器指令.

假设助记符 PSH 对应的机器指令是 0, 也就是把 PSH, 5 翻译为 0, 5, 但是这样我们读起来会比较费劲, 因为在 C 中, 以枚举形式写的代码更具可读性, 所以 C语言版 作者选择了使用枚举来设计机器指令集, 如下:

typedef enum {
   PSH,
   ADD,
   POP,
   SET,
   HLT
} InstructionSet;

Lua版的其他方案

看看我们的 Lua 版本如何选择数据结构, 众所周知 Lua 只有一种基本数据结构: table, 因此我们如果想使用枚举这种数据结构. 就需要写出 Lua 版的枚举来, 在网络上搜到这两篇文档:

第一篇是直接用 Lua 使用 C 定义的枚举, 代码比较多, 就不在这里列了, 不符合我们这个项目对于简单性的要求.

第二篇是用Lua的table 模拟实现了一个枚举, 代码比较短, 列在下面.

function CreateEnumTable(tbl, index)   
    local enumtbl = {}   
    local enumindex = index or 0   
    for i, v in ipairs(tbl) do   
        enumtbl[v] = enumindex + i   
    end   
    return enumtbl   
end  

local BonusStatusType = CreateEnumTable({"NOT_COMPLETE", "COMPLETE", "HAS_TAKE"},-1)  

不过这种实现对我们来说也不太适合, 一方面写起来比较繁琐, 另一方面代码也不太易读, 所以需要设计自己的枚举类型.

最终使用的Lua版

现在的方案是直接选择用一个 table 来表示, 如下:

InstructionSet = {"PSH","ADD","POP","SET","HLT"}

这样的实现目前看来最简单, 可读性也很不错, 不过缺乏扩展性, 我们暂时就用这种方案.

从游戏开发到工业控制:Lua脚本在串口屏中的跨界应用实战 本文探讨了Lua脚本从游戏开发到工业控制的跨界应用,特别是在串口屏中的实战案例。通过分析Lua的轻量级、跨平台和热加载特性,展示了其在工业自动化中的高效表现,包括通信协议处理、性能优化和异常处理等关键场景,显著提升开发效率和系统可靠性。 阅读详情

相关推荐

给STM32H743这颗‘大脑’装上Lua脚本引擎:5.4.6版本移植实战与内存优化心得

本文详细介绍了如何在STM32H743单片机上移植Lua 5.4.6脚本引擎,并重点分享了内存优化的实用技巧。通过定制内存分配策略、调整虚拟机参数和按需加载标准库等方法,开发者可以在资源受限的嵌入式环境中高效运行Lua脚本,实现动态逻辑更新和系统扩展。文章还提供了性能调优和稳定性保障的实战经验,帮助开发者充分发挥STM32H743与Lua的组合优势。

weixin_28256233的博客 261

minilua:Lua的单文件端口,一种强大的脚本语言

minilua:Lua的单文件端口,一种强大的脚本语言

LUA-Projects:LUA系列小项目

LUA项目 概述 LUA是一种非常强大的脚本语言,WoW(魔兽世界)使用它来实现一些UI功能。 这些是一些简单的示例,可以开始使用LUA进行编码。 基本 该文件包含一些基本思想,以了解如何在LUA脚本中编写和调用函数。 它还具有随机种子初始化和用法。 简单的游戏 猜数字:用户猜模式 猜数字:cpu猜模式 剪刀石头布游戏 战斗竞技场 该游戏是一款格斗游戏,练习使用LUA进行加载/保存。 游戏基于斗兽场,玩家必须击败获得关卡的不同等级的敌人。 man子手 用LUA编程的经典子手游戏。 井字游戏 经典的井字游戏。 欧拉白板练​​习 6-查找1000以下3或5的所有倍数的总和。 7-前4000000个数字的斐波那契和。 8-最大素数600851475143。 9-第10 001个质数 建于 -但是您可以使用任何文本处理器。 贡献 请阅读以获取有关行为准则的详细信息,以及向我提交请

LuaVM:Lua的Lua虚拟机(和各种工具),因此您可以在Lua的同时进行Lua

LuaVM:Lua的Lua虚拟机(和各种工具),因此您可以在Lua的同时进行Lua

线性代数笔记【空间曲面】

二次曲面 曲面可以看成是一个动点或一条动曲线按照一定条件或规律运动产生的轨迹 曲面的方程即是该动点的坐标所满足的方程 空间解析几何中,一般会涉及到由曲面写方程和由方程看曲面两种类型问题 曲面与曲面方程 球面方程 球面:空间内与定点的距离等于定长的点的集合 这一定点叫球心,定长叫半径 标准方程 (x−x0)2+(y−y0)2+(z−z0)2=r2(x-x_0)^2+(y-y_0)^2+(z-z_0)^2=r^2(x−x0​)2+(y−y0​)2+(z−z0​)2=r2 球心P0(x0,y0,z0)P_0(

qq_40500005的博客 3245

Agent 团队管理手册:如何设定目标、分配角色与解决冲突

本文从Agent团队的底层逻辑出发,完整讲解了Agent团队管理的三大核心模块:目标设定(分层拆解+对齐校验)、角色分配(能力匹配+最优算法)、冲突处理(分类处理+仲裁投票),并提供了可直接运行的完整代码示例。通过本文的方法,你可以快速搭建一个高效协作的Agent团队,大幅提升复杂任务的完成效率和准确率。Agent团队是未来AI应用的核心形态,现在正是落地的黄金期,建议你从一个小场景开始动手实践,逐步优化自己的Agent团队管理方法论。

AI天才研究院 232

自制温湿度计——STM32-L432KC驱动lcd1602和dht11温湿度显示

先给大家甩一张图片哈(附上网址)简单说一下这块板子在这个小项目里的小缺点:一、引脚有点少,lcd1602本来有两种传输数据方式,一种是4bit,另一种是8bit,但是这块板子对于这个项目来说引脚有点少,所以建议用4bit模式。然而,在网上是很难找到设置4bit传输模式的lcd1602的,这也是为什么我写这个blog。二、mbed-os有时候会有大大小小的问题,搞人心态是真的。比如库函数离奇失踪,从官网上下载库函数失败,重装也解决不了然后莫名其妙好了。

m0_72994251的博客 3912

算力网:正在编织的“第二电网“

中国算力网:编织智能时代的"第二电网" 中国正在构建全国一体化算力网,目标让算力资源像水电一样即取即用。这一国家战略通过"东数西算"布局,将东部算力需求与西部清洁能源优势结合,形成三级时延圈(1ms城市级、5ms区域级、20ms国家级)。算力网采用三层架构:基础设施层的八大枢纽节点作为"发电厂",编排管理层的智能调度系统作为"调度中心",运营服务层提供标准化算力服务。关键技术包括算力路由、异构算力统一度量、无损网络和液冷技术等。

这只是一个博客 664

小白学电路之cadance搭建buffer电路

Buffer(缓冲器)是一种放大器或驱动电路,主要用于隔离输入和输出,以防止负载对前级电路造成干扰或影响。本文作者在电路方面是小白水平,目前正在学习,有不足之处欢迎指正。3.创建新的cellview,对此buffer进行仿真验证。2.创建buffer的symbol。电路中的V2的详细参数。

weixin_58051657的博客 1982

vmware虚拟机网络连接问题

主机:ubuntu14.04 Vitual Network Editor

入门虽易,精通不易,且学且珍惜! 1353

整车电检工艺流程

本文是笔者在从事汽车行业智能制造领域过程,对于整车电检工艺流程的理解与总结。

qq_40664711的博客 1万+

辐射制冷无规散射结构非球形散射体的结构优化与设计准则

本文针对辐射制冷材料中非球形散射体的光散射特性开展研究,提出了一种基于体积散射截面和不对称因子的综合评价方法。通过建立简化模型分析球体、圆柱体、长方体等六种几何形状在太阳波段的散射性能,发现金字塔形和圆锥形具有更强的后向散射能力。研究创新性地提出"反射因子SR=S(1-g)"这一评价参数,该参数与宏观反射率高度相关,为非球形散射体的优化设计提供了定量依据。仿真结果表明,合理选择散射体形状可显著提升辐射制冷材料的太阳反射率,为实现高效被动制冷提供了新的结构设计思路。

huanghm88的专栏 77

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

上一篇: 菜鸟程序员,你还在一看就会,一写就废吗?
下一篇: SQL中被忽视的HAVING你知道它到底有多重要吗?
linuxguitu
博客等级 码龄6年 117粉丝 163原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值