一个很简单的基于栈式过程虚拟机的实现,它运行目标平台【x86】的原生代码。

    本文提供的 “栈式过程虚拟机” 的实现,挂在本人的 github 上面,对想要深入了解 “栈式过程虚拟机” 的人,它或许可以起到一个不错的作用,但是本人建议一般性了解就可以了,另外顺带一提:如果你想要依靠它维持生活,在咋们国家是不可能不现实的,到时候你就只有 “多冷的隆冬 恨啊啊啊 在东北玩泥巴” 西北风吹啊吹;差不多这样子的凄惨。

    如果你真想要搞 “过程虚拟机” 这方面的东西,或许可以给你一个中肯建议,如果可以进 “Oracle、Google、Microsoft” 里面搞这个东西,那么,不要犹豫的去吧,不然就自己娱乐的玩玩就可以了,不要对任何人提起这个东西否则你会被一帮逗比们说成装逼的,突破国外技术封锁、自主研发是一种美丽的幻想,要是国内有人忽悠喊回国XX公司一定不要回来,国内无论是技术界还是这些个公司的风气各方面就不对,回来只有领药丸被各种政治斗争的关系户给干了。(当然要是一帮真正搞技术的人,在一起弄家公司搞的话,这个可以有!)

    准确的说有时我并不明白,你了解某些东西的时候,为什么别人总会把你视作装逼,或许这就是这些人为什么到现在都只是我眼中的很低级 “不入流” 的家伙的缘故把,挂着 “高级工程师”、“架构师” 的名头;干着 “不入流” 的事情,讲着不 “负责任” 的话,装着各种神乎其技的逼,拿着老外的东西当个宝,别人开源就自主就懂了~!可笑吧。

    当然 “过程虚拟机” 其实实现并不是大多数人们想象中的那般困难,好比弄弄操作系统内核拿着 “C/C++” 可劲的 “肝” 几个月的时间也能 “肝” 出一个可运行的 “超级简单的玩具内核” 出来,当然还有一点是成熟度、稳定性、效率方面的问题。

    我这个人非常憎恶装逼侠,所以本文的内容不建议各位装逼 “大佬” 观看,毕竟我只是个 “小菜鸟” 不是吗?您们都是大佬,当然在这块领域让我真正的崇拜的是搞 “模拟芯片” 真正的大佬,例如 PPU、GPU、CPU、电路芯片模拟,而不是搞 “过程虚拟机” 的大佬,他们之间的技术层次差距应该还是会比较大的,当然 “搞过程虚拟机” 里面还是有真正的大佬;来自一枚小菜鸟的 “盲目的崇拜”!崇拜大佬这是很正常的事情,因为知道它们厉害,看不到之间的距离,所以知道自己有多菜。

    栈式过程虚拟机,有很多的缺点也有很多的优点,好的一点就是说编码与实现容易而且容易理解,但坏的一点就是说效率方面会有一些问题,大量的R/D读写栈内存,内存I/O的效能,影响了整体的执行效能,而且它不与 “C/C++”、.NET CLR/JIT[Win32K]、V8-Engine 那般会利用 CPU 的高速缓存与寄存器条目之间进行优化,R/D 读写内存的效率与读写寄存器的效率差距还是有点明显【内存的效率低于R/D读写CPU寄存器条目或缓存的效能】,当然这是利用CPU的振荡态频率高精度测量下的情况【100ns为一个基本单位】,Win32k PDH 中提供了可用于测量CPU振荡态频率的C函数,不过纵然如此,它还是远远比 “过程解释器” 快的多的多,这点不用质疑;

    所以 “过程虚拟机” 又分了另外一种类别叫做 “基于寄存器的过程虚拟机” 而,“.NET CLR/JIT[Win32K]、V8-Engine” 都属于这一类型的过程虚拟机,它们可以提供很不错的目标平台原生代码的性能;另外实现一个相对完整一点,super simple 的栈式过程虚拟机,几千行代码的样子应该差不多。

    

    一般做一套 “栈式过程虚拟机” 你首先就需要定义一套 “栈式指令集” 规范,你可以沿用现成或比较熟悉顺手的指令集规范,比如我就比较习惯写 .NET MSIL 中间语言指令集,当然这不等于 “.NET CLR/JIT[Win32K]” 就是 “栈式过程虚拟机”,MSIL指令集是栈式的,但“.NET CLR/JIT[Win32K]” 即时编译后的 native-code 却不是,评价一个 “过程虚拟机” 是不是栈式的,不是看它或者别人怎么说,而是要拿它最终编译并在目标平台执行的 native-code 来说话,否则都是扯淡的,当然 SimpleClr 它只是一个很简单的过程虚拟机,说白了就是拿来搞这玩的东西,所以它只有几十个被实现可用的 MSIL 中间语言指令,当然搞这个东西我大概就花了一天不到的样子,两个中午加一个下午的时间;

   不要把它们想的太复杂,没有所谓复杂到不能理解的技术,它们只是有一定的门槛而已,还谈不上去太超前太火星,另外没有学习资料或文献这不是借口;可劲的去 “肝” 不停地去 “悟”,花时间早晚都能整懂,你可以从这里获取到这个虚拟机与即时编译并运行一段IL指令的 demo 的源代码 https://github.com/liulilittle/SimpleClr 

    另外本人在 github 上挂的代码是可以直接运行的,这类型的东西说再多其实很抽象,当然你是一名搞技术的天才那另当别论,当然既然是天才靠自己 “悟” 就可以了,它们也不是很需要参考这些代码了,最多也就是锦上添点花而已。

扫描二维码关注公众号,回复: 3610382 查看本文章

namespace SimpleClr
{
    using System;
    using System.Diagnostics;
    using System.Reflection.Emit;
    using System.Runtime.InteropServices;

    public static class program
    {
        public delegate int Bootloader();

        public unsafe static void Main(string[] args)
        {
            byte[] il =
            {
                clr.Nop,
                clr.Ldc_0, // int i = 0;
                clr.Stloc_0,
                clr.Ldloc_0, // IL_003
                clr.Inc,
                clr.Dup,
                clr.Stloc_0,
                clr.Ldc,
                0, 0, 0, 0, // constant
                clr.Clt,
                clr.Brtrue_s, // i < 1000 then goto IL_003
                3, 0, 0, 0, // label
                clr.Ldloc_0,
                clr.Ret,
            };
            *(int*)Marshal.UnsafeAddrOfPinnedArrayElement(il, 8) = 100000000; // 循环一亿次
            byte[] instructions = clr.Build(il);
            // 固定托管内存请求不要被移动设为非托管内存
            IntPtr address = GCHandle.Alloc(instructions, GCHandleType.Pinned).AddrOfPinnedObject();
            Bootloader bootloader = (Bootloader)Marshal.GetDelegateForFunctionPointer(address, typeof(Bootloader));
            // 把即时编译的函数转换成 bootloader
            int eax = 0;
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            {
                eax = bootloader(); // 引导即时编译的函数执行
            }
            stopwatch.Stop();
            Console.WriteLine("ticks={0}, eax={1}", stopwatch.ElapsedMilliseconds, eax);
            Console.ReadKey(false);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/liulilittle/article/details/82462632
今日推荐