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

📄 caslutil.cpp

📁 这是一个软件水平资格考试中使用的CASL汇编语言的编译器,实现文件中包括一个编译器,一个虚拟机,一个类似于Debug的调试器.
💻 CPP
📖 第 1 页 / 共 4 页
字号:
    //应当设置一个常量记录变量表的大小(即一共为常量分配多少内存空间)
    g_iConstSize = iCurrentOffset;
    
#ifdef DEBUG_MODE 
    cout << "---------------------常量标号表------------------------------------" << endl;
    uiSize = argVecDst.size();
    for (i = 0; i < uiSize; i++)
    {
      cout << argVecDst[i].strLabelName << "    "  << argVecDst[i].iOffset;
      cout << endl;
    }
#endif
    return CASL_UTIL_OP_OK;
  }
  
  //////////////////////////////////////////////////////////////////
  //函数名称:MakeInstructionLabelTable
  //函数功能:依据中间代码指令标号表生成目标代码指令标号表,供生成目标代码使用
  //入口参数:const LabelMap& argMapSrc---------------------------------中间代码指令标号表
  //出口参数:vector<InstructionLabelItem>& argVecDst-------------------生成的目标代码指令标号表
  //返回值:CaslUtilStatus----------------操作状态,CASL_UTIL_OP_OK表示操作成功,其他表示操作失败
  //开发人员:杨军
  //开发日期:2004-3-18
  //修改人员:
  //修改日期:
  //////////////////////////////////////////////////////////////////
  CaslUtilStatus MakeInstructionLabelTable(const LabelMap& argMapSrc, vector<InstructionLabelItem>& argVecDst)
  {
    //----------------------变量定义部分begins----------------------
    InstructionLabelItem instructionLabelItem;

    size_t i = 0;
    size_t uiSize = 0;
    //----------------------变量定义部分ends----------------------
    LabelMap::const_iterator itMap = NULL;
    //预先清空结果vector
    argVecDst.clear();

    for (itMap = argMapSrc.begin(); itMap != argMapSrc.end(); itMap++)
    {
      strcpy(instructionLabelItem.strLabelName, itMap->second.c_str());
      instructionLabelItem.iOffset = (itMap->first << 1);   //因为COMET机中每条目标指令都是双字长,所以用指令条数编号乘以二
      //将生成的指令标号元素放入目标代码指令标号表
      argVecDst.push_back(instructionLabelItem);
    }

#ifdef DEBUG_MODe
    cout << "---------------------指令标号表------------------------------------" << endl;
    uiSize = argVecDst.size();
    for (i = 0; i < uiSize; i++)
    {
      cout << argVecDst[i].strLabelName << "   "  << argVecDst[i].iOffset;
      cout << endl;
    }
#endif
    
    return CASL_UTIL_OP_OK;
  }

  
  //////////////////////////////////////////////////////////////////
  //函数名称:MakeObjectCode
  //函数功能:生成目标代码
  //入口参数:无
  //出口参数:无
  //返回值:CaslUtilStatus----------------操作状态,CASL_UTIL_OP_OK表示操作成功,其他表示操作失败
  //开发人员:杨军
  //开发日期:2004-3-18
  //修改人员:
  //修改日期:
  //////////////////////////////////////////////////////////////////
  CaslUtilStatus MakeObjectCode()
  {
    //依据中间代码表,变量标号表,常量标号表,以及指令标号表来生成目标代码
    //----------------------变量定义部分begins----------------------
    ObjectCode objectCode;

    int nIndex = 0;

    size_t i = 0;
    size_t uiSize = 0;

    unsigned char  regNumber = 0;
    //----------------------变量定义部分ends----------------------
    uiSize = g_vecIntermediateCode.size();
    //清空上次生成的可视化调试信息
    g_vecVisualDebugInfo.clear();
    //循环处理每条中间代码,生成其对应的目标代码
    for (i = 0; i < uiSize; i++)
    {
      objectCode.instructionType = g_vecIntermediateCode[i].type;
      //清空寄存器,地址数据
      //以便于填入新的数据
      objectCode.regNumber = 0;
      memset(objectCode.address, 0, 2);
      //---------------处理操作数1 begins-------------------------------------------------------------
      switch (g_vecIntermediateCode[i].operand1.type)
      {
      case REG_OPERAND:
        //将通用寄存器的编号存放在低四位上
        objectCode.regNumber = g_vecIntermediateCode[i].operand1.OperandVal.regOperand.regNumber;
        break;
      case EA_OPERAND:
        regNumber = g_vecIntermediateCode[i].operand1.OperandVal.eaOperand.regNumber;
        regNumber <<= 4;
        //将变址寄存器的编号存放在高四位上
        objectCode.regNumber |= regNumber;
        //如果地址数据是标号的话,需要查标号表
        if (LABEL_EA_ADDRESS == g_vecIntermediateCode[i].operand1.OperandVal.eaOperand.address.type)
        {
          //如果标号在变量表中
          if ((nIndex = LookUpInVariableLableTable(g_vecVariableLabel, g_vecIntermediateCode[i].operand1.OperandVal.eaOperand.address.addressVal.labelAddress.strLabelName)) >= 0)
          {
            //(*objectCode.address) = g_vecVariableLabel[nIndex].iOffset;
            ASSIGN_INT_TO_DBYTE(g_vecVariableLabel[nIndex].iOffset, objectCode.address);
          }
          //如果标号在常量表中
          else if ((nIndex = LookUpInConstLableTable(g_vecConstLabel, g_vecIntermediateCode[i].operand1.OperandVal.eaOperand.address.addressVal.labelAddress.strLabelName))>= 0)
          {
            //常量表中标号的实际偏移应当是变量标号表的大小再加上
            //常量标号表中的标号在常量标号表中的相对偏移大小
            //(*objectCode.address) = g_iVariableSize + g_vecConstLabel[nIndex].iOffset;
            ASSIGN_INT_TO_DBYTE(g_iVariableSize + g_vecConstLabel[nIndex].iOffset, objectCode.address);
          }
          else if ((nIndex = LookUpInInstructionLableTable(g_vecInstructionLabel, g_vecIntermediateCode[i].operand1.OperandVal.eaOperand.address.addressVal.labelAddress.strLabelName)) >= 0)
          {
            //指令标号表中的实际偏移应当是变量标号表的大小再加上
            //常量标号表的大小以后
            //再加上指令标号表中的标号在指令标号表中的相对偏移大小
            //(*objectCode.address) = g_iVariableSize + g_iConstSize + g_vecInstructionLabel[nIndex].iOffset;
            ASSIGN_INT_TO_DBYTE(g_iVariableSize + g_iConstSize + g_vecInstructionLabel[nIndex].iOffset, objectCode.address);
            //ASSIGN_INT_TO_DBYTE(g_vecInstructionLabel[nIndex].iOffset, objectCode.address);
          }
          //如果标号也不在指令标号表中,则报错
          else
          {
            //cerr << ;
            //return ;
          }
        }
        //如果地址数据是数值的话,直接赋值即可
        else if (DEC_EA_ADDRESS == g_vecIntermediateCode[i].operand1.OperandVal.eaOperand.address.type)
        {
          //cout << g_szInstructionName[g_vecIntermediateCode[i].type] << "--decimal EA Address:" << g_vecIntermediateCode[i].operand1.OperandVal.eaOperand.address.addressVal.decAddress;
          //cout << endl;          
          //(*objectCode.address) = g_vecIntermediateCode[i].operand1.OperandVal.eaOperand.address.addressVal.decAddress;
          ASSIGN_INT_TO_DBYTE(g_vecIntermediateCode[i].operand1.OperandVal.eaOperand.address.addressVal.decAddress, objectCode.address);
        }
        break;
      case EMPTY_OPERAND:
        //暂时没有一个好的办法来标识空操作数
        //目前只有在虚拟机中判断指令是否不需要操作数
        //比如在Casl中只有RET指令是不需要操作数的
        //objectCode.regNumber = REG_NONE;
        //objectCode.address = EMPTY_OPERAND;
        break;
      default:
        break;
      }
      //---------------处理操作数1 ends-----------------------------------------------------------------
      //处理操作数2
      //---------------处理操作数2 begins---------------------------------------------------------------
      switch (g_vecIntermediateCode[i].operand2.type)
      {
      case REG_OPERAND:
        //将通用寄存器的编号存放在低四位上
        objectCode.regNumber = g_vecIntermediateCode[i].operand2.OperandVal.regOperand.regNumber;
        break;
      case EA_OPERAND:
        regNumber = g_vecIntermediateCode[i].operand2.OperandVal.eaOperand.regNumber;
        regNumber <<= 4;
        //将变址寄存器的编号存放在高四位上
        objectCode.regNumber |= regNumber;
        //如果地址数据是标号的话,需要查标号表
        if (LABEL_EA_ADDRESS == g_vecIntermediateCode[i].operand2.OperandVal.eaOperand.address.type)
        {
          //如果标号在变量表中
          if ((nIndex = LookUpInVariableLableTable(g_vecVariableLabel, g_vecIntermediateCode[i].operand2.OperandVal.eaOperand.address.addressVal.labelAddress.strLabelName)) >= 0)
          {
            //(*objectCode.address) = g_vecVariableLabel[nIndex].iOffset;
            ASSIGN_INT_TO_DBYTE(g_vecVariableLabel[nIndex].iOffset, objectCode.address);
          }
          //如果标号在常量表中
          else if ((nIndex = LookUpInConstLableTable(g_vecConstLabel, g_vecIntermediateCode[i].operand2.OperandVal.eaOperand.address.addressVal.labelAddress.strLabelName))>= 0)
          {
            //常量表中标号的实际偏移应当是变量标号表的大小再加上
            //常量标号表中的标号在常量标号表中的相对偏移大小
            //(*objectCode.address) = g_iVariableSize + g_vecConstLabel[nIndex].iOffset;
            ASSIGN_INT_TO_DBYTE(g_iVariableSize + g_vecConstLabel[nIndex].iOffset, objectCode.address);
          }
          else if ((nIndex = LookUpInInstructionLableTable(g_vecInstructionLabel, g_vecIntermediateCode[i].operand2.OperandVal.eaOperand.address.addressVal.labelAddress.strLabelName)) >= 0)
          {
            //指令标号表中的实际偏移应当是变量标号表的大小再加上
            //常量标号表的大小以后
            //再加上指令标号表中的标号在指令标号表中的相对偏移大小
            //(*objectCode.address) = g_iVariableSize + g_iConstSize + g_vecInstructionLabel[nIndex].iOffset;
            ASSIGN_INT_TO_DBYTE(g_iVariableSize + g_iConstSize + g_vecInstructionLabel[nIndex].iOffset, objectCode.address);
            //ASSIGN_INT_TO_DBYTE(g_vecInstructionLabel[nIndex].iOffset, objectCode.address);
          }
          //如果标号也不在指令标号表中,则报错
          else
          {
            //cerr << ;
            //return ;
          }
        }
        //如果地址数据是数值的话,直接赋值即可
        else if (DEC_EA_ADDRESS == g_vecIntermediateCode[i].operand2.OperandVal.eaOperand.address.type)
        {
          //cout << g_szInstructionName[g_vecIntermediateCode[i].type] << "--decimal EA Address:" << g_vecIntermediateCode[i].operand2.OperandVal.eaOperand.address.addressVal.decAddress;
          //cout << endl;          
          ASSIGN_INT_TO_DBYTE(g_vecIntermediateCode[i].operand2.OperandVal.eaOperand.address.addressVal.decAddress, objectCode.address);
          //cout <<  "after second  operand(decimal address)--" << (int)(*pTemp + *(pTemp + 1) * 0x100)<< endl;
        }
        break;
      case EMPTY_OPERAND:
        //暂时没有一个好的办法来标识空操作数
        //目前只有在虚拟机中判断指令是否不需要操作数
        //比如在Casl中只有RET指令是不需要操作数的
        //objectCode.regNumber = REG_NONE;
        break;
      default:
        break;
      }
      //---------------处理操作数2 ends---------------------------------------------------------------------
      g_vecObjectCode.push_back(objectCode);
      //为当前指令可以生成调试信息(注意:这里为IN,OUT实际上各生成了三条可视化调试信息记录,但是因为我们在调试器工作的时候
      //会进行一定的处理,对于IN,OUT所转换出的三条指令实际上是当成一条指令来执行的,这里就不再特殊处理了!)
      g_vecVisualDebugInfo.push_back(InstructionDebugInfo(g_vecIntermediateCode[i].iSrcCodeLineNumber, i));
    }

#ifdef DEBUG_MODE
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //输出生成的目标代码(不含变量,常量部分)
    uiSize = g_vecObjectCode.size();
    cout << "目标代码条数:" << uiSize << endl;
    for (i = 0; i < uiSize; i++)
    {
      //输出指令名称 
      cout << g_szInstructionName[g_vecObjectCode[i].instructionType] << " ";  
      //注意: 对于JMP, JNZ, JMI, JPZ, JZE, PUSH, POP只能有一个操作数
      //而对于RET则没有操作数
      //所以在这需要进行分支处理
      //如果当前指令是单操作数指令的话
      if (g_vecSingleOperandInstructionName.end() != find(g_vecSingleOperandInstructionName.begin(), g_vecSingleOperandInstructionName.end(), g_szInstructionName[g_vecObjectCode[i].instructionType]))
      {
        //处理操作数1即可
        //如果是POP指令的话,使用通用寄存器GR作为操作数
        if (!strcmp(g_szInstructionName[g_vecObjectCode[i].instructionType], "POP"))
        {
          //输出POP的操作数中的寄存器编号
          cout << "操作数1(REG): " << (int)(g_vecObjectCode[i].regNumber & 0x0f);
        }
        //如果是其他的单操作数指令的话
        //输入其EA操作数
        else
        {
          regNumber = g_vecObjectCode[i].regNumber & 0xf0;
          //cout << "single operand instruction(before right shift): " << (int)regNumber;
          regNumber >>= 4;
          //cout << "single operand instruction(after right shift): " << (int)regNumber;
          cout << "操作数1(EA): XR--" <<  (int)regNumber << " Address----" << ConvertDByteToInt(g_vecObjectCode[i].address);
        }
        //如果是其他的单操作数指令的话,使用EA作为操作数
      }
      //如果当前指令是无操作数指令的话
      else if (g_vecNoOperandInstructionName.end() != find(g_vecNoOperandInstructionName.begin(), g_vecNoOperandInstructionName.end(), g_szInstructionName[g_vecObjectCode[i].instructionType]))
      {
        //目前情况下不需要处理操作数
        //以后考虑在目标指令中加入一个标识操作数为空的标志位
      }
      //是普通的双操作数指令的话
      else 
      {
        //在Casl中,对于双操作数指令来说,第一个操作数必然是通用寄存器
        //第二个必然是EA,这就给我们的处理带来了很大的方便
        //输出操作数1的数据(通用寄存器的编号)
        cout << "操作数1(REG): " << (int)(g_vecObjectCode[i].regNumber & 0x0f);
        //输出操作数2的数据
        //cout << "dobule  operand instruction: XR(before shift) " << (int)g_vecObjectCode[i].regNumber << endl;
        regNumber = g_vecObjectCode[i].regNumber & 0xf0;
        //cout << "dobule  operand instruction: XR(after shift) " << (int)regNumber << endl;
        regNumber >>= 4;
        cout << "操作数2(EA): XR--" <<  (int)regNumber << " Address----" << ConvertDByteToInt(g_vecObjectCode[i].address);
      }
      cout << endl;
    }
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#endif

    return CASL_UTIL_OP_OK;
  }
  
  //////////////////////////////////////////////////////////////////
  //函数名称:LookUpInVariableLableTable
  //函数功能:在变量标号表中查询有无指定的变量标号记录
  //入口参数:vector<VariableLabelItem>& argVec--------------变量标号表
  //         const CaslString argLabelName------------------待查询的标号名称
  //出口参数:无
  //返回值:int---------------- >= 0 表示找到的指定的标号记录在变量标号表中的编号,< 0 表示未找到
  //开发人员:杨军
  //开发日期:2004-3-18
  //修改人员:
  //修改日期:
  //////////////////////////////////////////////////////////////////
  int LookUpInVariableLableTable(vector<VariableLabelItem>& argVec, const CaslString argLabelName) 
  {
    //----------------------变量定义部分begins----------------------    
    size_t i = 0;
    size_t uiSize =0;
    //----------------------变量定义部分ends----------------------
    uiSize = argVec.size();
    for (i = 0; i < uiSize; i++)
    {

⌨️ 快捷键说明

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