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

📄 masmber_c5.cpp

📁 MCS51单片机的宏汇编器源程序。有需要的朋友请下载!
💻 CPP
字号:
//---------------------------------------------------------------------------
//   MAsmber_C5.cpp 
//---------------------------------------------------------------------------

#include "MAsmber_H.h"
#include "AsmF_H.h"
#include "OBJfile_H.h"
#include "ListFile_H.h"
#include "OBJModule_H.h"
//---------------------------------------------------------------------------
#define DebugKit(str)       DebugMsg(str)
//---------------------------------------------------------------------------
// 产生OBJ文件。
// 流程:
// (1) 打开OBJ文件。
// (2) 写入一个文件头。
// (3) 写入模块信息。
// (4) 关闭OBJ文件。
//---------------------------------------------------------------------------
void MacroAsmber::GenOBJFile()
{ if(!ObjFile) { return; } // endif      开关没打开
  objFilePt->Open();                     // 打开文件。

  Jstring CommandLine("");
  for(int16u i = 0; i < Margc; ++i)      // 记录命令行参数
   { CommandLine = CommandLine + Margv[i] + " "; } // end for
  objFilePt->WriteFileHeaderRecord(CommandLine, *AsmFn); // 写文件头

  JModulePt->WriteModuleToOBJFile();     // 往目标文件写入一个模块!! (核心!)

  objFilePt->Close();                    // 关闭文件。
} // end GenOBJFile
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
// 汇编流程总调度。
// 流程:
// (1) 提取不带后缀名的Pname。
// (2) 初始化,创建各对象。
// (3) 将命令行输入的参数转换成汇编行。
// (4) 词法分析。
// (5) 装载8051的SFR符号。
// (6) 语法分析。
// (7) 语义分析。
// (8) 代码生成。
// (9) 对符号链表进行排序。
// (10)产生OBJ文件。
// (11)产生列表文件。
//---------------------------------------------------------------------------
ERR MacroAsmber::AssembleFile(const Jstring& FileNam)
{ FetchPname(FileNam, Pname); // 为Pname赋值。如果FileNam有后缀名,Pname不包括后缀名。
  Jstring Srcfilename(FileNam);
  if(Pname == FileNam)                 // 如果没有后缀名
   { Srcfilename = Srcfilename + ".asm"; } // endif

      AsmFn = new AsmFile(*this, Srcfilename); // 建立一个源Asm文件对象
  objFilePt = new OBJfile(*this, Pname);    // 创建OBJ文件
  LstFilePt = new LISTFile(*this, Pname);        // 创建LST文件


  JModulePt = new OBJmodule(*this, Pname); // 创建一个默认的当前模块
  SegPt = JModulePt->SegDefHead; // 给当前段指针赋初值,是一个绝对段

  printf("\nAssembling file %s...",AsmFn->FileName());

  CommandLineToAsmL(); // 将命令行输入的参数转换成汇编行。在词法分析之前做。

  ERR era = FileToToken(); // 词法分析, 该函数会影响Ln的值。
  DebugMsg(printf("\nFile lex %s! ", era ? "Error" : "Ok" );); // debug
  if(era) { goto enden; } // endif
  ++AsmFn->runCount;            // 1

  if(SFR51)   // 是否装载8051的SFR符号。在词法分析之后做。
   { LabMger->LoadSFR51(SRegAddr); } // endif

  era = AsmFileParse();      // 语法分析
  DebugMsg(printf("\nFile parse %s! ", era ? "Error" : "Ok" );); // debug
  if(era) { goto enden; } // endif
  ++AsmFn->runCount;            // 2

  era = MeaningTrans();    // 语义分析
  DebugMsg(printf("\nMeaningTrans %s! ", era ? "Error" : "Ok" );); // debug
  if(era) { goto enden; } // endif
  ++AsmFn->runCount;            // 3

  era = FileToObjCode();         // 代码生成
  DebugMsg(printf("\nToObjCode %s! ", era ? "Error" : "Ok" );); // debug
  if(era) { goto enden; } // endif
  ++AsmFn->runCount;            // 4

  //JModulePt->show(); Debugkey;
  //AsmFn->ShowFileToken(); Debugkey;
  // LabMger->ShowLabelList(); Debugkey;

  enden:
  LabMger->SortLabelByCrno(); // 对链表进行排序。在产生OBJ文件和列表文件之前做。

  if(!era) { GenOBJFile(); } // endif // 产生OBJ文件。
  GenListFile(); // 产生列表文件。

  fprintf(EpFile.GetEPfile(),"\nTotal %d errors, %d warnings.", GetErrorSum(), GetWarningSum());
  if(!EpFile.IsEPScreen())
   { printf("\nTotal %d errors, %d warnings.", GetErrorSum(), GetWarningSum());
     EpFile.Close();
     if(GetErrorSum() + GetWarningSum() == 0) { EpFile.Suicide(); } // endif
   } // endif

  return era;
} // end ComplyFile
//---------------------------------------------------------------------------


//---------------------------------------------------------------------------
// 建立符号表。
// 从文件头开始扫描,把所有的标号、常量、变量都登记起来。如果能计算的,马上计算。
// 不能计算的,忽略。
// 注意, 必须在汇编行语法分析完全正确的前提下进行!
// Fn 要预先设置好!Ln 被修改。
// 流程:
// (1) 初始化。(置SegPt指针,设置默认段段中新片段。)
// (2) 汇编行的lc值被赋成当前段的当前地址计数值,并置LnOK。
// (3) 汇编行语义分析。
// (4) 循环。
// (5) 更新段大小。
// (6) 关闭最后一个使用的段的片段。
// (7) 整理符号表。
//---------------------------------------------------------------------------
ERR MacroAsmber::MeaningTrans()
{ Pass = false;
  DebugMsg("\n\t\t\t\t(Pass 2)"; Debugkey;); // debug
  ERR erra = OK_no_Err;

  Ln = AsmFn->FirstLine(); // 从文件的第一汇编行开始, SegPt->SegLc地址预置初值
  SegPt = JModulePt->SegDefHead; // 给当前段指针赋初值, 指向默认段
  SegPt->InitSegTrpHead(Ln);   // Pass2 设置默认段段中新片段。

  for( ; Ln; Ln = Ln->next ) // 全文件扫描
   { // 第二遍扫描,汇编行的lc值被赋成当前段的当前地址计数值,并置LnOK。
     // Pass2, Ln->IsOK 之前是false。
     Ln->lc = SegPt->SegLc; Ln->IsOK = true;
     ERR err = AsmLineMeaningAct();
     if( err )
      { DebugKit( printf("\tErr:%d!",err); );
        erra = Have_Errs; } // endif
   } // end for

  // 退出循环后,SegPt当前段的地址计数器存有最大地址值。
  SegPt->UpdateSegSize(); // 根据SegLc更新段大小,保存上一段的最大地址
  SegPt->CloseCurrentSegTrp(AsmFn->Tail); // 关闭最后一个使用的段的片段。

  DebugMsg(printf("\n(Pass 2)FileFindVar pass=false err = %d", erra); Debugkey;); // debug
     //  AsmFn->ShowFileToken();      Debugkey;
     //  LabMger->ShowLabelList(); Debugkey;
     // JModulePt->show(); Debugkey;

  if(!erra) { erra = LabMger->LabelFresh(); } // endif
  return erra;
} // end MeaningTrans
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
// 输出警告信息。
//---------------------------------------------------------------------------
void MacroAsmber::OutWarning(int8u warn)
{ if(warn > WarningNUM){ warn = WarningNUM; } // endif  Just for Debug!!
  AsmFn->AddWarn(Ln->LineNo,warn);
  if(ErrPrint)
   { fprintf( EpFile.GetEPfile(), "\n*** Warning(Line %u, %s): ",
              Ln->LineNo, (const char*)AsmFn->FileName );
     fprintf( EpFile.GetEPfile(), ErrWarnMsg::warnmsg[warn] );
   } // endif
} // end OutWarning
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
// 输出错误信息。
//---------------------------------------------------------------------------
void MacroAsmber::OutputErr(int8u errno)
{ if(errno > ERRmsgSum){ errno = ERRmsgSum + 1 ; } // endif  Just for Debug!!
  AsmFn->AddErr(Ln->LineNo,errno);
  if(ErrPrint)
   { fprintf( EpFile.GetEPfile(), "\n*** ERROR(Line %u, %s): ",
              Ln->LineNo, (const char*)AsmFn->FileName );
     fprintf( EpFile.GetEPfile(), ErrWarnMsg::errmsg[errno] );
   } // endif
} // end OutputErr
//---------------------------------------------------------------------------

#include "OBJfile_H.h"
//---------------------------------------------------------------------------
//
//                    OBJ文件生成器
//
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
// 产生列表文件。
// 流程:
// (1)初始化。打开列表文件。
// (2)产生列表头。
// (3)产生OBJ目标码。
// (4)产生符号表。
// (5)产生使用的寄存器组号。
// (6)产生列表小结。
// (7)关闭文件。
//---------------------------------------------------------------------------
void MacroAsmber::GenListFile()
{ if(!LstFile) { return; } // endif
  rewind(AsmFn->FilePt);          // 从文件头开始读入

  LstFilePt->OpenFileForWrite();   // 为OutputFile赋初值。

  LstFilePt->GenListHeader();
  LstFilePt->GenOBJList();
  LstFilePt->PrintSymbolTable();
  LstFilePt->GenRegBankUsed();
  fprintf(LstFilePt->OutputFile,"\n\nTotal %d error(s), %d warning(s). ",
                        AsmFn->ErrorSum(), AsmFn->WarningSum());
  if(AsmFn->ErrorSum()==0)
   { fprintf(LstFilePt->OutputFile,"== << Assembly complete. >> =="); } // endif
  else
   { fprintf(LstFilePt->OutputFile,">> Please check your program. <<"); } // end else

  fprintf(LstFilePt->OutputFile,
    "\n==================== << End of list >> ========================",
                (const char*)LstFilePt->FileName );
  LstFilePt->CloseFile();
  printf("\nLIST file has been written to %s.",(const char*)LstFilePt->FileName);
} // end GenListFile
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
// 输入文件名, 把它包含过来。
// 注意,该函数使用Ln,影响Ln。
//---------------------------------------------------------------------------
ERR MacroAsmber::MC_Include(const Jstring& filename)
{ if(++IncFnNest > MaxIncFnNest)
   { FatalErr("\nINCLUDE file nest too deep!"); } // endif

  FILE* IncFnPt = fopen((const char*)filename,"r"); // 给文件句柄赋值。
  if(IncFnPt == NULL)
   { printf("\nCannot open file %s!",filename());
     return Have_Errs;
   } // endif

  AsmLine* IncLine = Ln;      // 保存当前的汇编行。
  AsmLine* LastLine = Ln;     // 保存上一行。

  ERR erra = OK_no_Err;          //
  bool cont = true;              // 在没有遇到END之前,该值为true。

  while(!feof(IncFnPt) && cont)  // 把整个文件转换成Token流。
   { // ............................................
     Ln = new AsmLine;                // 创建新汇编行对象
     Ln->LineNo = IncLine->LineNo;    // 给新行赋行号值
     //Ln->NestNo = 0;                  //
     Ln->Includ = true;               // 打上一个标记
     char* textbuf = AsmFn->buff;     // 使用了AsmFn的缓冲区

     fgets(textbuf, LineReadBufferSize, IncFnPt);
     textbuf[LineReadBufferSize-1]='\0';   // 缓冲区最终端填字串尾。
     register char* p = textbuf + strlen(textbuf) - 1;
     if( *p == '\n' ) { *p = '\0'; } // endif  // p 指向读入行最后一个字符。
     // Now, 已读入了一行文本到textbuf。
     Ln->head->Name = textbuf;        // 它的头节点装有源文本

     // 把ASCII文本字串转换成汇编行。
     ERR err = StrLexToAsmline(textbuf, Ln, AsmFn->CommentEnable); // 带回err值。
     switch(err)
     { case  0 : { break; } // end case
       case  2 : { cont = false; break; } // end case
       default : { erra = Have_Errs; } // end default
     } // end switch
     if(Ln->HeadToken()== MacroCTRLn && MajorCtrlParse(Ln) ) // 首要控制指令
      { erra = Have_Errs; } // endif

     if(Ln->TknLNotEmpty() && cont) // 如果不是只有一个头结点的话, 汇编行加进AsmFile中。
      { AsmFn->InsertAsmLine(Ln, LastLine);
        LastLine = Ln;
      } // endif  // "END"也不能加进去。
     else                   // 只有一个头结点的汇编行不添加到AsmFile中.
      { delete Ln; Ln = LastLine; } // end else
     // ............................................
   } // end while
  // Now, the file has been transfered to AsmFile.
  Ln = IncLine;

  if( fclose(IncFnPt) )
   { printf("\nClose file %s error.",filename()); } // endif

  return erra;
} // MC_Include
//---------------------------------------------------------------------------


//---------------------------------------------------------------------------
// end MAsmber_C5.cpp
//---------------------------------------------------------------------------
//               Written by JamesyFront.    ZLGmcu Dev.Co.Ltd.  2002.
//---------------------------------------------------------------------------

⌨️ 快捷键说明

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