关 闭

新闻中心

EEPW首页 > 工控自动化 > 设计应用 > COMET虚拟机的设计与实现

COMET虚拟机的设计与实现

作者: 时间:2012-07-10 来源:网络 收藏

2.8 调试器

调试器是一个内嵌在里的机器级的调试器。当需要调试一个的程序时,只需要在启动的时给出相应的命令参数就启动调试功能了[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 主函数

int

main(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 字节码载入

void

comet_load(void)

{

unsigned short n, flag[2];

fseek(source, 0, SEEK_SET);

n = fread(flag,

sizeof(off_t), 2, source);

n = fread(cmt.mem[flag[0]],

sizeof(off_t),tmp[1],source);

/* 其他处理代码 */

}

变量n用于记录读取字节码的数目,如果n小于相应的值,则发生字节码装载错误。变量flag用于保存字节码装载信息,分别字节码装载地址和字节码大小。

COMET字节码设计比较简单,也存在很多不足。例如,没有标志文件格式的魔数,没有更完善的错误检测措施。我们的目的是让读者了解字节码的工作原理,因此只给出了一种最简单的实现[1,2,4]。

3.4 指令解析

指令的解析一般包含这个几个过程:取指令,解码,执行。其中解码对虚拟机的执行效率有很大的影响[5]。这里采用下标索引技术来解码指令。具体代码如下:

void comet_ld(void); /* LD指令*/

void comet_ld(void); /*ST指令 */

void comet_ld(void); /* LEA指令 */

/* 其他指令函数声明 */

int comet_step(void)

{

static void (*comet_op)() = {

comet_ld, comet_st, comet_lea,

/* 其他指令执行函数指针 */

};

/* 解析指令,存放在op中 */

short op = get_op();

/* 执行op对应的代码 */

(*comet_op [op])();

/* 返回执行状态 */

return val;

}

例如,有指令LEA,其对应的机器码为031,那么将通过函数指针数组comet_op直接定位到(*comet_op[031])函数,即并执行相应的comet_lea函数。

3.5 输入输出设备

COMET虚拟机在解析每个指令前,先读取IO设备状态寄存器IO_FLAG中的值,如果IO_FLAG被设置,则执行相应的IO操作[3]。具体代码如下:

void

comet_io(void)

{

switch(cmt.mem[IO_FLAG]IO_TYPE)

{

case IO_NULL:

/* 无IO操作 */

case IO_OCT IO_IN:

/* 八进制输入 */

case IO_DEC IO_IN:

/* 十进制输入 */

case IO_HEX IO_IN:

/* 十六进制输入 */

case IO_OCT IO_OUT:

/* 八进制输出 */

case IO_DEC IO_OUT:

/* 十进制输出 */

case IO_HEX IO_OUT:

/* 十六进制输出 */

default:

/* 未知IO类型 */

}

/* 重置IO状态寄存器IO_FLAG */

}

3.6 调试器

调试程序是建立和单步执行的COMET虚拟机之上的。当没有打开调试功能时,循环执行COMET虚拟机字节码程序,直到停止。当打开了调试功能时,调试函数debug根据调试命令,执行相应步的指令、显示或操作相关的数据。

/* 各种调试命令 */

typedef enum

{

GO, STEP, JUMP, REGS,

IMEM, DMEM, ALTER,

TRACE, PRINT, CLEAR,

HELP, QUIT

} DbType;

/* 调试函数 */

void

comet_debug(void)

{

int cmd; /* 保存调试命令 */

while(1) {

/* 读调试命令 */

switch(cmd) {

case HELP: /* 帮助文件 */

case GO : /* 执行程序 */

case STEP: /* 分步执行 */

/* 其他调试命令 */

default : /* 未知命令 */

}

}

}

调试函数comet_debug根据不同的调试命令执行相应的操作,并显示虚拟机状当前的状态信息。

4 运行虚拟机

下面通过一个求(1 + 2 + … + n)的程序,来介绍其在COMET虚拟机上的执行的流程。程序的字节码由相关的工具生成,保存为sum.comet文件(后缀为comet)。

4.1 普通运行

输入命令:comet sum

在COMET虚拟机获得sum参数后,会自动识别为sum.comet字节码文件。

输入100,表示求1+2+…+100的和。

COMET虚拟机输出:

===============

COMET虚拟计算机

存储器相关文章:存储器原理


尘埃粒子计数器相关文章:尘埃粒子计数器原理


关键词: COMET 虚拟机

评论


相关推荐

技术专区

关闭