📄 cometvm.cpp
字号:
// CometVM.cpp: implementation of the CCometVM class.
//
//////////////////////////////////////////////////////////////////////
#include "Stdafx.h"
#include "CometVM.h"
#include "CaslUtil.h"
#include "XmlErrorHandler.h"
#include "aslIFStream.h"
#include "DebugCmd.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CCometVM::CCometVM() : m_icVMMemoryLimit(64 * 1024)
{
//------------------变量定义部分 begins------------------------------
int iRet = 0;
//------------------变量定义部分 ends--------------------------------
m_pConstMemoryBase = NULL;
m_pInstructionMemoryBase = NULL;
m_pVarMemoryBase = NULL;
m_pVMMemoryBase = NULL;
m_FR = 0;
m_PC = 0;
m_iStackBottom = 0;
m_GR[0] = 0;
m_GR[1] = 0;
m_GR[2] = 0;
m_GR[3] = 0;
m_GR[4] = 0;
}
CCometVM::~CCometVM()
{
if (m_pVMMemoryBase != NULL)
{
delete []m_pVMMemoryBase;
}
#ifdef WINDOW_MODE
m_console.ExitConsole();
#endif
}
/////////////////////////////////////////////////////////////////////////
//函数名称:InitVM
//函数功能:---------------------初始化虚拟机的运行环境----------------------
//入口参数:无
//出口参数:无
//返回值:int--------------STATUS_OK表示操作成功,其他表示操作出现问题
//开发人员:杨军
//开发日期:2004-4-18
//修改人员:
//修改日期:
/////////////////////////////////////////////////////////////////////////
int CCometVM::InitVM()
{
//----------------分配64KB的内存作为虚拟机的工作内存使用---------------
//m_pVMMemoryBase = new (nothrow)S1[64 * 1024];
try {
m_pVMMemoryBase = new S1[64 * 1024];
}
catch (exception e)
{
cout << "error" << endl;
}
//----------------初始化堆栈-------------------------------------------
//为堆栈默认分配1K的空间(63 * 1024 ----> 64 * 1024)
//设置栈底指针(注意: 这个值是一个相对虚拟机工作内存基址的偏移)
m_GR[4] = static_cast<short>(64 * 1024 - 38);
m_iStackBottom = m_GR[4];
//----------------初始化寄存器组的值-----------------------------------
m_GR[0] = 0;
m_GR[1] = 0;
m_GR[2] = 0;
m_GR[3] = 0;
m_FR = 0;
m_PC = 0;
//----------------创建虚拟机输入,输出数据使用的控制台窗口--------------
//unfinished
//---------------初始化错误日志记录------------------------------------
m_errorHandler.SetLogFilePrefix("CometVM");
m_errorHandler.BeginErrorLog();
return STATUS_OK;
}
/////////////////////////////////////////////////////////////////////////
//函数名称:ExitVM
//函数功能:---------------------结束虚拟机的运行----------------------------
//入口参数:无
//出口参数:无
//返回值:int--------------STATUS_OK表示操作成功,其他表示操作出现问题
//开发人员:杨军
//开发日期:2004-4-19
//修改人员:
//修改日期:
/////////////////////////////////////////////////////////////////////////
int CCometVM::ExitVM()
{
delete []m_pVMMemoryBase;
m_pVMMemoryBase = NULL;
//-----------关闭控制台窗口------------------------------------------
#ifdef WINDOW_MODE
if (m_console.IsConsoleStarted())
{
m_console.ExitConsole();
}
#endif
//-----------关闭错误日志记录-----------------------------------------
m_errorHandler.EndErrorLog();
return STATUS_OK;
}
/////////////////////////////////////////////////////////////////////////
//函数名称:LoadExeFile
//函数功能:---------------------装入一个可执行文件--------------------------
//入口参数:const char * argExeFile---------------------------要装入的文件
//出口参数:无
//返回值:int--------------STATUS_OK表示操作成功,其他表示操作出现问题
//开发人员:杨军
//开发日期:2004-4-18
//修改人员:
//修改日期:
/////////////////////////////////////////////////////////////////////////
int CCometVM::LoadExeFile(const char * argExeFile)
{
//----------------变量定义部分 begins-----------------------------
CaslIFStream ifStream;
CaslExeHeader exeHeader;
int i = 0;
int iSize = 0;
int iRet = 0;
U2 u2Temp1 = 0;
U2 u2Temp2 = 0;
S1 s1Temp = 0;
//----------------变量定义部分 ends-------------------------------
#ifdef WINDOW_MODE
//启动控制台,为虚拟机的运行作准备
iRet = m_console.StartConsole();
if (iRet != CConsoleManage::CONSOLE_WORK_OK)
{
if (CConsoleManage::CONSOLE_ALREADY_STARTED == iRet)
{
MessageBox(NULL, _T("Console Already Exists!"), _T(""), MB_OK);
}
else
{
MessageBox(NULL, _T("Console Start Failed!"), _T(""), MB_OK);
}
return STATUS_FAILED;
}
#endif
//-----将Exe文件中的内容读到虚拟机的工作内存中-----------------------
//打开指定的可执行文件
try
{
ifStream.open(argExeFile, ios::in | ios::binary);
if (ifStream.is_open())
{
//-----------进行变量,常量部分的初始化工作------------------------
//读入文件头的内容,以完成运行可执行文件的初始化工作
ifStream >> exeHeader;
//设置变量区的起始内存地址
m_pVarMemoryBase = m_pVMMemoryBase;
//设置常量区的起始内存地址
m_pConstMemoryBase = m_pVarMemoryBase + exeHeader.variableAreaSize * 2;
//设置指令区的起始内存地址
m_pInstructionMemoryBase = m_pConstMemoryBase + exeHeader.constAreaSize * 2;
//将变量区预置为零
memset(m_pVarMemoryBase, 0, exeHeader.variableAreaSize * 2);
//读入可视化调试信息
iSize = exeHeader.iVisualDebugInfoSize / sizeof(InstructionDebugInfo);
m_vecVisualDebugInfo.clear();
for (i = 0; i < iSize; i++)
{
ifStream >> u2Temp1;
ifStream >> u2Temp2;
m_vecVisualDebugInfo.push_back(InstructionDebugInfo(u2Temp1, u2Temp2));
}
//从可执行文件中将常量区的数据复制到内存中的常量区中
for (i = 0; i < exeHeader.constAreaSize * 2; i++)
{
ifStream >> s1Temp;
*(m_pConstMemoryBase + i) = s1Temp;
}
//从可执行文件中将指令复制到内存中的指令区中
//直到文件结束
i = 0;
while (!ifStream.eof())
{
ifStream >> s1Temp;
*(m_pInstructionMemoryBase + i) = s1Temp;
i++;
}
//关闭打开的可执行文件
ifStream.close();
//----------设置相关的寄存器的值----------------------------------
//设置PC偏移
m_PC = exeHeader.variableAreaSize + exeHeader.constAreaSize;
m_ExecCodeStart = m_PC;
//m_PC = 0;
}
else
{
CXmlErrorHandler::ShowErrMsg("Open Exe File Failed");
return STATUS_FAILED;
}
}
catch (...)
{
CXmlErrorHandler::ShowErrMsg("File I/O operation Failed!");
if (ifStream.is_open())
{
ifStream.close();
}
return STATUS_FAILED;
}
return STATUS_OK;
}
/////////////////////////////////////////////////////////////////////////
//函数名称:Run
//函数功能:---------------------开始运行装入的可执行文件--------------------
//入口参数:无
//出口参数:无
//返回值:int--------------STATUS_OK表示操作成功,其他表示操作出现问题
//开发人员:杨军
//开发日期:2004-4-18
//修改人员:
//修改日期:
/////////////////////////////////////////////////////////////////////////
int CCometVM::Run()
{
//------------------变量定义部分 begins-------------------------------
int iRet = 0;
//------------------变量定义部分 ends-------------------------------
//---------------执行指令---------------------------
//这是一个死循环,因为程序执行的终止是以遇到Exit指令为据的
m_errorHandler.WriteErrorMessage("Starts to execute instruction:");
while (1)
{
//首先从当前PC处读出一条指令
if (STATUS_OK != ReadInstruction())
{
goto Run_Failed;
}
//检验指令是否正确
if (!VerifyInstruction())
{
m_errorHandler.WriteErrorMessage("指令格式不正确");
CXmlErrorHandler::ShowErrMsg("指令不正确,退出虚拟机");
m_errorHandler.EndErrorLog();
exit(-1);
}
//执行到程序结束点,可以退出程序的执行流程了
if (CASL_EXIT == m_objInstruction.instructionType)
{
m_errorHandler.WriteErrorMessage("Meet Exit Instruction, Exiting executing instructionnow!");
break;
}
if (ExecuteInstruction() != STATUS_OK)
{
goto Run_Failed;
}
}
m_errorHandler.WriteErrorMessage("Execute instruction successfully!");
#ifdef WINDOW_MODE
//虚拟机运行可执行程序结束以后,就可以释放与之相连的用于I/O的Console了
iRet = m_console.ExitConsole();
if (CConsoleManage::CONSOLE_WORK_OK != iRet)
{
if (CConsoleManage::CONSOLE_NOT_STARTED == iRet)
{
MessageBox(NULL, _T("Console Not Started"), _T(""), MB_OK);
}
else
{
MessageBox(NULL, _T("Console Exit Failed"), _T(""), MB_OK);
}
goto Run_Failed;
}
#endif
return STATUS_OK;
Run_Failed:
//exit(-1);
return STATUS_FAILED;
}
/////////////////////////////////////////////////////////////////////////
//函数名称:ReadInstruction
//函数功能:---------------------从当前PC处读出一条指令-----------------------
//入口参数:无
//出口参数:无
//返回值:int--------------STATUS_OK表示操作成功,其他表示操作出现问题
//开发人员:杨军
//开发日期:2004-4-19
//修改人员:
//修改日期:
/////////////////////////////////////////////////////////////////////////
int CCometVM::ReadInstruction()
{
//从当前PC指针处读出一个4Bytes的指令,并将该指令放入成员
//变量m_objInstruction中以便于后面的处理
//memcpy(&m_objInstruction, m_pInstructionMemoryBase + (m_PC << 1), sizeof(m_objInstruction) / sizeof(char));
//仿真更真实!!
//要读写的内存地址超出COMET机的范围,则报错
if ((m_PC << 1) >= m_icVMMemoryLimit)
{
return STATUS_FAILED;
}
memcpy(&m_objInstruction, m_pVMMemoryBase + (m_PC << 1), sizeof(m_objInstruction) / sizeof(char));
return STATUS_OK;
}
/////////////////////////////////////////////////////////////////////////
//函数名称:Instruction_LD
//函数功能:---------------------ST指令的执行函数----------------------------
//入口参数:无
//出口参数:无
//返回值:int--------------STATUS_OK表示操作成功,其他表示操作出现问题
//开发人员:杨军
//开发日期:2004-4-19
//修改人员:
//修改日期:
/////////////////////////////////////////////////////////////////////////
int CCometVM::Instruction_LD()
{
//---------------LD指令的功能描述 begins-------------------------------
//格式: LD GR, ADR[,XR]
//功能: 将(E) ----> GR (E = ADR [ + XR] (mod 2 ^ 16)
//---------------LD指令的功能描述 ends----------------------------------
//---------------变量定义部分 begins----------------------------------
S2 s2EA = 0;
int iRegNumber = 0;
//---------------变量定义部分 ends------------------------------------
m_errorHandler.WriteErrorMessage("Execute Instruction LD: begins");
//--------------计算出有效地址E-----------------------------------------
//获得变址寄存器的编号
iRegNumber = (m_objInstruction.regNumber & 0xf0) >> 4;
//如果变址寄存器的编号合法的话(GR0---GR4)
//则有效地址 = Addr + XR
if (0 <= iRegNumber && iRegNumber <= 4)
{
//memcpy(&s2EA, m_objInstruction.address, sizeof(s2EA) / sizeof(char));
s2EA = (*(S2*)m_objInstruction.address) + m_GR[iRegNumber];
}
//否则 有效地址 = Addr
else
{
//如果变址寄存器值为空的话
if (REG_EMPTY == iRegNumber)
{
s2EA = *(short*)m_objInstruction.address;
}
//如果变址寄存器引用一个非法的编号的话
else
{
m_errorHandler.WriteErrorMessage("unsupported XR number");
return STATUS_FAILED;
}
}
//检查有效地址是否合法
if (!IsAddressValid(s2EA << 1))
{
return STATUS_FAILED;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -