为了进一步了解虚拟机是如何解释执行任意一段与当前指令集相符的程序,阅读了一篇关于基于寄存器的的虚拟机实现的相关文章。
虚拟机的设计与实现
虚拟机原理
虚拟机用软件模拟指令在硬件机器中执行的全过程,即先从磁盘中读取字节码文件 ,存储到虚拟机开辟的内存段中,再将指令加载到虚拟机寄存器并予以执行。它并不是指某个特定的软件 ,而是一整套完整的规范,可以用不同的程序设计语言在不同的硬件平台上实现。不论是硬件机器还是虚拟机系统 ,只要遵循相同的规范,即可运行遵循该规范的可执行代码。
两种处理器引擎
Stack-Based虚拟机在运行时对系统资源的消耗要远小于Register-Based虚拟机 ,但堆栈将会延伸到内存 ,后者的计算处理则全部在芯片内部的寄存器上完成,因此后者的处理速度要远远高于前者。
虚拟机的工作流程
1.启动虚拟机,并处理命令行输入
2.初始化虚拟机运行环境
3.调入并加载文件
4.格式化内存存储方式
5.执行指令
其中虚拟机的初始化和执行字节码阶段是整个程序运行的核心
初始化虚拟机
通过输入命令行,获取字节码文件的信息,并传入处理函数。在myvm中其实就是将文件送入sub_CE0()中,将字节码字段加载到 内存空间的正文段。为了清楚的描述sub_CE0()的功能,将它的算法提炼出来如下:
1 | if(文件大小为零或文件打开错误) |
执行字节码
加载好字节码内容后,就该将这些字节码翻译执行了。把这些字节码送入指令执行引擎函数sub_E90中,将字节码指令从虚拟地址0处开始逐条执行,当遇到HALT指令或发生错误时停止。参照基于寄存器的处理器的设计方法 ,此阶段指令执行过程的算法如下(其中,R[IP]表示指令指针寄存器IP的值 ;RAM[R[IP]]表示 内存地址为R[IP]处的指令或数值):
1 | while(内存地址为r[iP]不等于中止指令HALT){ |
其实准确来讲myvm中sub_E90函数执行的是中间switch那段,用于识别各种机器指令,并执行。
机器指令按照操作数的不同来分,包括双操作数指令(OP DEST,SRC)、单操作数指令(OPDEST)、无操作数指令(op)等3种。由于操作数的不同直接关系到指令指针IP的变化不同,因此R[IP]值的变化将因具体指令的操作数不同而异。下面通过 LAI R1,R2,qword指令来解释具体的指令执行过程 。
指令功能:将基地址(reg2)和地址偏移量(8 bytes常量)相加得到的结果存入目的寄存器中
指令流程:
1 | 寄存器1=寄存器2的值+8字节常量 |
总结
通过今天的学习验证了之前代码的分析,也初步明确sub_E90中switch分支的结构,下一步应该对switch每一条语句进行分析,识别出每一个分支具体实现了哪条指令。