⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cometvm.cpp

📁 这是一个软件水平资格考试中使用的CASL汇编语言的编译器,实现文件中包括一个编译器,一个虚拟机,一个类似于Debug的调试器.
💻 CPP
📖 第 1 页 / 共 5 页
字号:
// 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 + -