COMET虚拟机的设计与实现(1)(2)
2013-12-08 01:35
导读:图3 指令格式 根据指令操作数据的类型的不同,可将COMET虚拟机的机器指令分为四种:寄存器-存储器型,存储器型,寄存器型,空操作数型。如果一个CO

图3 指令格式 根据指令操作数据的类型的不同,可将COMET虚拟机的机器指令分为四种:寄存器-存储器型,存储器型,寄存器型,空操作数型。如果一个COMET虚拟机指令不涉及主存储器操作(无ADR),则为1个字长,其他均为2个字长。2.6 字节码格式 字节码文件是COMET虚拟机的可执行文件。在启动虚拟机时,由命令行中的参数给出字节码文件名。字节码文件含有程序的长度、装载位置、程序指令等信息。虚拟机依据这些信息,将字节码中的指令从二级存储器装载到相应的虚拟机内存。这一系列操作和操作系统的程序加载器的工作情况类似[4]。 COMET虚拟机的字节码文件是一种二进制格式文件,格式如图4所示。

图4 字节码结构 其中addr为字节码在虚拟机内存的装载地址,len为字节码中指令的个数(不包含len和addr),ins1、ins2、…、insn为要载入虚拟机的指令。2.7 输入输出设备 文本中并没有明确定义COMET虚拟机的输入输出设备,只是给出IN、OUT几个IO操作宏指令。在这里,我们采用将外部设备寄存器在内存中统一编址的方法来处理输入和输出设备[1,3]。COMET虚拟机默认的I/O设备是键盘和显示器。利用操作系统提供的从定向功能用户也可以将它们重新定向到其他的设备。 COMET虚拟机输入输出设备的两个专用寄存器为:IO_ADDR、IO_FLAG,分别对应0xFD100、xFD10地址内存。IO_ADDR用于保存要传输数据的内存地址;IO_FLAG为IO设备的标志位,其8-15位是要传输数据的个数(0表示无IO),7位表示输入或输出(1表示输入,0为输出),6位在出现IO错误时设置,3-5位为传输的类型(有字符、八进制、十进制、十六进制等),0-2位保留。2.8 调试器COMET调试器是一个内嵌在虚拟机里的机器级的调试器。当需要调试一个COMET虚拟机的程序时,只需要在启动COMET虚拟机的时给出相应的命令参数就启动调试功能了[2,4]。 COMET调试器的基本功能有:显示帮助(help),运行程序直到停止(go),分步执行(step n),跳转程序(jump),显示寄存器内容(regs),显示内存数据(dMem),显示内存指令(iMem),修改内存数据(alter),遍历指令(trace),指令记数功能(print),重新装载字节码(clear),退出调试器(quit)。每个调试命令的具体用法可以参考COMET虚拟机的帮助文件。3 COMET虚拟机实现3.1 虚拟机数据结构struct comet{ off_t pc; short fr; short gr[5]; short mem[MEMSIZE];} cmt; 虚拟机结构变量cmt是一个全局变量,成员分别为:指令计数器(pc)、标志寄存器(fr)、通用寄存器(gr)、存储器(mem)。将cmt设计为全局变量的优点是个函数不用传递复杂的结构体参数,缺点是每个进程同时只能有一个虚拟机实例。3.2 主函数intmain(int argc, char *argv[]){ init(argc, argv); if(debug) comet_debug(); else while(comet_step()); fclose(source); return 0;} 函数init首先初始化COMET虚拟机并装载字节码,如果发生错误则停止。然后根据调试器状态,选择运行虚拟机的方式。如果调试开关(debug)被设置,则调用comet_debug函数在调试状态下运行COMET虚拟机。如果没有打开调试开关,则循环调用单步执行函数comet_step,直到程序结束[1,2]。3.3 字节码载入voidcomet_load(void){ unsigned short n, flag[2]; fseek(source, 0, SEEK_SET); n = fread(flag,sizeof(off_t), 2, source); n = fread(