8x8点阵滚动纯c语言模拟_【虚拟机系列】C语言虚拟机诞生!

1efdaf8594812900f34cf66e74bdffa7.png

【置顶】详细说明地址:bajdcc/clibparser,目标:C语言为脚本的虚拟操作系统(+后期的图形界面),运行时动态加载code文件夹下的代码。用途:目前只是实验品,因为只有黑框框,没啥娱乐特性,后期加上美丽的GUI后可以做窗口、菜单、APP、游戏等东西。cpp脚本代码支持#include,与虚拟机的一级通信借助interrupt指令(IR),与虚拟操作系统的通信后期会采用VFS(如cat /proc/0/exe是打印pid为0的进程路径,那么cat /proc/0/kill也许就能kill这个进程了),像是ll命令就等同于ls -l=shell("ls -l XX")=shell("cat XX:ls"),即一个路径加:冒号,会执行后面的语义动作。那为什么不直接像之前的陈安:【游戏框架系列】开篇那样搞lua+gui呢?因为我觉得lua与gui间的束缚太严重,因此不如自己搞套gui接口,反正操作系统都自己模拟出来了。说实在的,实验品归实验品,没人会去了解windows、unity是怎么做出来的,只会去了解应用程序、游戏是怎么制作的,说clibparser不实用,那就不实用呗,写代码又不是为了追求啥意义,自己开心就行。

【置顶2】前期的虚拟机命令行全部没啥问题,后期的GUI设计存在许多坑(难度相当大),由于GUI是高度抽象化的,除了显示元素外还会有许多实时消息要程序处理。不做GUI时clibparser已过万行了,加个GUI估计起码2万行。

【置顶3】这个项目是铺垫了很久的,我写过N个语法分析器,包括C#、java、C++等形式,并且在栈虚拟机实验项目bajdcc/jMiniLang中实现了大部分好玩的特性(由于Java的库很多,有GC,因此特性很简单就能实现,如yield等)。N个GUI项目(C#、MFC、D2D:bajdcc/GameFramework、Java)等。一个操作系统bajdcc/MiniOS。对编译器、虚拟机、操作系统、图形界面有了一些认识,因此也就有了clibparser的诞生。然而,由于代码比较搓,暂时也没有让他人参与的想法(我应该还能hold住一万行左右的代码)。有评论说有意义也有说没意义的,有道理的我都会接受。


【更新】19/02/11

  • 下列画爱心代码出自:bajdcc/clibparser,原作者:miloyip
  • 完美支持各类显式、隐式类型转换!(包括char(1B) short(2B) int(4B) long(8B) float double ptr),函数参数可隐式转换
  • 初步链接数学库是没问题了(目前签名是double)
  • 目前有输出流不能及时处理的bug(应该是没接收完就退出了)——问题已解决,忘记重置输入流关闭标志了TVT
  • heart3程序时IPS为60M左右(每秒6000万虚拟指令),极限为200M左右,纯CPU运算时比bajdcc/jMiniLang体现出优势(几乎不会申请内存,架构上有优势)
  • shell支持按上下键切换历史记录了,当然可以输history看记录

48887038ab9e95650d897ad72f0ef7a0.gif
画爱心小程序可以运行啦~~~

【更新】19/02/04

  • 添加了/dev/random和/dev/null,接口很丑陋,不过不用在意
  • 可以显示IPS(一秒内指令数),并且根据FPS自动调整IPS(导致不会太卡。。)
  • 支持了Ctrl-C,方法是Shell将任务分为前台任务和后台任务,Kill掉全部前台就可以了
  • 安装了badapple小程序(=V=)(对我来说像helloworld一样重要)(代码https://github.com/bajdcc/clibparser/blob/master/code/usr/badapple.cpp)

24142bb791c5038f22c09d1ab3c0bb21.gif
命令为“cat /dev/random | od”可以按Ctrl-C啦~

f029062a884bffcd93df6f1c7e5584d6.gif
badapple字符画测试~~~

【更新】19/02/02

编译:支持简单的结构体/union/指针,支持嵌套struct/union,示例代码中已完成链表,命令行敲“/usr/test_struct”可看结果。(https://github.com/bajdcc/clibparser/blob/master/code/usr/test_struct.cpp)

更新命令行读写。

3b5b1723a978b36933447bc46085f67a.gif
命令行读写

【更新】19/02/01

加入显示文件树的功能。

381b8481b7d929283a0acde1eac605e1.gif
列举文件树

【更新】19/01/31

加入对颜色的支持。

680c5cd3537bf05552db29a0955f1f9e.gif
有颜色啦~

【更新】19/01/29

加入了对文件系统(伪)的支持。(知乎竟然不支持半分钟以上的gif)

80592aa304a34dad0ad8126c6739e59c.gif
(伪)文件系统

【更新】19/01/26

实现:

  • malloc, free
  • 命令行管道

说明:

欢迎友好交流,友善评论。
本项目只是一个实验品,这点不必再强调。仁者见仁,智者见智。
本程序的最终目标是虚拟出一套GUI(不是现在的黑框框),在这之上要做一些游戏、界面都是可以的(代码可以跨平台,暂时没在linux上试过)。在这个过程中的一切操作都是实验性的。

8d8ca026306b19153fa80b813fb1affd.gif
命令行管道

【更新】19/01/21

由于clibparser在起步阶段,读文件的接口暂时还没做(因此不能命令行直接解释C文件了),打算先搞多任务系统以及类似动态链接那样的东西,步骤是将C文件编译成两个段——代码段和数据段,然后加载到内存空间中,那么不同的源代码加载到不同的空间中即可,要链接的话,保存下函数签名和地址就行。读取二进制文件的步骤——利用虚拟文件系统加载文件内容到内存空间中然后执行。

任务比较多,因此可能需一段时间才能显露雏形。

回答几个问题——

  1. cliblisp的控制流——自己水平不高,因此对call/cc要有研究才可实现(当然靠copy的没意思了)。网上都是教你如何用call/cc,很少教你去实现它。我不是用lisp去做东西,而是做lisp本身。
  2. clibparser干嘛用的?——可以将其看作qemu,但不完全是。我是想仿个操作系统带界面罢了,做语法分析属于边角料内容。
  3. 不是会用工具就可以了,要去了解工具本身是如何运作的,也就是俗话说的造轮子
  4. clibparser纯属toys(实验性项目),有兴趣就去了解,没兴趣就算了。

【更新】19/01/20

bajdcc/clibparser

由于有cliblisp项目的代码,因此直接移植UI代码,瞬间搞定GUI。

示例代码(已经支持了超多语法!):

enum 

上述代码没有使用标准库,与UI的交互通过interrupt实现(看作中断)。

参数:FPS=30,每帧虚拟机指令执行1000次。Release下1秒跑完。(其实并行也可以,但会有UI刷新的问题。)

效果:

UI抄了bajdcc/cliblisp。

dd0603f6a10fc5bb7311134d1359c068.png
效果图

【本系列原本为parser系列,因语法分析部分已基本完成,因此后续的重点会放在虚拟机设计上。故此更名为虚拟机系列~】

经过一番番的努力,制作的第一个C语言虚拟机诞生了!

目前支持语法如下:

a41452076178edd5081ef76391e385ab.png
支持的语法

综观整个clibparser,那么其中我严重参考并感谢的有:

  1. LR分析核心代码及思路——轮子哥的vczh-libraries/Vlpp
  2. C语言寄存器式简易虚拟机及前期指令设计——lotabout/write-a-C-interpreter

自己的微小贡献之处有:

  1. 内存池:负责语法树的内存管理
  2. 虚页管理:负责虚拟机中的地址转换
  3. 对LR分析的优化,解决其中的二义性问题
  4. 其余的在词法分析、语法分析、语义分析、AST生成、指令生成中涉及到的代码

当然,我的目标并不是做一个C语言虚拟机就好了,这个虚拟机可是拿来用的!

先前的陈安:【Lisp系列】启用LR文法!中尝试了用lisp语言去做虚拟机,但会有一个问题:lisp中的循环难以实现,而循环作为控制流语句最关键的就是含有跳转指令,而cliblisp虚拟机是以函数指针为参数,进行trampoline式回调的,因此无法实现跳转,所以cliblisp我就弃了。。尝试失败。

clibparser目前可以编译并运行:

int 

递归及基本的控制流语句毫无压力,虽然指令生成部分代码比较不美观,但真的比我之前写的任何一款指令生成器都好看。

后续支持指针和结构体之后 ,clibparser会更加强大。

调用方式

#include 

要支持从文件读取并运行的话很简单,修改root的来源即可。

虚拟机运行实况

截取一段:

0001> [C000009C] 08 ENT 0000001C(28)

---------------- STACK BEGIN <<<<
AX: 00000000 BP: E0000FF0 SP: E0000FD4 PC: C00000A0
[E0000FD4]> 00000000
[E0000FD8]> 00000000
[E0000FDC]> 00000000
[E0000FE0]> 00000000
[E0000FE4]> 00000000
[E0000FE8]> 00000000
[E0000FEC]> 00000000
[E0000FF0]> 00000000
[E0000FF4]> E0000FF8
[E0000FF8]> 0000000D
[E0000FFC]> 00000028
---------------- STACK END >>>>

0002> [C00000A4] 01 LEA FFFFFFFC(-4)

---------------- STACK BEGIN <<<<
AX: E0000FEC BP: E0000FF0 SP: E0000FD4 PC: C00000A8
[E0000FD4]> 00000000
[E0000FD8]> 00000000
[E0000FDC]> 00000000
[E0000FE0]> 00000000
[E0000FE4]> 00000000
[E0000FE8]> 00000000
[E0000FEC]> 00000000
[E0000FF0]> 00000000
[E0000FF4]> E0000FF8
[E0000FF8]> 0000000D
[E0000FFC]> 00000028
---------------- STACK END >>>>

0003> [C00000AC] 13 PUSH E0000FEC

---------------- STACK BEGIN <<<<
AX: E0000FEC BP: E0000FF0 SP: E0000FD0 PC: C00000AC
[E0000FD0]> E0000FEC
[E0000FD4]> 00000000
[E0000FD8]> 00000000
[E0000FDC]> 00000000
[E0000FE0]> 00000000
[E0000FE4]> 00000000
[E0000FE8]> 00000000
[E0000FEC]> 00000000
[E0000FF0]> 00000000
[E0000FF4]> E0000FF8
[E0000FF8]> 0000000D
[E0000FFC]> 00000028
---------------- STACK END >>>>

这里就要感谢VMM虚页机制了,clibparser定义的四个段为:

3e2800b65cb50edaae2a13cc8c1a24c9.png
定义的段基址

虚页机制支持权限控制,目前还未使用起来。

全局数据、字符串保存在数据段中,生成的指令保存在代码段中,程序运行使用栈,堆的话在后面支持malloc语法会用到(会以系统调用实现)。

后续计划

在题图上已有涉及:走模拟操作系统的老路,希望这次可以比bajdcc/jMiniLang做得更好。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值