电脑技术学习

一份关于两个汇编语言级别模拟CPU的虚拟机的分析文档

dn001
1)虚拟机是什么?

"虚拟机"的概念其实很广,最常见的有以下两种虚拟机,第一种是模拟"裸机"运行的虚拟机,这样的虚拟机有VMWAREVirturePC,Bochs等,另一种是模拟操作系统运行情况的虚拟机,这样的虚拟机有Wine,JVM(java虚拟机)。其实,虚拟机就是一个中间层,可以理解为是两种环境的桥梁,如果把虚拟机的概念抽象一点描述,可以认为虚拟机是在某一个环境上模拟另一种环境运行情况的软件,这样的环境可以是不同的cpu,不同的os....等等。

这里选择的是两个非常简单的虚拟机,一个是<<编译原理与实践>>一书中自带的TM虚拟机,另一个是<<程序员>>杂志2003年第六期里的一篇文章<<一个小型虚拟机的实现>>中实现的虚拟机,两者都有一个共同点,就是两者都是在汇编语言级别虚拟cpu运行情况的虚拟机,正因为这两个虚拟机的如此定位,所以在实现或者阅读这两个虚拟机的时候,你不得不从cpu的角度去思考问题,你必须对cpu的运行情况有了解,反过来说,阅读这两个虚拟机的源码也可以加深对cpu工作原理以及汇编语言的理解。这两个虚拟机的源码都可以在网上找到,前者在http://www.mathcs.sjsu.edu/faculty/louden/cmptext/,而后者可以在CSDN的网站上查找2003年第六期的源码。值得一提的是,CS:APP(<<深入理解计算机系统>>)一书中也有一章专门讲述CPU的运行原理,而且作者也自己实现了一个CPU,而且还是流水线型,所以这个虚拟机功能更酷也更加强大,因为作者自己定义了一种硬件语言来描述cpu,最后还有在这种cpu支持的汇编指令,在有Tcl/Tk的环境下还带有图形界面,非常直观,可以在http://csapp.cs.cmu.edu/public/students.html里的Chapter 4:Processor Architecture中找到源代码。

2)设计一个汇编语言级别的虚拟机的要求

学习过计算机原理的人都知道,一个cpu至少需要有以下几个部件:a)内存,装载所要执行的指令之用;b)寄存器;3)指令集,没有指令集执行指令就无从谈起。前两者非常简单,无非就是在内存中分配一个空间来模拟就可以了,而后者这里要专门说明一下。我们知道任何高级语言,经过这个高级语言的编译器编译之后都是翻译成汇编语言的,然后由汇编器汇编成二进制文件最后再进行库的链接等等才形成了可执行文件,而可执行文件最终也是二进制格式的,在执行可执行文件的时候由加载器加载到内存中去,那么这里就有一个问题了:cpu是如何识别已经加载到内存中二进制文件并且正确执行的?这需要下面的一个概念:OpCode。

OpCode是什么?简而言之,OpCode就是与汇编指令相对应的二进制格式的代码,OpCode的英文名是OperationCode(中文可以翻译成"操作码"),每一个汇编指令都有一个相对应的OpCode格式,反之不然,不过这个问题这里不再深究,只需要知道汇编器把汇编指令翻译成相应的由opcode组成的二进制文件,这样在可执行文件加载到内存的时候,cpu就可以根据在可执行文件中的opcode来执行程序了。理论上来说,不同厂家的cpu所支持的opcode是不的,那么这里就有一个问题了,比如说在Intel机子上编译成功的可执行文件到了AMD的机子上如何正确执行呢?如果没有猜错的是,每个cpu在实现的时候需要在cpu的上层加一个翻译指令的东东....具体的我不清楚,只是猜测而已,也许不对。扯了这么多,回到这里要实现的cpu上,因为只是简易的cpu,所以opcode上也尽量的精简,在这两个虚拟机的实现中,都是采用了汇编指令和opcode一一对应的关系进行实现(记住我前面说过汇编指令和opcode在真正的cpu中并不是一一对应的!),这样简化了cpu的实现。关于opcode,网上有一份不错的教程<<学习opcode>>:http://www.luocong.com/learningopcode.htm,遗憾的是作者从开始写这份教程一直到现在差不多两年时间过去了还没有完成,不过前面的文章对于理解opcode的基本概念已经足够了。opcode看起来好像很高深,其实它就在我们身边,在linux上有一个objdump的反汇编软件可以反汇编二进制文件,比如这样的一段反汇编的代码:

代码:

116: 89 e5 mov %esp,%ebp

其中的116是指令地址,而89 e5就是指令mov %esp,%ebp 所对应的opcode。

总结一下,设计一个汇编语言级别的虚拟机至少需要以下的部件:1)内存空间,用于存放机器指令之用。2)寄存器:用于保存程序运行的状态,暂存数据等等之用。3)汇编器,汇编器的功能就是把汇编指令翻译成cpu指定的机器指令,然后将指令装入虚拟机的内存之中。4)指令集,指令集包括了指令的助记符,也就是汇编语言中的指令,还需要有每个指令所对 应的机器指令也就是OpCode,助记符由汇编器处理翻译成为机器指令,最后在cpu执行的时候根据不同的机器指令来执行相关的操作。

虽然这两个虚拟机的设计略有不同,但是由于都是模拟的汇编语言级别的cpu,所以工作过程大体都是一致的,把握这个运行的过程是正确掌握这两个源代码的关键所在!虚拟机运行的大体过程如下:首先由汇编起扫描汇编源文件,将汇编指令也就是机器指令的助记符翻译为机器指令,如果没有错误就把机器指令加载到内存之中,这时汇编器的任务就结束了;然后由虚拟机读取已经装载到内存中的机器指令,根据机器指令对应的操作来执行指令。
ok,这里基本上把一些基本的概念解释完了,后面紧跟着就可以开始我们的虚拟机之旅了....