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

📄 assembler.cpp

📁 MIPS32指令系统的汇编器。 在QUARTUS仿真环境中
💻 CPP
📖 第 1 页 / 共 5 页
字号:
#include "assembler.h"


Assembler::Assembler()
{
	InitTwoTables();		//初始化预测分析表和语法规则表
	InitRegsAlias();	//初始化寄存器编号与别名对应表
	GenFiles();
	TOKEN.TokenID = 0;
	TOKEN.TokenName = "";
	No_Com = 0;		//指令行编号
	No_Var = 0;		//变量行编号
	No_TxtLine = 0;

	for ( int z = 0; z < RamSize; z++ )
	{
		CodeUnitUsed[z] = false;
		DataUnitUsed[z] = false;
	}
}

Assembler::~Assembler()
{	
	ShutFiles();
}

void Assembler::Parser( FILE* SourceFileName )
{
	int v = SyntacticAnalysis(SourceFileName);
	if ( v != 0 )
	{
		cout << "Error occurs...SyntacticAnalysis' return value: " << v << endl;
		ErrorProcess(v);
	}
	else
		cout << "Succeed!" << endl;
}

int Assembler::SyntacticAnalysis( FILE * SourceFileName )
{
	int i;
	int LastRule;

	int dataline = 0;	//用以指示数据文件的行数

	TOKEN.TokenID = 0;
	STACK.push(-1);
	STACK.push(N_PRO); 

	// CMD是32位char类型,存放最新已经语法分析得到的指令的二进制码,初始化为'0'
	for ( i = 0; i < 32; i++ )
		CMD[i] = '0';

	// 调用词法分析器Scanner,依据栈顶符号<N_PRO>,从源程序中读取第一个
	// 单词入TOKEN中,如果返回-1,表示源程序中有词法错误
	if ( Scanner(STACK.top(), SourceFileName) )
		return ERROR_LEX;
	//cout << TOKEN.TokenID << '\t' << TOKEN.TokenName << endl;
	//开始LL(1)分析,包含调用词法分析器Scanner和指令翻译器ConstructCMD
	while (1)
	{
		if ( STACK.top() == -1 )		//若栈空,且当前读入源程序单词为-1,则语法分析完成,并正确
		{
//				fprintf( DataFile, "END;" );	//写入数据文件最后一个单词"END"
			// 以下是写数据文件的结尾,因为程序文件是一次性写的,所以它的起始和结尾都是在同一个函数WriteProg()中完成的
			fprintf( DataFile, "		[" );
			fprintf( DataFile, "% x", No_Var );
			fprintf( DataFile, "..3FF] : 00000000;\nENDS;" );

			int rrt = WriteProg();
			if ( rrt == -1 )   //将指令写入程序文件,返回值为-1,表示地址交迭
				return ERROR_CODE_ADDR_OVERLAPPED;
			else if ( rrt == -2 )   //将指令写入程序文件,返回值为-2,表示有转移指令引用不存在的指令标号名
				return ERROR_NOTEXIST_SEGID;
			return 0;       //汇编过程成功退出
		}
		if ( STACK.top() > CountOfVT )
					//如果当前栈顶为VN,则查预测分析表
		{
	//		if ( (STACK.empty()) || (TOKEN.TokenID == -1) )
					//若栈空,且当前读入源程序单词为-1,则语法分析完成,并正确
			if ( ForcastTable[STACK.top()-CountOfVT][TOKEN.TokenID] == 0 )
				return ERROR_SEMANTIC;
			else
			{
				LastRule = ForcastTable[STACK.top()-CountOfVT][TOKEN.TokenID]; //记录编号
//				cout << "NT:LastRule: " << LastRule << "\tTOKEN.TokenID: " << TOKEN.TokenID << endl;
				if ( Deduction(ForcastTable[STACK.top()-CountOfVT][TOKEN.TokenID]) == 5 )
					return ERROR_DEDUCTION;
				continue;
			}
		}
		else
					//当前栈顶为VT,则匹配,并翻译
		{
			if ( STACK.top() == TOKEN.TokenID )
					//当栈顶为终结符,并和当前读取的单词同,则匹配
			{
				// store segids with SEGID
				if ( LastRule == 27 && TOKEN.TokenID == T_IDNAME )
						//如果最近采用的是27号产生式,则IDNAME是指令标号,
						//顺序保存到标号表SEGID
					if ( AddNormalSegID() )
						return ERROR_REIDNAME;	//如果标号有重复则错误退出
				if ( LastRule == 15 && TOKEN.TokenID == T_IDNAME )
						//如果最近采用的是15号产生式,则IDNAME是起始指令标号,
						//保存到标号表SEGID的最前面
					if ( AddStartSegID() )
						return ERROR_REIDNAMES;	//如果标号有重复则错误退出 
				if ( ( LastRule == 36 || LastRule == 42 ) && TOKEN.TokenID == T_IDNAME )  //J,JAL,BEQ,BNE中遇到IDNAME,需要回填
						//如果最近采用的是36号产生式,则IDNAME是转移的目的标号
						//保存到回填表BACKTABLE中
					if ( AddBackID() )
						return ERROR_BACK;	//添加失败则错误退出 
				
				/////////////TRANSLATATION/////////////////////////////////////
				//////////SEMANTICS RULES OF <N_COM> RULES/////////////////////
				if ( LastRule == 17 || LastRule == 18 || LastRule == 19
					|| LastRule == 20 || LastRule == 21 || LastRule == 22
					|| LastRule == 23 || LastRule == 30 || LastRule == 32
					|| LastRule == 33 || LastRule == 34 || LastRule == 35
					|| LastRule == 37 ||LastRule == 36 || LastRule == 38
					|| LastRule == 39 || LastRule == 40 || LastRule == 41 || LastRule == 42 || LastRule == 43 )	//表明当前读取的是指令   LastRule == 36,23|| ??? J,JAL,BEQ,BNE中遇到IDNAME,需要回填
				{
/*					cout << "VT:LastRule: " << LastRule << endl
						 << "STACK.top(): " << STACK.top() << endl
						 << "TOKEN.TokenID: " << TOKEN.TokenID << endl
						 << "TOKEN.TokenName: " << TOKEN.TokenName << endl;
*/ 					if ( STACK.top() != T_ENDL ) //如果当前读取的不是指令结束的单词,则翻译
					{
						if ( ConstructCMD() ) // 将当前单词翻译为二进制码,存入CMD,注意这些函数是成功时才返回0,否则返回非零值
							return ERROR_CONCMD;		//翻译失败退出
					}
					else if ( STACK.top() == T_ENDL )
						//当前读取的是指令结束的单词,则CMD保存了一个完整指令的二进制码,并且当前TOKEN.TokenName串中保存的就是用户解释
					{
						if ( ConstructCOMMANDS() )
									//将CMD按照指令顺序保存到指令链COMMANDS
							return ERROR_CONCMDS;
//						cout << "after concmds: " << endl;
					}
				}

				////////
				////////
				if ( LastRule == 9 && STACK.top() == T_IDNAME )
						//如果当前读取的是标识符,且产生式为9号
						//则说明当前是定义变量,将变量标识符保存到VAR
					if ( StoreVar() )
						return ERROR_DEFVAR;		//变量定义错误

				////////
				////////
				if ( LastRule == 9 && STACK.top() == T_32NUM )
						//如果当前读取的是32位数据,且产生式为9号
						//则说明当前是定义变量,将值输出到数据文件
				{
					if ( DataUnitUsed[No_Var] == true )
						return ERROR_DATA_ADDR_OVERLAPPED;
					if ( dataline != No_Var )
					{
						if ( dataline == No_Var - 1 )
						{
							fprintf( DataFile, "\t" );
							fprintf( DataFile, "% x", dataline );
							fprintf( DataFile, " : \t00000000;\n" );
						}
						else
						{
							fprintf( DataFile, "\t\t[" );
							fprintf( DataFile, "% x", dataline );
							fprintf( DataFile, ".." );
							fprintf( DataFile, "% x", No_Var - 1 );
							fprintf( DataFile, "] : 00000000;\n" );
						}
						dataline = No_Var;
					}
					fprintf( DataFile, "     " );
					fprintf( DataFile, "% x", No_Var );
					fprintf( DataFile, " : " );
					fprintf( DataFile, TOKEN.TokenName );
					fprintf( DataFile, ";\n" );
					DataUnitUsed[No_Var] = true;
					No_Var++;
					dataline++;
				}
				//////////////////////
				//////////////////////以下是由读入的ADDR来设置指令地址No_Com和数据地址No_Var
				if ( LastRule == 5 && STACK.top() == T_ADDR )	//数据地址
				{
					int tempv = AddrToInt( TOKEN.TokenName );
					if ( tempv % 4 != 0 )	//如果地址不能被4整除,则返回错误
						return ERROR_DATA_ADDR;
					No_Var = tempv/4;
				}
				if ( LastRule == 13 &&STACK.top() == T_ADDR )	//指令地址
				{
					int tempc = AddrToInt( TOKEN.TokenName );
//					cout << tempc << endl;
					if ( tempc % 4 != 0 )	//如果地址不能被4整除,则返回错误
						return ERROR_CODE_ADDR;
					No_Com = tempc/4;
				}
				///////////////////////////////////////////////////////
				STACK.pop();	//匹配完成弹出栈顶元素 
				if ( STACK.top() == -1 )
				{
//					cout << "stack is empty" << endl;
					continue;
				}
 //				cout << "After  pop stack, top is " << STACK.top() << endl;
				if ( Scanner(STACK.top(), SourceFileName) )
				{
					return ERROR_LEX;
				}
 //				cout << "after scanner: " << TOKEN.TokenID << '\t' << TOKEN.TokenName << endl;
			}
			else	//栈顶为终结符,并和当前读取的单词不同,则匹配失败
			{
				return ERROR_SEMANTIC;
			}
		}
	}  // end while

	return -1;
}


int Assembler::Scanner(int TypeOfToken,FILE *SourceFileName)
{
	int State=0;
	static char ret[256];
	int i = 0;
	int times = 0;
	if ( TypeOfToken > CountOfVT )     //当前栈顶符号为非终结符
	{
		switch ( TypeOfToken-CountOfVT )
		{
		case 1:						//当前栈顶符号为<N_PRO>
		case 2:						//当前栈顶符号为<N_DATA>
			{                        //扫描DATA或CODE单词
				char ch = ReadOneChar(SourceFileName);
				if ( ch == '\n' )
					No_TxtLine++;
				while ( 1 )
				{
					switch ( ch )
					{
					case 'd':
					case 'D':
						{
							if(State==0) {State=1;break;}
							if(State==6) {State=7;break;}
							else return -1;
						}
					case 'a':
					case 'A':
						{
							if(State==1) {State=2;break;}
							if(State==3) {State=4;break;}
							else return -1;
						}
					case 't':
					case 'T':
						{
							if(State==2) {State=3;break;}
							else return -1;
						}
					case 'c':
					case 'C':
						{
							if(State==0) {State=5;break;}
							else return -1;
						}
					case 'o':
					case 'O':
						{
							if(State==5) {State=6;break;}
							else return -1;
						}
					case 'e':
					case 'E':
						{
							if(State==7) {State=8;break;}
							else return -1;
						}
					case ' ':
					case '\t':
//					case '\n':
						{
							if(State==4){TOKEN.TokenID=1;TOKEN.TokenName="DATA";return 0;}
							if(State==8){TOKEN.TokenID=1;TOKEN.TokenName="CODE";return 0;}
							else return -1;
						}
					default: return -1;
					}
					ch = getc( SourceFileName );
					if ( ch == '\n' )
						No_TxtLine++;
				}
				break;
			}
		case 4:					//当前栈顶符号为<N_DATASEG>
		case 9:					//当前栈顶符号为<N_DATAENDS>
			{                   //根据预测分析表,以上两种情况应该扫描DATA单词
				char ch = ReadOneChar(SourceFileName);
				if ( ch == '\n' )
					No_TxtLine++;
				while ( 1 ) 
				{
					switch ( ch )
					{
					case 'd':
					case 'D':
						{
							if(State==0) {State=1;break;}
							else return -1;
						}
					case 'a':
					case 'A':
						{
							if(State==1) {State=2;break;}
							if(State==3) {State=4;break;}
							else return -1;
						}
					case 't':
					case 'T':
						{
							if(State==2) {State=3;break;}
							else return -1;
						}
					case ' ':
					case '\t':
//					case '\n':
						{
							if(State==4){TOKEN.TokenID=1;TOKEN.TokenName="DATA";return 0;}
							else return -1;
						}
					default: return -1;
					}
					ch = getc(SourceFileName);
					if ( ch == '\n' )
						No_TxtLine++;
				}
				break;
			}
		case 5:					//当前栈顶符号为<N_ORG_DATA>
			{                   //应该扫描ORG_DATA单词
				char ch = ReadOneChar(SourceFileName);
				if ( ch == '\n' )
					No_TxtLine++;
				while ( 1 )
				{
					switch ( ch )
					{
					case 'o':
					case 'O':
						{
							if(State==0) {State=1;break;}
							else return -1;
						}
					case 'r':
					case 'R':
						{
							if(State==1) {State=2;break;}
							else return -1;
						}
					case 'g':
					case 'G':
						{
							if(State==2) {State=3;break;}
							else return -1;
						}
					case '_':
						{
							if(State==3) {State=4;break;}
							else return -1;
						}
					case 'd':
					case 'D':
						{
							if(State==4) {State=5;break;}
							else return -1;
						}
					case 'a':
					case 'A':
						{
							if(State==5) {State=6;break;}
							if(State==7) {State=8;break;}
							else return -1;
						}
					case 't':
					case 'T':
						{
							if(State==6) {State=7;break;}
							else return -1;
						}
					case ' ':
					case '\t':
//					case '\n':
						{
							if(State==8){TOKEN.TokenID=2;TOKEN.TokenName="ORG_DATA";return 0;}
							else return -1;
						}
                   default:return -1;
					}
					ch = getc(SourceFileName);
					if ( ch == '\n' )
						No_TxtLine++;
				}
				break;
			}
		case 6:						//当前栈顶符号为<N_PRO>
		case 8:						//当前栈顶符号为<N_VAR>
		case 13:					//当前栈顶符号为<N_SEG>
		case 14:					//当前栈顶符号为<N_START SEGID>
		case 18:					//当前栈顶符号为<N_SUBSEGID>
			{                                 //以上五种情况,应该扫描IDNAME单词
				i = 0;
				char ch = ReadOneChar( SourceFileName );
				if ( ch == '\n' )
					No_TxtLine++;
				ret[i++] = ch;
				while ( 1 )
				{
					if ( ((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')) && (State==0||State==1) )
					{
						State = 1;
						ch = getc( SourceFileName );
						if ( ch == '\n' )
							No_TxtLine++;
						ret[i++] = ch;
						continue;
					}
					if ( (ch>='0'&&ch<='9') && State == 1 )
					{
						State = 1;
						ch = getc( SourceFileName );
						if ( ch == '\n' )
							No_TxtLine++;
						ret[i++] = ch;
						continue;
					}
					if ( State == 1 )
						if ( ungetc(ch, SourceFileName) )
						{
							if ( ch == '\n' )
								No_TxtLine--;
							ret[--i]='\0';
							TOKEN.TokenID=3;
							TOKEN.TokenName=ret;
							return 0;
						}
						else
							return -1;
					else 
						return -1;
				}
				break; 
			}
		case 7:							//当前栈顶符号为<N_VARS>'
			{                           //应该扫描DATA或IDNAME单词
				i = 0;
				char ch=ReadOneChar(SourceFileName);
				if ( ungetc(ch, SourceFileName) == 0 ) return -1;
				while ( 1 )
				{
					ch = getc( SourceFileName );
					if ( ch == '\n' )
						No_TxtLine++;
					ret[i++] = ch;
					switch ( ch )
					{
					case 'd':
					case 'D':
						{
							if(State==0) {State=1;break;}
							if(State==1) {State=5;break;}
							if(State==2) {State=5;break;}
							if(State==3) {State=5;break;}
							if(State==4) {State=5;break;}
							if(State==5) {State=5;break;}
							return -1;
						}
					case 'a':
					case 'A':
						{
							if(State==1) {State=2;break;}
							if(State==0) {State=5;break;}
							if(State==2) {State=5;break;}
							if(State==3) {State=4;break;}
							if(State==4) {State=5;break;}
							if(State==5) {State=5;break;}
							return -1;
						}
					case 't':
					case 'T':
						{
							if(State==2) {State=3;break;}
							if(State==0) {State=5;break;}
							if(State==1) {State=5;break;}
							if(State==3) {State=5;break;}
							if(State==4) {State=5;break;}

⌨️ 快捷键说明

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