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

📄 midtodemi.cpp

📁 上课时老师用过的SNL编译器
💻 CPP
📖 第 1 页 / 共 3 页
字号:
}

/************************************************/
/* 函数名 	arithGen							*/ 
/* 功  能 	生成算术运算的目标代码				*/		
/* 说  明										*/
/************************************************/
void	Cmidtodemi::arithGen(CodeFile  *midcode)
{
   /* 如果代码生成追踪标志TraceCode为TRUE,写入注释,标注操作开始 */
  if (TraceCode) 	  emitComment("-> Op");

  /*生成左操作数的目标代码,值存在ac中*/
  operandGen(midcode->codeR.arg1);

  /* 暂存左操作数 */
  emitRM("LDA",ac2,0,ac,"op: store  left ");  
  
  /*生成右操作数的目标代码,值存在ac中*/
  operandGen(midcode->codeR.arg2);

  /* 取出左操作数ac1*/
  emitRM("LDA",ac1,0,ac2,"op: load left");

  /*根据操作符,生成运算的目标代码,ac中为计算结果*/
  switch(midcode->codeR.codekind)
  {		/*相加*/
		case	ADD:    emitRO("ADD",ac,ac1,ac,"op +");	break;
		/*相减*/
		case	SUB:    emitRO("SUB",ac,ac1,ac,"op -");	break;
		/*相乘*/
		case	MULT:   emitRO("MUL",ac,ac1,ac,"op *");	break;
		/*相除*/
		case	DIV:    emitRO("DIV",ac,ac1,ac,"op /");  break;
		/*小于*/
		case	LTC:  
						/* 写入减指令,将(左-右)操作数相减,结果送累加器ac */
					    emitRO("SUB",ac,ac1,ac,"op <") ;  

					    /* 写入判断跳转指令,如果累加器ac的值小于0,	*
					  	 * 则代码指令指示器跳过两条指令				*/
					    emitRM("JLT",ac,2,pc,"br if true") ;

					    /* 写入载入常量指令,将累加器ac赋值为0 */
					    emitRM("LDC",ac,0,0,"false case") ; 

					    /* 写入数值载入指令,代码指令指示器pc跳过下一条指令 */
					    emitRM("LDA",pc,1,pc,"unconditional jmp") ;

					    /* 写入载入常量指令,将累加器ac赋值为1 */
					    emitRM("LDC",ac,1,0,"true case") ;
					    break;

		/*等于*/
		case	EQC:
						/* 写入减法指令,将左,右操作数相减,结果送累加器ac */
						emitRO("SUB",ac,ac1,ac,"op ==") ;

						/* 写入判断跳转指令,如果累加器ac等于0,	*
						 * 代码指令指示器pc跳过两条指令			*/
						emitRM("JEQ",ac,2,pc,"br if true");

						/* 写入载入常量指令,将累加器ac赋值为0 */
						emitRM("LDC",ac,0,0,"false case") ;

						/* 写入数值载入指令,代码指令指示器pc跳过一条指令 */
						emitRM("LDA",pc,1,pc,"unconditional jmp") ;

						/* 写入载入常量指令,将累加器ac赋值为1 */
						emitRM("LDC",ac,1,0,"true case") ;
						break;
		default :       break;
  }

  /*后面要用ac,故保存ac*/
  emitRM("LDA",ac2,0,ac,"op: store  result ");  

  /*计算目的操作数的地址,存在ac中*/
  FindAddr(midcode->codeR.arg3);

  /*取出暂存的计算结果,存入ac1*/
  emitRM("LDA",ac1,0,ac2,"op: load result");

  /*计算结果存入目的操作数*/
  emitRM("ST",ac1,0,ac, "");

  /* 如果代码生成追踪标志TraceCode为TRUE,写入注释信息,标注操作结束 */
  if (TraceCode)  emitComment("<- Op") ;
 
}

/************************************************/
/* 函数名 	operandGen							*/ 
/* 功  能 	生成操作数的目标代码				*/		
/* 说  明	分操作数为常数或者变量两种情况处理	*/
/*			注意不能用ac2						*/
/************************************************/
void Cmidtodemi:: operandGen(ArgRecord  *arg)
{
	switch(arg->form)
	{ /*操作数为常数*/
	  case  ValueForm :	   
			/* 如果代码生成追踪标志TraceCode为TRUE,写入注释,常数部分开始 */
			if (TraceCode) emitComment("-> Const") ;

			/* 生成载入常量指令,载入常量到累加器ac */
			emitRM("LDC",ac,arg->Attr.value,0,"load const");
	  
			/* 如果代码生成追踪标志TraceCode为TRUE,写入注释,常数部分结束 */
			if (TraceCode)  emitComment("<- Const") ;
			break; 

      /*分量为标号*/
	  case  LabelForm:
		  /* 如果代码生成追踪标志TraceCode为TRUE,写入注释,标号部分开始 */
			if (TraceCode) emitComment("-> Label") ;

			/* 生成载入标号指令,载入标号值到累加器ac */
			emitRM("LDC",ac,arg->Attr.label,0,"load label");
	  
			/* 如果代码生成追踪标志TraceCode为TRUE,写入注释,标号部分结束 */
			if (TraceCode)  emitComment("<- Label") ;
			break; 

	  /*操作数为变量,有可能是临时变量*/
	  case  AddrForm:
			 /* 如果代码生成追踪标志TraceCode为TRUE,写入注释,标注标识符开始 */
			if (TraceCode) emitComment("-> var") ;
	  
			FindAddr(arg);
			/*其中ac返回的是源变量或临时变量的绝对偏移*/
	  
			if(arg->Attr.addr.access==indir)
			{   
				
				/*取内容作为地址,再取内容*/
				emitRM("LD",ac1,0,ac,"indir load id value");
				emitRM("LD",ac,0,ac1,"");
			}
			else
			{   /*存的是值*/
				/* 写入数值载入指令,载入变量标识符的值*/
				emitRM("LD",ac,0,ac,"load id value");
			}

			/* 如果代码生成追踪标志TraceCode为TRUE,写入注释,标注标识符结束 */
	  		if (TraceCode)  emitComment("<- var") ;
			break;
	 
	  default:  break;
	}
}

/************************************************/
/* 函数名 	aaddGen								*/ 
/* 功  能 	生成地址加操作的目标代码			*/		
/* 说  明										*/
/************************************************/
void	Cmidtodemi::aaddGen(CodeFile  *midcode)
{	/* 如果代码生成追踪标志TraceCode为TRUE,写入注释,aadd语句开始 */
	if(TraceCode)  emitComment("->address  add");
  
	if(midcode->codeR.arg1->Attr.addr.access == dir)
	{   /*ac中的地址即为基地址*/
		/*计算变量的绝对偏移,ac中存为变量的绝对偏移*/
        FindAddr(midcode->codeR.arg1);
	}
	else
	{   /*ac中的地址存放的内容为基地址*/
		/*计算变量的绝对偏移,ac中存为变量的绝对偏移*/
        FindAddr(midcode->codeR.arg1);
		emitRM("LD",ac,0,ac,"");
	}
    /*基地址转存到ac2*/
    emitRM("LDA",ac2,0,ac,"op: store  baseaddr ");  

	/*求地址相加运算的偏移量,存在ac中*/
	operandGen(midcode->codeR.arg2);

	/*地址相加,结果在ac中*/
	emitRO("ADD",ac2,ac2,ac,"op +");
    
    /*求目的变量的地址,存入ac*/
    FindAddr(midcode->codeR.arg3);

    /*地址相加结果写入目的变量*/
    emitRM("ST",ac2,0, ac,"");

}

/************************************************/
/* 函数名 	readGen								*/ 
/* 功  能 	生成读操作的目标代码				*/		
/* 说  明	根据变量是直接变量还是间接变量进行	*/
/*			不同的处理							*/
/************************************************/
void	Cmidtodemi::readGen(CodeFile  *midcode)
{
	/*生成读指令,该指令完成读入外部数值到累加器ac2的动作*/
	emitRO("IN",ac2,0,0,"read integer value");

	/*计算变量的绝对偏移,ac中存为变量的绝对偏移*/
	FindAddr(midcode->codeR.arg1);
    
	if(midcode->codeR.arg1->Attr.addr.access == dir)
	{	/*直接存*/
		/*最后生成存储指令*/
		emitRM("ST",ac2,0,ac," var read : store value");
	}
	else
	{
		/*以ac内容作为地址找变量单元,再存*/
		emitRM("LD",ac1,0,ac,"");
		emitRM("ST",ac2,0,ac1," indir var read : store value");
	}
}

/************************************************/
/* 函数名 	writeGen							*/ 
/* 功  能 	生成写操作的目标代码				*/		
/* 说  明	调用函数得到值,并产生输出代码		*/
/************************************************/
void	Cmidtodemi::writeGen(CodeFile  *midcode)
{
	/*调用函数,得到输出的值,存在ac中*/
	operandGen(midcode->codeR.arg1);
	
	/*生成写指令,该指令完成将累加器ac中的值输出的动作*/
	emitRO("OUT",ac,0,0,"write ac");

}

/************************************************/
/* 函数名 	returnGen							*/ 
/* 功  能 	生成返回语句的目标代码				*/		
/* 说  明	返回过程调用的下一条语句,注意return*/
/*			语句只在过程中出现					*/
/************************************************/
void	Cmidtodemi::returnGen(CodeFile  *midcode)
{
	/*从过程里跳出,所做的工作与过程结束相同*/
	endprocGen(midcode);

}

/************************************************/
/* 函数名 	assigGen							*/ 
/* 功  能 										*/		
/* 说  明										*/
/************************************************/
void	Cmidtodemi::assigGen(CodeFile  *midcode)
{
	/* 如果代码生成追踪标志TraceCode为TRUE,写入注释,assign语句开始 */
	if(TraceCode)  emitComment("->assign");
    
	/*赋值左部变量的地址,存在ac中*/
	FindAddr(midcode->codeR.arg2);
	/*转放在ac2中*/
    emitRM("LDA",ac2,0,ac,"op: store  addr ");  

	/*生成赋值右部的目标代码,值存在ac中*/
    operandGen(midcode->codeR.arg1);

	if(midcode->codeR.arg2->Attr.addr.access==dir)
		/*赋值,ac2中为地址*/
		emitRM("ST",ac,0,ac2,"var assign : store value");
	else
	{
		/*从ac2中取出内容,作为地址*/
		emitRM("LD",ac1,0,ac2," indir var assign");
		emitRM("ST",ac,0,ac1," store value");
	}
		
	/* 如果代码生成追踪标志TraceCode为TRUE,写入注释,assign语句结束 */
    if (TraceCode)  emitComment("<- assign") ;

}

/************************************************/
/* 函数名 	labelGen							*/ 
/* 功  能 										*/		
/* 说  明										*/
/************************************************/
void	Cmidtodemi::labelGen(CodeFile  *midcode)
{
  /*取得标号值*/
  int label = midcode->codeR.arg1->Attr.label;

  /*取得当前目标代码编号*/
  int currentLoc = emitSkip(0) ;
  
  /*查找标号地址表*/
  LabelAddr  *item = labelAddrT;
  LabelAddr  *last = item;
  while (item!=NULL)
  {	if (item->label == label)
		break;
    last = item;
    item = item->next;
  }

  if (item==NULL)  /*表中没有此标号对应得项,填表 */
  { /*新建一项*/
	LabelAddr  *newItem = (LabelAddr *)malloc(sizeof(LabelAddr));
    newItem->label = label;
	newItem->destNum = currentLoc;
	newItem->next = NULL;
    /*加入标号地址表中*/
    if (labelAddrT == NULL)
		labelAddrT = newItem;
	else last->next = newItem;
 }
 else /*表中有此标号对应项,则回填目标代码*/ 
 {  
	/*退回到指令回填地址*/
	emitBackup(item->destNum);
	/*写入跳转到此标号所在目标代码位置的代码*/
	emitRM("LDC",pc,currentLoc,0,"jump to label");
	/*恢复当前目标代码*/
	emitRestore();

 }
}

/************************************************/
/* 函数名 	jumpGen								*/ 
/* 功  能	生成跳转的目标代码					*/		
/* 说  明   参数i是为了复用此函数而设,根据i	*/
/*			决定从中间代码中哪个分量取标号值	*/
/************************************************/
void	Cmidtodemi::jumpGen(CodeFile  *midcode, int i)
{
  int  label ;

⌨️ 快捷键说明

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