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

📄 debugcmd.cpp

📁 这是一个软件水平资格考试中使用的CASL汇编语言的编译器,实现文件中包括一个编译器,一个虚拟机,一个类似于Debug的调试器.
💻 CPP
📖 第 1 页 / 共 5 页
字号:
// DebugCmd.cpp: implementation of the CDebugCmd class.
//
//////////////////////////////////////////////////////////////////////
#include "Stdafx.h"
#include "DebugCmd.h"


#include "InstructionDef.h"
#include "OperandDef.h"
#include "CodeGenerationDataType.h"
#include "CaslUtil.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CDebugCmd::CDebugCmd(CCometVM * argVM /* = NULL */)
{
  m_pVM = argVM;
  m_iLen = 0;
  m_iPos = 0;
  m_cszInstruction = NULL;
  strcpy(m_szSpace, "  ");
}

//-------------设置当前活动的虚拟机----------------------------------
void CDebugCmd::SetActiveVM(CCometVM * argVM)
{
  m_pVM = argVM;
}
/////////////////////////////////////////////////////////////////////////
//函数名称:DbgCmd_Assemple
//函数功能:---------------------Assemple功能的执行函数------------------------
//入口参数:U2 argAddress---------------将被进行Assemble的起始内存地址
//出口参数:无
//返回值:int-------------STATUS_OK表示操作成功,其他表示操作失败
//开发人员:杨军
//开发日期:2004-4-23
//修改人员:
//修改日期:
/////////////////////////////////////////////////////////////////////////
int CDebugCmd::DbgCmd_Assemple(U2 argAddress)
{
  //unfinished now !!!
  //---------------------变量定义部分 begins-----------------------------
  ObjectCode objCode;

  string strStmt("");
  int iRet = 0;
  //---------------------变量定义部分 ends  -----------------------------

  //-----循环接受用户输入的汇编指令,直到用户输入回车符表示结束输入!------
  while (1)
  {
    //参照Debug中的A功能,在输入汇编指令的时候还要加入一定的词法分析的功能!!!!
    //-----------输出当前要编辑汇编码的内存地址---------------------------
    cout << hex << argAddress << m_szSpace;
    //------------接受用户输入的汇编指令----------------------------------
    //cin  >> strStmt;
    cin.sync();
    getline(cin, strStmt, '\n');
    CaslUtil::Trim(strStmt);
    //用户直接按下了回车符,则退出Assemble工作状态
    if (strStmt.length() <= 0)
    {
      break;
    }
    //将指令转化成大写以便于统一处理
    strStmt = strupr(strStmt.begin());
    m_cszInstruction = strStmt.c_str();
    //-----为GetNextChar函数进行准备---------------------------------------
    //获得用户输入的字符串的长度
    m_iLen = strlen(m_cszInstruction);
    //设置起始字符位置
    m_iPos = 0;

    //--------------为用户输入的汇编指令生成中间代码结构,为生成目标代码作准备---
    iRet = PrepareSingleCaslStmt();
    //用户输入的汇编指令有问题
    if (STATUS_OK != iRet)
    {
      //Need to do some error handling operation!!!
      cout << "Error In the statement You Input!" << endl;
      //继续要求用户在当前内存单元输入汇编指令 
      continue;
    }
    //用户输入的汇编指令合法
    else
    {
      //---用户输入的Casl指令是合法的,则为其生成目标代码,----------------------
      //---并将生成的目标代码放入当前内存单元中去------------------------------
      //为用户输入的Casl源程序生成目标代码

      memset(&objCode, 0, sizeof(objCode) / sizeof(char));

      switch (m_asmCode.instType)
      {
      //-----------对宏指令IN要生成三条Casl指令--------------------------------
      case CASL_IN:
        //生成指令Set_ALabel
        objCode.instructionType = CASL_SET_ALABEL;
        objCode.regNumber = REG_EMPTY;
        objCode.regNumber <<= 4;
        objCode.regNumber = REG_EMPTY;
        if (m_asmCode.bALabelAddress)
        {
          (*(S2*)objCode.address) = m_asmCode.s2ALabelAddress;
        }
        //将生成的目标代码放入内存单元中去
        memcpy(m_pVM->m_pVMMemoryBase + argAddress, &objCode, sizeof(objCode) / sizeof(char));
        argAddress += 2;
        //生成指令Set_NLabel
        objCode.instructionType = CASL_SET_NLABEL;
        objCode.regNumber = REG_EMPTY;
        objCode.regNumber <<= 4;
        objCode.regNumber = REG_EMPTY;
        if (m_asmCode.bNLabelAddress)
        {
          (*(S2*)objCode.address) = m_asmCode.s2NLabelAddress;
        }
        //将生成的目标代码放入内存单元中去
        memcpy(m_pVM->m_pVMMemoryBase + argAddress, &objCode, sizeof(objCode) / sizeof(char));
        argAddress += 2;
        //生成指令Func_In
        objCode.instructionType = CASL_FUNC_IN;
        objCode.regNumber = REG_EMPTY;
        objCode.regNumber <<= 4;
        objCode.regNumber = REG_EMPTY;
        //将生成的目标代码放入内存单元中去
        memcpy(m_pVM->m_pVMMemoryBase + argAddress, &objCode, sizeof(objCode) / sizeof(char));
        argAddress += 2;
        break;
      //-----------对宏指令OUT要生成三条Casl指令--------------------------------
      case CASL_OUT:
        //生成指令Set_ALabel
        objCode.instructionType = CASL_SET_ALABEL;
        objCode.regNumber = REG_EMPTY;
        objCode.regNumber <<= 4;
        objCode.regNumber = REG_EMPTY;
        if (m_asmCode.bALabelAddress)
        {
          (*(S2*)objCode.address) = m_asmCode.s2ALabelAddress;
        }
        //将生成的目标代码放入内存单元中去
        memcpy(m_pVM->m_pVMMemoryBase + argAddress, &objCode, sizeof(objCode) / sizeof(char));
        argAddress += 2;
        //生成指令Set_NLabel
        objCode.instructionType = CASL_SET_NLABEL;
        objCode.regNumber = REG_EMPTY;
        objCode.regNumber <<= 4;
        objCode.regNumber = REG_EMPTY;
        if (m_asmCode.bNLabelAddress)
        {
          (*(S2*)objCode.address) = m_asmCode.s2NLabelAddress;
        }
        //将生成的目标代码放入内存单元中去
        memcpy(m_pVM->m_pVMMemoryBase + argAddress, &objCode, sizeof(objCode) / sizeof(char));
        argAddress += 2;
        //生成指令Func_In
        objCode.instructionType = CASL_FUNC_OUT;
        objCode.regNumber = REG_EMPTY;
        objCode.regNumber <<= 4;
        objCode.regNumber = REG_EMPTY;
        //将生成的目标代码放入内存单元中去
        memcpy(m_pVM->m_pVMMemoryBase + argAddress, &objCode, sizeof(objCode) / sizeof(char));
        argAddress += 2;
        break;
      default:
        objCode.instructionType = m_asmCode.instType;
        if (m_asmCode.bXRUse)
        {
          //变址寄存器的编号放在regNumber的高四位
          objCode.regNumber |= m_asmCode.iXRNumber;
        }
        else
        {
          objCode.regNumber |= REG_EMPTY;
        }
        objCode.regNumber <<= 4;
        if (m_asmCode.bGRUse)
        {
          //通用寄存器编号放在regNumber的低四位
          objCode.regNumber |=  m_asmCode.iGRNumber;
        }
        else
        {
          objCode.regNumber |= REG_EMPTY;
        }

        if (m_asmCode.bAddressUse)
        {
          (*(S2*)objCode.address) = m_asmCode.s2Address;
        }
        //将生成的目标代码放入内存单元中去
        memcpy(m_pVM->m_pVMMemoryBase + argAddress, &objCode, sizeof(objCode) / sizeof(char));
        //因为一条Casl目标指令占两个字长,所以内存地址加2
        argAddress += 2;
      }
    }
    
  }

  return STATUS_OK;
}

/////////////////////////////////////////////////////////////////////////
//函数名称:CheckSingleCaslStmt
//函数功能:检测用户输入的一条Casl源程序是否符合Casl语言的文法标准
//入口参数:无
//出口参数:无
//返回值:int-------------STATUS_OK表示操作成功,其他表示操作失败
//开发人员:杨军
//开发日期:2004-4-23
//修改人员:
//修改日期:
/////////////////////////////////////////////////////////////////////////
int CDebugCmd::CheckSingleCaslStmt()
{
  //--------------------变量定义部分begins---------------

  //--------------------变量定义部分ends  ---------------

  //-----将指令按第一个字母来分类处理--------------------  
  switch (GetNextChar())
  {
  case 'A':   //AND, ADD ?
    if (STATUS_OK != Instruction_HeadedByA())
    {
      goto CheckSingleStmtFailed;
    }
    break;
  case 'C':   //CPA, CPL, CALL ?
    if (STATUS_OK != Instruction_HeadedByC())
    {
      goto CheckSingleStmtFailed;
    }
    break;
  case 'E':   //EOR ?
    if (STATUS_OK != Instruction_HeadedByE())
    {
      goto CheckSingleStmtFailed;
    }
    break;
  case 'I':   //IN ?
    if (STATUS_OK != Instruction_HeadedByI())
    {
      goto CheckSingleStmtFailed;
    }
    break;
  case 'J':   //JMP, JPZ, JMI, JNZ, JZE ?
    if (STATUS_OK != Instruction_HeadedByJ())
    {
      goto CheckSingleStmtFailed;
    }
    break;
  case 'L':   //LD, LEA ?
    if (STATUS_OK != Instruction_HeadedByL())
    {
      goto CheckSingleStmtFailed;
    }
    break;
  case 'O':   //OR, OUT ?
    if (STATUS_OK != Instruction_HeadedByO())
    {
      goto CheckSingleStmtFailed;
    }
    break;
  case 'P':   //PUSH, POP ?
    if (STATUS_OK != Instruction_HeadedByP())
    {
      goto CheckSingleStmtFailed;
    }
    break;
  case 'R':   //RET ?
    if (STATUS_OK != Instruction_HeadedByR())
    {
      goto CheckSingleStmtFailed;
    }
    break;
  case 'S':   //ST, SUB, SLA, SRA, SLL, SRL
    if (STATUS_OK != Instruction_HeadedByS())
    {
      goto CheckSingleStmtFailed;
    }
    break;
  default:    //Other
    goto CheckSingleStmtFailed;
    break;
  }

  m_pVM->m_errorHandler.WriteErrorMessage("CheckSingleStmt Successfully!");
  return STATUS_OK;


  
CheckSingleStmtFailed:
  m_pVM->m_errorHandler.WriteErrorMessage("CheckSingleStmt Failed!");
  return STATUS_FAILED;
}


/////////////////////////////////////////////////////////////////////////
//函数名称:PrepareSingleCaslStmt
//函数功能:---------------------产生一条源程序指令的中间代码,为生成目标代码
//                              进行准备----------------------------------
//入口参数:无
//出口参数: 无
//返回值:int-------------STATUS_OK表示操作成功,其他表示操作失败
//开发人员:杨军
//开发日期:2004-4-24
//修改人员:
//修改日期:
/////////////////////////////////////////////////////////////////////////
int CDebugCmd::PrepareSingleCaslStmt()
{
  m_asmCode.bAddressUse = false;
  m_asmCode.bALabelAddress = false;
  m_asmCode.bGRUse = false;
  m_asmCode.bNLabelAddress = false;
  m_asmCode.bXRUse = false;
  //--------------检测用户输入的汇编指令的格式是否正确--------------------   
  //用户输入的汇编指令有问题
  if (STATUS_OK != CheckSingleCaslStmt())
  {
    return STATUS_FAILED;
  }
  //用户输入的汇编指令合法
  else
  {
    
  }
  return STATUS_OK;
}


/////////////////////////////////////////////////////////////////////////
//函数名称:GetNextChar
//函数功能:-----用于A命令中获得用户输入的指令串的下一个字符,并改变索引指针-------
//入口参数:无
//出口参数:无
//返回值:char--------------------------------指令串中的下一个字符,如果已经读到末尾,就返回EOI标志
//开发人员:杨军
//开发日期:2004-4-24
//修改人员:
//修改日期:
/////////////////////////////////////////////////////////////////////////
char CDebugCmd::GetNextChar()
{
  if (m_iPos >= m_iLen)
  {
    return EOI;
  }
  return m_cszInstruction[m_iPos++];
}

/////////////////////////////////////////////////////////////////////////
//函数名称:Instruction_HeadedByA
//函数功能:---------------------处理以字符A作为起始字符的指令----------------
//入口参数:无
//出口参数:无
//返回值:int-------------STATUS_OK表示操作成功,其他表示操作失败
//开发人员:杨军
//开发日期:2004-4-24
//修改人员:
//修改日期:
/////////////////////////////////////////////////////////////////////////
int CDebugCmd::Instruction_HeadedByA()
{
  switch (GetNextChar())
  {
  case 'N':   //AND ?
    //得到AND输入
    if ('D' == GetNextChar())
    {
      m_asmCode.instType = CASL_AND;
      //注意: 指令后必须跟至少一个空格才能再跟操作数!!
      //      否则视为不合法!!!
      if (' ' == GetNextChar())
      {
        //略过多余的空格
        PassBySpace();
        if (STATUS_OK != HandleGRAndEA())
        {
          goto Instruction_HeadedByA_Failed;
        }
      }
      else
      {
        goto Instruction_HeadedByA_Failed;
      }
    }
    //不支持的输入
    else
    {
      goto Instruction_HeadedByA_Failed;
    }
    break;
  case 'D':   //ADD ?
    //得到ADD输入
    if ('D' == GetNextChar())
    {
      m_asmCode.instType = CASL_ADD;

      if (' ' == GetNextChar())
      {
        //略过多余的空格
        PassBySpace();
        if (STATUS_OK != HandleGRAndEA())
        {
          goto Instruction_HeadedByA_Failed;
        }
      }
      else
      {
        goto Instruction_HeadedByA_Failed;
      }
    }
    //不支持的输入
    else
    {
      goto Instruction_HeadedByA_Failed;
    }
    break;
  default:    //Other
    goto Instruction_HeadedByA_Failed;
    break;
  }
 
  return STATUS_OK;

//--------------错误处理部分----------------------------------------------------------
Instruction_HeadedByA_Failed:
  m_pVM->m_errorHandler.WriteErrorMessage("Unknown Instruction!");
  return STATUS_FAILED;
}

/////////////////////////////////////////////////////////////////////////
//函数名称:Instruction_HeadedByC
//函数功能:---------------------处理以字符C作为起始字符的指令----------------
//入口参数:无
//出口参数:无
//返回值:int-------------STATUS_OK表示操作成功,其他表示操作失败
//开发人员:杨军
//开发日期:2004-4-24
//修改人员:
//修改日期:
/////////////////////////////////////////////////////////////////////////
int CDebugCmd::Instruction_HeadedByC()
{
  //CPA, CPL, CALL ?
  switch (GetNextChar())
  {
  case 'P':   //CPA OR CPL?
    switch (GetNextChar())
    {
    case 'A':       //CPA
      m_asmCode.instType = CASL_CPA;
      break;
    case 'L':       //CPL
      m_asmCode.instType = CASL_CPL;
      break;
    default:        //不支持的输入
      goto Instruction_HeadedByC_Failed;
      break;
    }
    //处理操作数
    if (' ' == GetNextChar())
    {
      //略过多余的空格
      PassBySpace();
      if (STATUS_OK != HandleGRAndEA())

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -