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

📄 masmber_c3.cpp

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

#include "MAsmber_H.h"
#include "OBJfile_H.h"
#include "ListFile_H.h"
#include "OBJModule_H.h"
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
//
//                          语义分析器
//
//---------------------------------------------------------------------------
#define DebugKit(str)    //DebugMsg(str)
//---------------------------------------------------------------------------
// 两次扫描的寻找标号程序。
// 第一遍扫描,确定汇编行所属段。扫描过程中,SegPt需跟踪当前段。
// 第二遍扫描,确定汇编行的地址。建立段中的片段。
// 二次扫描后, 所有的常量都必须算好! 而表达式一旦算好, 就赋给Value存储起来!
// 说明: 在标号中, 它的ExpPt存有创建它的汇编行的指针!
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
// 遇到标号时做。登记表号所在的汇编行,并把它从汇编行中删除。
// This work is done in Pass1. Not in Pass2.
//---------------------------------------------------------------------------
inline ERR MacroAsmber::TknIsLabelDefknDo(Tokenfield* pt)
{ ERR err;
  JLabelNode* tp =
        LabMger->AddLabel( err,             // 错误返回码。
                           pt->Name,        // 标号名。
                           SegPt->GetSegType(), // 标号类型(跟段类型保持一致)。
                           Constant_,       // 标号是常量。
                           Ln,              // 创建该标号的汇编行的指针。
                           NULL,            // 表达式(无)。
                           SegPt,           // 标号所属段(当前段)。
                           true );          // 间接访问。
         // 标号的类型与当前段的类型一致,是常量,创建于当前汇编行,无表达式。
         // 它的值由当前汇编行的lc来决定。参考段与当前段一致。间接访问。
  if( !err )    // 如果在AddLabel过程中没有发生错误,就把它删除。
   { TokenOper::DelnextTokenNode(Ln->head); } // end else
  return err;
} // end TknIsLabelDefknDo
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
// 需要的全局变量有:Pass, Ln。
// 根据pt所指向的Tokenfield建立一个标号,然后禁用该行。
// This work is done both in Pass1 and Pass2.
//---------------------------------------------------------------------------
inline ERR MacroAsmber::AddLabelThenDis(Tokenfield* pt, int8u typ, bool var)
{ ERR err;
// 原型 JlabelNode* AddLabel( ERR &err,const Jstring &name,int8u labelTp,
//                            bool var,  AsmLine* Crln, Tokenfield* pt,
//                            ASM_Segment* rSeg = NULL,
//                            bool Ind = false, bool Ext = false )
  JLabelNode* tp =
        LabMger->AddLabel( err,                // 错误返回码。
                           pt->Name,           // 标号名。
                           typ,                // 标号类型(指定)。
                           var,                // 标号是常量还是变量。
                           Ln,                 // 创建该标号的汇编行的指针。
                           pt->next->ExpPt );  // 表达式。
                   // typ强制转换类型,参考段由结果决定。
  if(!err)         // 添加标号成功
   { pt->Token = pt->Token2;   // Token升级。
     pt->LabPt = tp;           // pt->Value存有指向标号的指针。
     Ln->Enable = false;       // 禁用该行。(Disable)
   } // endif
  return err; // No error.
} // end AddLabelThenDis
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
// Pass1遇到SET指令。
//---------------------------------------------------------------------------
inline ERR MacroAsmber::SetVarLabel(Tokenfield* pt, int8u typ, bool var)
{ ERR err;
// 原型 JlabelNode* AddLabel( ERR &err,const Jstring &name,int8u labelTp,
//                            bool var,  AsmLine* Crln, Tokenfield* pt,
//                            ASM_Segment* rSeg = NULL,
//                            bool Ind = false, bool Ext = false )
  JLabelNode* tp =
     LabMger->AddLabel( err,               // 错误返回码。
                        pt->Name,          // 变量名。
                        typ,               // 标号类型(指定)。
                        var,               // 标号是变量!
                        Ln,                // 创建该标号的汇编行的指针。
                        pt->next->ExpPt ); // 表达式。
                   // typ强制转换类型,参考段由结果决定。
  // 忽略err。
  pt->Token = pt->Token2;     // Token升级。
  pt->LabPt = tp;             // pt->Value存有指向标号的指针。
  if(tp->RefSeg == NULL)
   { tp->RefSeg = JModulePt->SegDefHead; } // endif
  return err;
} // end SetVarLabel
//---------------------------------------------------------------------------
// 在第二次扫描时,遇到SET指令,在标号表中更新对应的变量。
//---------------------------------------------------------------------------
#define SetVarInPass2();                                                        \
        JLabelNode* tp = LabMger->AddLabel( err, pt->Name, LB_NUM,              \
                                      Variable_, Ln, pt->next->ExpPt );         \
        if(err) { return ErrInSetLabel; }                                       \
        if(tp->RefSeg == NULL)                                                  \
         { tp->RefSeg = JModulePt->SegDefHead; }                                \
        pt->LabPt->CopyFrom(*tp);                                               \
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
#define USING_do();                                                             \
         if( TknIsUsing_Do(pt) ) { err = ErrInUsing; }
//---------------------------------------------------------------------------
#define ReservInstDoSth();                                                      \
         if( ReservInstDo(pt) ) { err = ErrInResvInst; }
//---------------------------------------------------------------------------
#define SEGMTDefkn_do();                                                        \
        JLabelNode* tp =                                                        \
        LabMger->AddLabel( err, pt->Name, LB_SEG, Constant_, Ln, NULL );        \
        if(err) { err = ErrInSegmentDef; break; }                               \
        register ASM_Segment* sg = JModulePt->AddSegment(*pt);                  \
        pt->LabPt = tp;                                                         \
        tp->RefSeg = sg;                                                        \
        tp->Attrb  = sg->GetRelType();                                          \
        Ln->Enable = false;
//---------------------------------------------------------------------------
// 原型 JlabelNode* AddLabel( ERR &err,const Jstring &name,int8u labelTp,
//                            bool var,  AsmLine* Crln, Tokenfield* pt,
//                            ASM_Segment* rSeg = NULL,
//                            bool Ind = false, bool Ext = false )
// 遇到SEGMENT指令,往目标模块添加一个新段。往标号表添加一个段标号,
// 标号的value值存放指向段标号的指针。
// 段标号的参考段指针指向新段。最后禁用此行。
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
// 遇到EXTRN指令,把其后的单词表中的外部标号添加到标号表中。然后每添加一个单词,
// 就删除一个单词,直到表空。最后禁用该行。
//---------------------------------------------------------------------------
#define ExTRNKn_do();                                                           \
        for( ; pt && pt->Token == EXTRNKn; pt = Ln->FirstTkn() )                \
         { err = AddExtLabelThenDel(pt);                                        \
           if(err) { err = ErrInExtLabel; break; }                              \
           TokenOper::DelnextTokenNode(Ln->head);                               \
           TokenOper::DelnextTokenNode(Ln->head);                               \
         }                                                                      \
        if(!err) { Ln->Enable = false; }
//---------------------------------------------------------------------------


//---------------------------------------------------------------------------
// 输入一行Asmline的Token流, 对其进行语义分析。
// 需要使用Ln。
//---------------------------------------------------------------------------
ERR MacroAsmber::AsmLineMeaningAct()
{ if(!Ln->Enable) { return OK_no_Err; } // 如果此行被禁用,忽略此行。
  ERR err = OK_no_Err;
  DebugKit(printf("\nMeaning at Line %d...",Ln->GetLineNo());
           Ln->show(); Debugkey;); // debug

  Tokenfield* pt = Ln->head;
  if(pt->Token==MacroCTRLn) { Ln->Enable = false; return OK_no_Err; } // endif

  pt = Ln->FirstTkn(); // 每次从行头开始。
  if(!pt) { Ln->Enable = false; return OK_no_Err; } // 遇到空行, 忽略并禁用。

  // pt指向的是汇编行第一个Tokenfield. (除头结点)
  if(pt->Token == LabelDefkn)     // 遇到一个标号。Be done only in Pass1.
   { // 遇到标号定义,把标号添加到标号表中,并将其从汇编行删除。
     if(TknIsLabelDefknDo(pt)) { return ErrInLabelDef; } // endif
   } // endif
  // 在一个汇编行的开头, 还有什么可以是选择的, 都写到这里来, 这些东西可以省略。

  pt = Ln->FirstTkn();
  if(!pt) { return OK_no_Err; }      // Only have Label defination, return.

  switch(pt->Token)
  { case ReservInst: { ReservInstDoSth(); break; } //  end case         Pass1
    //case OPsetInst : { return OPsetInstDo(pt); } // end case            Pass2
    case PseudoWord: { return PWordMeaningAct(pt); } // end case        Pass1&2
    case DB:     case DW: // 见下。
                     { SegPt->SegLc += Ln->len; break; } // end case    Pass2
    case DS:         { Ln->Enable = false;     // 禁用该行
                       TknIsDSDoSth(pt); break; } // end case Pass2
    case DBIT:       { Ln->Enable = false;     // 禁用该行
                       TknIsDBITDoSth(pt); break; } // end case Pass2

    case SETsDefken: { SetVarInPass2(); break; } // SET。            // Pass2
    case  USINGTkn : { USING_do();      break; } // USING。          // Pass2
    case    ORG    : { TknIsORGDo(pt);  break; } // ORG。            // Pass2
    case   EXTRNKn : { ExTRNKn_do();    break; } // 外部变量定义。   // Pass1
    case SEGMTDefkn: { SEGMTDefkn_do(); break; } // 段定义。         // Pass1

    case MroCalling:   case   END :   // 同下。     // 宏指令。      // Pass1
    case  ReptDefkn:   case IRPTkn:   case IRPCTkn: // 宏指令。      // Pass1
                     { Ln->Enable = false; break; } // end case      // Pass1

    default: { EThrows(printf("\n====== Cannot understand the P-word!!!"); Debugkey;);
               err = Have_Errs;
             } // end default
  } // end switch (pt->Token)
  DebugKit( if(err) { printf("\nErr = %d",err); Debugkey; } // endif
           );

  return err;
} // end AsmLineMeaningAct
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------

⌨️ 快捷键说明

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