📄 masmber_c3.cpp
字号:
//---------------------------------------------------------------------------
// 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 + -