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

📄 caslutil.cpp

📁 这是一个软件水平资格考试中使用的CASL汇编语言的编译器,实现文件中包括一个编译器,一个虚拟机,一个类似于Debug的调试器.
💻 CPP
📖 第 1 页 / 共 4 页
字号:
      if (!strcmp(argVec[i].strLabelName, argLabelName))
      {
        return i;
      }
    }
    return -1;
  }
  
  //////////////////////////////////////////////////////////////////
  //函数名称:LookUpInConstLableTable
  //函数功能:在常量标号表中查询有无指定的常量标号记录
  //入口参数:vector<ConstLabelItem>& argVec---------------------常量标号表
  //         const CaslString argLabelName----------------------待查询的标号名称
  //出口参数:无
  //返回值:int---------------- >= 0 表示找到的指定的标号记录在常量标号表中的编号,< 0 表示未找到
  //开发人员:杨军
  //开发日期:2004-3-18
  //修改人员:
  //修改日期:
  //////////////////////////////////////////////////////////////////
  int LookUpInConstLableTable(vector<ConstLabelItem>& argVec, const CaslString argLabelName)
  {
    //----------------------变量定义部分begins----------------------    
    size_t i = 0;
    size_t uiSize =0;
    //----------------------变量定义部分ends----------------------
    uiSize = argVec.size();
    for (i = 0; i < uiSize; i++)
    {
      if (!strcmp(argVec[i].strLabelName, argLabelName))
      {
        return i;
      }
    }
    return -1;
  }

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

  //完成Casl编译器工作前的一些初始化工作
  //如设置全局变量的默认值等

  CaslUtilStatus CaslCompilerInitialize()
  {
    char szVal[5]; 
    //----------初始化单指令操作数的指令的名称数组 begins-------------
    strcpy(szVal, "JMP");
    g_vecSingleOperandInstructionName.push_back(szVal);
    strcpy(szVal, "JPZ");
    g_vecSingleOperandInstructionName.push_back(szVal);
    strcpy(szVal, "JMI");
    g_vecSingleOperandInstructionName.push_back(szVal);
    strcpy(szVal, "JNZ");
    g_vecSingleOperandInstructionName.push_back(szVal);
    strcpy(szVal, "JZE");
    g_vecSingleOperandInstructionName.push_back(szVal);
    strcpy(szVal, "PUSH");
    g_vecSingleOperandInstructionName.push_back(szVal);
    strcpy(szVal, "POP");
    g_vecSingleOperandInstructionName.push_back(szVal);
    strcpy(szVal, "CALL");
    g_vecSingleOperandInstructionName.push_back(szVal);
    strcpy(szVal, "SET_NLABEL");
    g_vecSingleOperandInstructionName.push_back(szVal);
    strcpy(szVal, "SET_ALABEL");
    g_vecSingleOperandInstructionName.push_back(szVal);
    //----------初始化单指令操作数的指令的名称数组 ends-------------      

    //----------初始化不使用操作数的指令的名称数组 begins-------------
    strcpy(szVal, "RET");
    g_vecNoOperandInstructionName.push_back(szVal);
    strcpy(szVal, "FUNC_IN");
    g_vecNoOperandInstructionName.push_back(szVal);
    strcpy(szVal, "FUNC_OUT");
    g_vecNoOperandInstructionName.push_back(szVal);
    strcpy(szVal, "EXIT");
    g_vecNoOperandInstructionName.push_back(szVal);
    //----------初始化不使用操作数的指令的名称数组 ends-------------
    return CASL_UTIL_OP_OK;
  }

  


  //////////////////////////////////////////////////////////////////
  //函数名称:<<
  //函数功能:自定义文件流输出operator,用于向文件流中输出一个目标代码数据
  //入口参数:无
  //出口参数:无
  //返回值:无
  //开发人员:杨军
  //开发日期:2004-3-19
  //修改人员:
  //修改日期:
  //////////////////////////////////////////////////////////////////
  CaslOFStream& operator << (CaslOFStream& outStream, ObjectCode argData)
  {
    outStream << argData.instructionType;
    outStream << argData.regNumber;
    outStream << argData.address[0];
    outStream << argData.address[1];
    return outStream;
  }

  //////////////////////////////////////////////////////////////////
  //函数名称:<<
  //函数功能:自定义文件流输入operator,用于从文件流中读入一个目标代码数据
  //入口参数:无
  //出口参数:无
  //返回值:无
  //开发人员:杨军
  //开发日期:2004-3-19
  //修改人员:
  //修改日期:
  //////////////////////////////////////////////////////////////////
  CaslIFStream& operator >> (CaslIFStream& inStream, ObjectCode& argData)
  {
    //inStream >> argData.instructionType;
    inStream.read((char*)&argData.instructionType, 1);
    inStream.read((char*)&argData.regNumber, 1);
    inStream.read((char*)argData.address, 2);
    //inStream >> argData.regNumber;
    //inStream >> argData.address[0];
    //inStream >> argData.address[1];
    return inStream;
  }
  
  //////////////////////////////////////////////////////////////////
  //函数名称:WriteExeFile
  //函数功能:以当前的目标代码和常量表及变量表生成指定名称的Casl程序的可执行文件
  //入口参数:string szFileName---------------------要生成的可执行文件的名称
  //出口参数:无
  //返回值:CaslUtilStatus----------------操作状态,CASL_UTIL_OP_OK表示操作成功,其他表示操作失败
  //开发人员:杨军
  //开发日期:2004-3-19
  //修改人员:
  //修改日期:
  //////////////////////////////////////////////////////////////////
  CaslUtilStatus WriteExeFile(string szFileName)
  {
    //为了保证平台无关性,这一部分采用标准的C++流输出
    //----------------------变量定义部分begins----------------------    
    CaslExeHeader exeHeader;

    CaslOFStream ofOut(szFileName.c_str(), ios::out | ios::binary | ios::trunc);
   
    //如果打开文件失败的话
    if (!ofOut)
    {
      cout << "创建文件" << szFileName << "failed " << endl;
      return OPEN_FILE_FAILED;
    }
    size_t i = 0;
    size_t uiSize = 0;

    U2 u2Temp1 = 0;
    U2 u2Temp2 = 0;

    unsigned char * pTemp = NULL;
    //----------------------变量定义部分ends--------------------------    
    //初始化可执行文件头部数据
    //注意我们这里在计算大小,偏移时都是以字(16 bits)为单位
    //设置可执行文件的常量区域大小
    exeHeader.constAreaSize = g_iConstSize;
    //设置可执行文件中的可视化调试信息大小
    exeHeader.iVisualDebugInfoSize = g_vecVisualDebugInfo.size() * sizeof(InstructionDebugInfo);
    //设置可执行文件中的变量区域大小
    exeHeader.variableAreaSize = g_iVariableSize;
    //设置可执行文件中的执行入口点
    exeHeader.entryPoint = g_iConstSize + g_iVariableSize + exeHeader.iVisualDebugInfoSize;
    //将文件头写入目标文件中
    ofOut << exeHeader.entryPoint;
    ofOut << exeHeader.iVisualDebugInfoSize;
    ofOut << exeHeader.variableAreaSize;
    ofOut << exeHeader.constAreaSize;
#ifdef DEBUG_MODE
    cout << "entry point(Write):" << exeHeader.entryPoint << endl;
    cout << "variable area size(Write):" << exeHeader.variableAreaSize << endl;
    cout << "size of const area(Write):" << exeHeader.constAreaSize << endl;
#endif
    //紧随文件头写入可视化调试信息
    uiSize = g_vecVisualDebugInfo.size();
    for (i = 0; i < uiSize; i++)
    {
      //每条调试信息都是一个二元组
      //先写入源程序行号
      ofOut << g_vecVisualDebugInfo[i].u2SrcCodeLineNumber;
      //再写入目标代码在目标程序中的可执行代码序号
      ofOut << g_vecVisualDebugInfo[i].u2InstructionNumber;
    }

    //对于变量信息只需要在文件头中记录变量区域的大小
    //然后在虚拟机中装入可执行文件时再分配变量空间即可
    //而对于常量区域则需要将常量数据全部写入目标文件中
    //在向目标文件中写入数据的时候可以按int ,char型写入
    //而在虚拟机执行装入可执行文件模块时则需要
    //将int型数据转化为Double Byte数据存放
    //将char扩充为double Byte数据存放
    //目前在写入目标文件的时候已经进行了double Byte的扩充
    //所以在从目标文件中载入虚拟机内存时就可以比较方便地完成了!!!!
    //一定要注意此处!!!!!!
    uiSize = g_vecConst.size();
    
    for (i = 0; i < uiSize; i++)
    {
      switch (g_vecConst[i].type)
      {
      case DEC_CONST: 
        //pTemp = (unsigned char*)&g_vecConst[i].constData.decVal;
        //ofOut << *pTemp << *(pTemp + 1);
        ofOut << g_vecConst[i].constData.decVal;
        break;
      case HEX_CONST:
        //pTemp = (unsigned char*)&g_vecConst[i].constData.hexVal;
        //ofOut << *pTemp << *(pTemp + 1);
        ofOut << g_vecConst[i].constData.hexVal;
        break;
      case LABEL_CONST:
        //ofOut << g_vecConst[i].constData.labelVal;
        ofOut << g_vecConstLabel[i].iOffset;
        break;
      case STR_CONST:
        ofOut << g_vecConst[i].constData.strVal;
        break;
      }
    }
    //将可执行代码写入目标文件中
    uiSize = g_vecObjectCode.size();

#ifdef DEBUG_MODE
    cout << "被写入文件中的目标代码条数:" << uiSize << endl;
#endif

    for (i = 0; i < uiSize; i++)
    {
      ofOut << g_vecObjectCode[i];
    }
    ofOut.close();

#ifdef DEBUG_MODE
    //debug use --------------------------------------------begins
    CaslIFStream inFile(szFileName.c_str());
    //打开文件失败的话
    if (!inFile.is_open())
    {
      cout << "Open " << szFileName << "failed!" << endl;
      return OPEN_FILE_FAILED;
    }
    exeHeader.entryPoint = 0;
    exeHeader.iVisualDebugInfoSize = 0;
    exeHeader.constAreaSize = 0;
    exeHeader.variableAreaSize = 0;
    //读入可执行文件头部信息
    inFile >> exeHeader;
    cout << "entry point(Read):" << exeHeader.entryPoint << endl;
    cout << "size of Visual Debugging Info(Read):" << exeHeader.iVisualDebugInfoSize << endl;
    cout << "variable area size(Read):" << exeHeader.variableAreaSize << endl;
    cout << "size of const area(Read):" << exeHeader.constAreaSize << endl;

    //--------------------读入可视化调试信息----------------------------------
    //计算出可视化调试信息的记录条数
    uiSize = exeHeader.iVisualDebugInfoSize / sizeof(InstructionDebugInfo);
    g_vecVisualDebugInfo.clear();
    for (i = 0; i < uiSize; i++)
    {
      inFile >> u2Temp1;
      inFile >> u2Temp2;
      g_vecVisualDebugInfo.push_back(InstructionDebugInfo(u2Temp1, u2Temp2));
    }

    char chTemp;
    cout << hex;
    for (i = 0; i < (size_t)exeHeader.constAreaSize; i++)
    {
      inFile >> chTemp;
      cout << (int)chTemp << endl;
      inFile >> chTemp;
      cout << (int)chTemp << endl;
    }
    cout << dec;
    //读入目标代码
    vector<ObjectCode> vecObjCode;
    ObjectCode objCode;
    unsigned char regNumber;
    while (1)
    {

⌨️ 快捷键说明

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