www.pudn.com > subpas.rar > CodeGen.c


/****************************************************/ 
/* File: code.h                                     */ 
/* Code emitting utilities and implementaton		*/ 
/* for the SubPas compiler 					        */ 
/****************************************************/ 
 
#include  
#include "globals.h" 
#include "parse.h" 
#include "CodeGen.h" 
 
typedef struct savedRegidx{ 
	int value; 
	struct savedRegidx * next; 
	} SavedRegidx; 
 
static char * regint[] = {"ax","bx","cx","dx"}; 
 
static char * regreal[] = {"eax","ebx","ecx","edx"}; 
 
static int regidx = 0; 
 
static SavedRegidx * savedregidx = NULL; 
 
int RealUsed = FALSE; 
 
char * newLabel(void) 
{ 
	static int i=1; 
	char * lab; 
	lab = (char *)malloc(8); 
	if(lab==NULL) { 
		printf("Fatal Error:Out of memory."); 
		exit(1); 
	} 
	sprintf(lab,"Lab%d",i); 
	i++; 
	return lab; 
} 
/*生成readln过程的代码*/ 
void genReadln(void) 
{	 
	fprintf(asmfile,";////////////////////////////////////////////////////////\n\n"); 
	fprintf(asmfile,"_readln\tPROC\tNEAR\n"); 
	fprintf(asmfile,"; The offset of parameters is:\n"); 
	fprintf(asmfile,"\t_x$ = 4\n"); 
	fprintf(asmfile,"\tpush\tbp\n"); 
	fprintf(asmfile,"\tmov\tbp,sp\n"); 
	fprintf(asmfile,"\tmov\tdx,0\t;number will store here\n"); 
	fprintf(asmfile,"\tmov\tch,0\t;indicate that whether the char is digit\n"); 
	fprintf(asmfile,"\tmov\tcl,0\t;indicate that whether the number is positive\n"); 
	fprintf(asmfile,"\tmov\tah,1\n"); 
	fprintf(asmfile,"\tint\t21h\n"); 
	fprintf(asmfile,"\tcmp\tal,'-'\n"); 
	fprintf(asmfile,"\tjne\tpositive$\n"); 
	fprintf(asmfile,"\tmov\tcl,1\n"); 
	fprintf(asmfile,"\tnewchar$:\n"); 
	fprintf(asmfile,"\tmov\tah,1\n"); 
	fprintf(asmfile,"\tint\t21h\n"); 
	fprintf(asmfile,"\tpositive$:\n"); 
	fprintf(asmfile,"\tcmp\tal,0dh  ;if enter?\n"); 
	fprintf(asmfile,"\tje\tenter$\n"); 
	fprintf(asmfile,"\tcmp\tch,1\t\t;not convert\n"); 
	fprintf(asmfile,"\tje\tnewchar$\n"); 
	fprintf(asmfile,"\tsub\tal,30h\t\n"); 
	fprintf(asmfile,"\tjl\tnotdigit$\t;not digit\n"); 
	fprintf(asmfile,"\tcmp\tal,9\n"); 
	fprintf(asmfile,"\tjg\tnotdigit$\t;not digit,too\n"); 
	fprintf(asmfile,"\timul\tdx,10\n"); 
	fprintf(asmfile,"\tmov\tah,0\n"); 
	fprintf(asmfile,"\tadd\tdx,ax\t;now handled a digit\n"); 
	fprintf(asmfile,"\tjmp\tnewchar$\n"); 
	fprintf(asmfile,"\tnotdigit$:\n"); 
	fprintf(asmfile,"\tmov\tch,1\n"); 
	fprintf(asmfile,"\tjmp\t newchar$\n"); 
	fprintf(asmfile,"\tenter$:\n"); 
	fprintf(asmfile,"\tmov\tdi,word ptr _x$[bp]\t\n"); 
	fprintf(asmfile,"\tcmp\tcl,1\n"); 
	fprintf(asmfile,"\tjne\tnext$\n"); 
	fprintf(asmfile,"\tneg\tdx\n"); 
	fprintf(asmfile,"\tnext$:\n"); 
	fprintf(asmfile,"\tmov\t[di],dx\t;save the number\n"); 
	fprintf(asmfile,"\tmov\tdl,10\t\t;打印换行符\n"); 
	fprintf(asmfile,"\tmov\tah,2\n"); 
	fprintf(asmfile,"\tint\t21h\n"); 
	fprintf(asmfile,"\tmov\tsp,bp\n"); 
	fprintf(asmfile,"\tpop\tbp\n"); 
	fprintf(asmfile,"\tret\t2\n"); 
	fprintf(asmfile,"_readln\tENDP\n\n"); 
} 
/*生成writeln过程的代码*/ 
void genWriteln(void) 
{ 
	fprintf(asmfile,";////////////////////////////////////////////////////////\n\n"); 
	fprintf(asmfile,"_writeln\tPROC\tNEAR\n"); 
	fprintf(asmfile,";\tThe\toffset of\tparameters is:\n"); 
	fprintf(asmfile,"_x$\t=\t4\n"); 
	fprintf(asmfile,"push\tbp\n"); 
	fprintf(asmfile,"mov\tbp,sp\n"); 
	fprintf(asmfile,"mov\tax,word\tptr\t_x$[bp]\t;把数放到ax\n"); 
	fprintf(asmfile,"cmp\tax,0\n"); 
	fprintf(asmfile,"jge\tnext1$\t\t;若为负数,则打印负号\n"); 
	fprintf(asmfile,"mov\tcx,ax\n"); 
	fprintf(asmfile,"mov\tdl,'-'\n"); 
	fprintf(asmfile,"mov\tah,2\n"); 
	fprintf(asmfile,"int\t21h\n"); 
	fprintf(asmfile,"mov\tax,cx\n"); 
	fprintf(asmfile,"neg\tax\t\t\t;负数转为正数\n"); 
	fprintf(asmfile,"next1$:\n"); 
	fprintf(asmfile,"mov\tcx,0\t\t;cx用来保存该正数的位数,即入栈个数\n"); 
	fprintf(asmfile,"mov\tbx,10\t\t;bx用作除数\n"); 
	fprintf(asmfile,"mov\tdx,0\t\t;屏蔽高位\t\n"); 
	fprintf(asmfile,"loop3$:\n"); 
	fprintf(asmfile,"div\tbx\t\t;将ax:bx中的数除以10,以得到余数和商\n"); 
	fprintf(asmfile,"cmp\tax,10\n"); 
	fprintf(asmfile,"jb\tprint$\t\t;如果商只有一位,则打印该数字\n"); 
	fprintf(asmfile,"push\tdx\t\t;否则,保存余数,\n"); 
	fprintf(asmfile,"inc\tcx\t\t;并增加保存余数的个数\n"); 
	fprintf(asmfile,"mov\tdx,0\t;屏蔽余数\n"); 
	fprintf(asmfile,"jmp\tloop3$\t;将商继续除以10\n"); 
	fprintf(asmfile,"print$:\n"); 
	fprintf(asmfile,"push\tdx\t;将个位数保存\n"); 
	fprintf(asmfile,"inc\tcx\n"); 
	fprintf(asmfile,"cmp\tax,0\t;这时ax是最高位,如果为0,\n"); 
	fprintf(asmfile,"jz\tprint_left$\t;则不打印,对应该数能被10除尽的情况;\n"); 
	fprintf(asmfile,"mov\tdl,al\t;将al中的数移到dl中\n"); 
	fprintf(asmfile,"add\tdl,30h\t;以打印该数\n"); 
	fprintf(asmfile,"mov\tah,2\n"); 
	fprintf(asmfile,"int\t21h\n"); 
	fprintf(asmfile,"print_left$:\n"); 
	fprintf(asmfile,"cmp\tcx,0\t;如果没有保存余数的个数为零,\n"); 
	fprintf(asmfile,"jz\texit$\t;则退出\n"); 
	fprintf(asmfile,"pop\tax\t;否则,把余数出栈\n"); 
	fprintf(asmfile,"mov\tdl,al\t;并放到dl中\n"); 
	fprintf(asmfile,"add\tdl,30h\t;打印\t\n"); 
	fprintf(asmfile,"mov\tah,2\n"); 
	fprintf(asmfile,"int\t21h\n"); 
	fprintf(asmfile,"dec\tcx\t;保存余数的个数减一\n"); 
	fprintf(asmfile,"jmp\tprint_left$\n"); 
	fprintf(asmfile,"exit$:\n"); 
	fprintf(asmfile,"mov\tah,2\t;打印回车\n"); 
	fprintf(asmfile,"mov\tdl,13\n"); 
	fprintf(asmfile,"int\t21h\n"); 
	fprintf(asmfile,"mov\tdl,10\n"); 
	fprintf(asmfile,"int\t21h\n"); 
	fprintf(asmfile,"mov\tsp,bp\n"); 
	fprintf(asmfile,"pop\tbp\n"); 
	fprintf(asmfile,"ret\t2\n"); 
	fprintf(asmfile,"_writeln\tENDP\n\n"); 
} 
void modifyName(char * name) 
{ 
	size_t i = strlen(name); 
	if(i>20) i = 19;  
	name[i+1] = 0; 
	for( ; i>0 ; i--)	name[i] = name[i-1]; 
	name[0] = '_'; 
} 
 
/*生成数据区的声明,参数为树的公共变量声明根节点*/ 
void genDataSegment(TreeNode * t) 
{ 
	char * TypeData[] ={"DW",//integer 
						 "DD",//real 
						 "DW"//boolean 
						}; 
	fprintf(asmfile,".DATA\n"); 
	while(t){ 
		modifyName(t->name); 
		switch( t->type ){ 
			case Integer: 
			case Real: 
			case Boolean: 
				fprintf(asmfile,"\t%s\t%s\t?\n",t->name,TypeData[t->type]); 
				break; 
			case Array: 
				fprintf(asmfile,"\t%s\t%s\t%d\tdup(?)\n",t->name,TypeData[t->attr.arrayattr->type], 
							t->attr.arrayattr->count); 
				break; 
		} 
		t = t->sibling; 
	} 
	fprintf(asmfile,"\n"); 
} 
 
/*主过程的初始化*/ 
void initMainPro(void) 
{ 
	fprintf(asmfile,"_MAIN\tPROC\tFAR\n"); 
	fprintf(asmfile,"; Store return address to OS:\n"); 
	fprintf(asmfile,"\tpush\tds\n"); 
	fprintf(asmfile,"\tsub\tax,ax\n"); 
	fprintf(asmfile,"\tpush\tax\n"); 
	fprintf(asmfile,"; set segment registers:\n"); 
	fprintf(asmfile,"\tmov\tax,@data\n"); 
	fprintf(asmfile,"\tmov\tds,ax\n"); 
} 
/*数据类型的大小*/ 
int TypeSize[]={2, //integer 
				4, //real 
				2  //boolean,用两个字节长度是为了方便进栈出栈 
				}; 
static char * TypePtr[]={"word","dword","word"}; 
static char * TypeReg[]={"ax","eax","ax"}; 
 
/*计算参数在堆栈中的偏移值,由于参数传递从左到右,故使用递归方式来计算。参数 
	为参数的节点,返回值为该节点的偏移值*/ 
int computeParamOffset(TreeNode * param) 
{   
	if ( ! param->sibling ){ 
		param->offset = 4; 
		return 4; 
	} 
	if( param->sibling->attr.paramkind == ByRefer )//传地址 
		param->offset = computeParamOffset(param->sibling) + 2;	 
	else param->offset = computeParamOffset(param->sibling) + TypeSize[param->sibling->type]; 
	return param ->offset; 
} 
 
/*其它函数的初始化,完成局部变量和参数在堆栈中 
	的偏移值的计算和栈顶指针的改变,参数为函数根节点*/ 
void initSubPro(TreeNode * t) 
{ 
	int off = 0; 
	TreeNode * tree = t->child[0]; 
	if(tree) computeParamOffset(tree); 
	tree = t->child[1];	 
	while(tree){		//局部变量 
		switch(tree->type){ 
			case Integer: 
			case Real	: 
			case Boolean: 
				off -= TypeSize[tree->type]; 
				break; 
			case Array  : 
				off -= TypeSize[tree->attr.arrayattr->type]* (tree->attr.arrayattr->count); 
				break; 
		} 
		tree->offset = off; 
		tree = tree->sibling; 
	} 
	fprintf(asmfile,"%s\tPROC\tNEAR\n",t->name); 
	if(t->type <= Boolean ) { 
		off -= TypeSize[t->type];//该区域用于存放返回值 
		fprintf(asmfile,"; @result stores the return value\n"); 
		fprintf(asmfile,"\t@result = %d\n",off); 
	} 
	t->offset = off;		//栈顶的减少值 
	tree = t->child[0]; 
	if(tree) fprintf(asmfile,"; The offset of parameters is:\n"); 
	while(tree) { 
		modifyName(tree->name); 
		fprintf(asmfile,"\t%s$ = %d\n",tree->name,tree->offset); 
		strcat(tree->name,"$[bp]"); 
		tree = tree->sibling; 
	} 
	tree = t->child[1]; 
	if(tree) fprintf(asmfile,"; The offset of local Variables is:\n"); 
	while(tree) { 
		modifyName(tree->name);	 
		fprintf(asmfile,"\t%s$ = %d\n",tree->name,tree->offset);				 
		strcat(tree->name,"$[bp]");		//现在所有声明的变量的名字都表示地址 
		tree = tree->sibling; 
	} 
	if (off<0 || t->child[0]){				//设置bp,sp,申请局部变量区域 
		fprintf(asmfile,"\tpush\tbp\n"); 
		fprintf(asmfile,"\tmov\tbp,sp\n"); 
		if(off<0) fprintf(asmfile,"\tsub\tsp,%d\n",-off); 
	} 
} 
 
/*保存寄存器*/ 
void saveReg(void) 
{	int i; 
	SavedRegidx * temp; 
	if(regidx==0) return; 
	for(i=0;ivalue = regidx; 
	temp->next = savedregidx; 
	savedregidx = temp; 
	regidx = 0; 
} 
/*恢复寄存器*/ 
void resumeReg(void) 
{	int i; 
	SavedRegidx * temp; 
	if(!savedregidx) return; 
	for(i = savedregidx->value - 1 ; i>=0 ; i--) 
		fprintf(asmfile,"\tpop\t%s\n",regint[i]); 
	regidx = savedregidx->value; 
	temp = savedregidx->next; 
	free(savedregidx); 
	savedregidx = temp; 
} 
 
 
/*生成计算数组下标的代码,返回表示数组下标的字符串(可能为数字或[si]) 
	参数为ArrayK的节点*/ 
char * genArrayIndex(TreeNode * t) 
{ 
	int index=0; 
	static char result[16]; 
	if(t->child[0]->kind.exp==NumK){ 
		index = (t->child[0]->attr.intval - t->attr.arrayattr->low) * TypeSize[t->type]; 
		sprintf(result,"+%d",index); 
		return result; 
	} 
	saveReg(); 
	genCode(t->child[0]); 
	fprintf(asmfile,"\tmov\tsi,ax\n"); 
	resumeReg(); 
	fprintf(asmfile,"\tshl\tsi,%d\n",TypeSize[t->type]/2); 
	sprintf(result,"[si-(%d)]",t->attr.arrayattr->low * TypeSize[t->type]); 
	return result; 
} 
/*生成函数调用的代码,参数为一个CallK节点*/ 
void genCallK(TreeNode * t) 
{ 
	TreeNode * realp = t->child[0];  //指向实参 
	TreeNode * formp = t->child[2]->child[0];//指向形参 
	while(realp){ 
		switch(realp->kind.exp){ 
			case IdK: 
				if(formp->attr.paramkind==ByRefer){// 传地址 
					if(realp->child[2]->attr.paramkind == ByRefer) 
						fprintf(asmfile,"\tpush\t%s\n",realp->child[2]->name); 
					else{ 
						fprintf(asmfile,"\tlea\tsi,%s\n",realp->child[2]->name);//realp->child[2]为Id的声明 
						fprintf(asmfile,"\tpush\tsi\n"); 
					} 
				}else {			//传值 
					if(realp->child[2]->attr.paramkind==ByRefer){ // 
						fprintf(asmfile,"\tmov\tsi,word ptr %s\n",realp->child[2]->name); 
						fprintf(asmfile,"\tpush\t%s ptr [si]\n",TypePtr[realp->type]); 
					}else fprintf(asmfile,"\tpush\t%s ptr %s\n", 
								TypePtr[realp->type],realp->child[2]->name); 
				} 
				break; 
			case ArrayK: 
				if(formp->attr.paramkind==ByRefer){// 传地址 
					fprintf(asmfile,"\tlea\tsi,%s%s\n", 
						realp->child[2]->name,genArrayIndex(realp));//realp->child[2]为Id的声明 
					fprintf(asmfile,"\tpush\tsi\n"); 
				}else 			//传值 
					fprintf(asmfile,"\tpush\t%s ptr %s%s\n",TypePtr[realp->type], 
								realp->child[2]->name,genArrayIndex(realp)); 
				break; 
			case NumK: 
			case BoolK: 
				fprintf(asmfile,"\tmov\t%s,%d\n",TypeReg[realp->type],realp->attr.intval); 
				fprintf(asmfile,"\tpush\t%s\n",TypeReg[realp->type]); 
				break; 
			case RealNumK: 
				fprintf(asmfile,"\tmov\teax,%f\n",realp->attr.realval); 
				fprintf(asmfile,"\tpush\teax\n"); 
				break; 
			default: 
				genCode(realp); 
				fprintf(asmfile,"\tpush\t%s\n",TypeReg[realp->type]); 
				break; 
		} 
		realp = realp->sibling; 
		formp = formp->sibling; 
	} 
	fprintf(asmfile,"\tcall\t%s\n",t->child[2]->name); 
} 
 
/*生成赋值语句的代码参数为一个AssignK节点*/ 
void genAssignK(TreeNode * t) 
{ 
	TreeNode * tree; 
	if(t->child[0]->type == Real || t->child[1]->type ==Real){ 
		//to do 
		return; 
	} 
	tree = t->child[1]; 
	switch(tree->kind.exp){ 
		case NumK: 
		case BoolK: 
			if(t->kind.exp == ReturnK){ 
				fprintf(asmfile,"\tmov\tword ptr @result[bp],%d\n",tree->attr.intval); 
				return; 
			} 
			if(t->child[0]->kind.exp == ArrayK) 
				fprintf(asmfile,"\tmov\tword ptr %s%s,%d\n",t->child[0]->child[2]->name, 
						genArrayIndex(t->child[0]),tree->attr.intval); 
			else{ 
				if(t->child[0]->child[2]->attr.paramkind == ByRefer){ 
					fprintf(asmfile,"\tmov\tdi,word ptr %s\n",t->child[0]->child[2]->name); 
					fprintf(asmfile,"\tmov\tword ptr [di],%d\n" , tree->attr.intval); 
				}else 
					fprintf(asmfile,"\tmov\tword ptr %s,%d\n",t->child[0]->child[2]->name,tree->attr.intval); 
			} 
			break; 
		default: 
			genCode(tree); 
			if(t->kind.exp == ReturnK){ 
				fprintf(asmfile,"\tmov\tword ptr @result[bp],ax\n"); 
				return; 
			} 
			regidx++; 
			if(t->child[0]->kind.exp == ArrayK) 
				fprintf(asmfile,"\tmov\t%s ptr %s%s,ax\n",TypePtr[tree->type],t->child[0]->child[2]->name, 
						genArrayIndex(t->child[0])); 
			else{ 
				if(t->child[0]->child[2]->attr.paramkind == ByRefer){ 
					fprintf(asmfile,"\tmov\tdi,word ptr %s\n",t->child[0]->child[2]->name); 
					fprintf(asmfile,"\tmov\t%s ptr [di],ax\n" ,TypePtr[tree->type]); 
				}else 
					fprintf(asmfile,"\tmov\t%s ptr %s,ax\n",TypePtr[tree->type], 
						t->child[0]->child[2]->name); 
			} 
			regidx--; 
			break; 
	} 
} 
 
/*生成And和Or操作的代码,参数为该操作的节点*/ 
void genLogop(TreeNode * t) 
{ 
	int flag = FALSE; 
	if(t->attr.op == AND){ 
		if(t->ltrue) t->child[1]->ltrue = t->ltrue; 
		if(t->lfalse)  
			t->child[0]->lfalse = t->child[1]->lfalse =  t->lfalse; 
		else {									//实现短路跳转操作 
			t->child[0]->lfalse = t->lfalse = newLabel(); 
			flag = TRUE; 
		} 
	}else{						//t->attr.op == OR 
		if(t->lfalse) 
			t->child[1]->lfalse = t->lfalse; 
		if(t->ltrue) 
			t->child[0]->ltrue = t->child[1]->ltrue = t->ltrue; 
		else{									//实现短路跳转操作 
			t->child[0]->ltrue = t->ltrue = newLabel(); 
			flag = TRUE; 
		} 
	} 
	genCode(t->child[0]); 
	genCode(t->child[1]); 
	if(flag){ 
		if(t->attr.op == AND) fprintf(asmfile,"\t%s:\n",t->lfalse); 
		else fprintf(asmfile,"\t%s:\n",t->ltrue); 
	} 
 
} 
 
 
/*生成关系运算操作(case EQ: case NE:case LT: case LE: case GT: case GE: ) 
	的代码,参数为该操作节点*/ 
void genRelop(TreeNode * t) 
{ 
	TreeNode * tree; 
	char childname[2][40]; 
	int	MemUsed = FALSE; 
	int i; 
	if(t->child[0]->type == Real || t->child[1]->type ==Real){ 
		//to do 
		return; 
	} 
	for(i = 0; i<=1; i++){ 
		tree = t->child[i]; 
		switch(tree->kind.exp){ 
			case IdK: 
				if(tree->child[2]->attr.paramkind == ByRefer){ 
					if(!MemUsed){ 
						fprintf(asmfile,"\tmov\tdi,word ptr %s\n",tree->child[2]->name); 
						strcpy(childname[i],"[di]"); 
						MemUsed = TRUE;						 
					}else { 
						fprintf(asmfile,"\tmov\tsi,word ptr %s\n",tree->child[2]->name); 
						fprintf(asmfile,"\tmov\tax,[si]\n"); 
						strcpy(childname[i],"ax"); 
					} 
				}else{ 
					if(!MemUsed){ 
						sprintf(childname[i],"word ptr %s",tree->child[2]->name); 
						MemUsed  = TRUE; 
					}else { 
						fprintf(asmfile,"\tmov\tax,word ptr %s\n",tree->child[2]->name); 
						strcpy(childname[i],"ax"); 
					}					 
				} 
				break; 
			case ArrayK: 
				if(!MemUsed){ 
					if(i==0 && t->child[1]->kind.exp == ArrayK){ 
						fprintf(asmfile,"\tmov\tdi,word ptr %s%s\n",tree->child[2]->name,genArrayIndex(tree)); 
						strcpy(childname[0],"di"); 
					}else{ 
						sprintf(childname[i],"word ptr %s%s",tree->child[2]->name,genArrayIndex(tree)); 
						MemUsed = TRUE; 
					} 
				}else { 
					fprintf(asmfile,"\tmov\tax,word ptr %s%s\n",tree->child[2]->name,genArrayIndex(tree)); 
					strcpy(childname[i],"ax"); 
				} 
				break; 
			case NumK: 
			case BoolK: 
				sprintf(childname[i],"%d",tree->attr.intval); 
				break; 
			case CallK: 
				if(regidx){ 
					saveReg(); 
					genCode(tree); 
					fprintf(asmfile,"\tmov\t%s,ax\n",regint[regidx]); 
					resumeReg(); 
					strcpy(childname[i],regint[regidx]); 
				}else { 
					genCode(tree); 
					strcpy(childname[i],regint[regidx]); 
					regidx++; 
				} 
				break; 
			case OpK:case SignK: 
				genCode(tree); 
				strcpy(childname[i],regint[regidx]); 
				regidx++; 
				break; 
		} 
	} 
	fprintf(asmfile,"\tcmp\t%s,%s\n",childname[0],childname[1]); 
 
	regidx = 0; 
	switch(t->attr.op){ 
		case EQ: 
			if (t->ltrue)  fprintf(asmfile,"\tje\t%s\n",t->ltrue); 
			if (t->lfalse) fprintf(asmfile,"\tjne\t%s\n",t->lfalse); 
			break; 
		case NE: 
			if (t->ltrue)  fprintf(asmfile,"\tjne\t%s\n",t->ltrue); 
			if (t->lfalse) fprintf(asmfile,"\tje\t%s\n",t->lfalse); 
			break; 
		case LT: 
			if (t->ltrue)  fprintf(asmfile,"\tjl\t%s\n",t->ltrue); 
			if (t->lfalse) fprintf(asmfile,"\tjnl\t%s\n",t->lfalse); 
			break; 
		case LE: 
			if (t->ltrue)  fprintf(asmfile,"\tjle\t%s\n",t->ltrue); 
			if (t->lfalse) fprintf(asmfile,"\tjnle\t%s\n",t->lfalse); 
			break; 
		case GT: 
			if (t->ltrue)  fprintf(asmfile,"\tjg\t%s\n",t->ltrue); 
			if (t->lfalse) fprintf(asmfile,"\tjng\t%s\n",t->lfalse); 
			break;			 
		case GE: 
			if (t->ltrue)  fprintf(asmfile,"\tjge\t%s\n",t->ltrue); 
			if (t->lfalse) fprintf(asmfile,"\tjnge\t%s\n",t->lfalse); 
			break;			 
	} 
} 
 
/*生成整数(not include 除法)运算操作的代码,参数为该操作的节点*/ 
void genNumop(TreeNode * t) 
{ 
	int opIndex = t->attr.op - PLUS; 
	int currentRegidx,flag; 
	TreeNode * tree; 
	char * numop[6] = {"add","sub","imul","idiv","idiv","idiv"}; 
	char right[40]; 
	if( t->type == Real ){ 
		//to do 
		return; 
	} 
	tree = t->child[0]; 
	if (tree->kind.exp == CallK){ 
		saveReg(); 
		genCode(tree); 
		if (regint>0)	fprintf(asmfile,"\tmov\t%s,ax\n",regint[regidx]); 
		resumeReg(); 
	}else genCode(tree); 
 
	tree = t->child[1]; 
	switch (tree->kind.exp) 
		{  
		case NumK: 
			if (opIndex <= 1) sprintf(right,"%d",tree->attr.intval); 
			else{ 
				fprintf(asmfile,"\tmov\t%s,%d\n",regint[regidx+1],tree->attr.intval); 
				strcpy(right,regint[regidx+1]); 
			} 
			break; 
        case IdK: 
			if(tree->child[2]->attr.paramkind == ByRefer){ 
				fprintf(asmfile,"\tmov\tsi,word ptr %s\n",tree->child[2]->name); 
				strcpy(right,"word ptr [si]"); 
			}else  
				sprintf(right,"word ptr %s",tree->child[2]->name);			 
			break; 
		case ArrayK: 
			regidx++; 
			sprintf(right,"word ptr %s%s",tree->child[2]->name,genArrayIndex(tree)); 
			regidx--; 
			break; 
		default: 
			flag = (tree->kind.exp == CallK); 
			currentRegidx = regidx; 
			regidx++; 
			if (flag) saveReg(); 
			genCode(tree); 
			if (flag){ 
				fprintf(asmfile,"\tmov\t%s,ax\n",regint[currentRegidx + 1]); 
				resumeReg(); 
			} 
			regidx--; 
			strcpy(right,regint[regidx+1]); 
			break; 
		} 
	if (opIndex <= 1)  
		fprintf(asmfile,"\t%s\t%s,%s\n",numop[opIndex],regint[regidx],right); 
	else{ 
		if(regidx>0) {				//保存ax 
			fprintf(asmfile,"\tpush\tax\n"); 
			fprintf(asmfile,"\tmov\tax,%s\n",regint[regidx]); 
		} 
		if(opIndex >= 4) fprintf(asmfile,"\tmov\tdx,0\n"); //div mod 
		fprintf(asmfile,"\t%s\t%s\n",numop[opIndex],right); 
		if (regidx == 0){ 
			if(t->attr.op == MOD) 
				fprintf(asmfile,"\tmov\tax,dx\n");//余数在dx中 
		}else {		//把结果放回原来的寄存器 
			if(t->attr.op == MOD) 
				fprintf(asmfile,"\tmov\t%s,dx\n",regint[regidx]);//余数在dx中 
			else 
				fprintf(asmfile,"\tmov\t%s,ax\n",regint[regidx]);//商或积在ax中 
		} 
		if(regidx>0) fprintf(asmfile,"\tpop\tax\n");  //恢复ax 
	} 
} 
 
 
/* 生成汇编代码,输出到目标文件*/ 
void genCode(TreeNode * t) 
{ 
	int isAssignStmt = FALSE; 
	if (!t) return; 
	switch (t->nodekind) 
	{  
    case Pro: 
		if (t->kind.pro ==MainP){  
			fprintf(asmfile,";generated by subpas Compiler\n"); 
			fprintf(asmfile,"TITLE\t%s\n",t->name); 
			if(RealUsed) fprintf(asmfile,"\t.386\n"); 
			else fprintf(asmfile,".286\n"); 
			fprintf(asmfile,".model\tsmall\n\n"); 
			fprintf(asmfile,".STACK\t2048\n\n"); 
			genDataSegment(t->child[1]); 
			fprintf(asmfile,".CODE\n\n"); 
			genCode(t->sibling); 
			if (ReadlnUsed) genReadln(); 
			if (WritelnUsed) genWriteln(); 
			fprintf(asmfile,";////////////////////////////////////////////////////////\n\n"); 
			initMainPro(); 
			fprintf(asmfile,"; main instructions\n"); 
			genCode(t->child[2]); 
			fprintf(asmfile,"\tret\n"); 
			fprintf(asmfile,"_MAIN\tENDP\n\n"); 
			fprintf(asmfile,"\tEND\t_MAIN\n"); 
		} 
		else{		//SubP 
			modifyName(t->name); 
			fprintf(asmfile,";////////////////////////////////////////////////////////\n\n"); 
			initSubPro(t); 
			genCode(t->child[2]); 
			if(t->type <= Boolean) 
				fprintf(asmfile,"\tmov\t%s,%s ptr @result[bp]\n",	//将返回值放到ax或eax中 
					TypeReg[t->type],TypePtr[t->type]); 
			if(t->offset<0 || t->child[0]){	//还原bp,sp 
				fprintf(asmfile,"\tmov\tsp,bp\n"); 
				fprintf(asmfile,"\tpop\tbp\n"); 
			} 
			if(t->child[0]){	//弹出参数偏移 
				int size = t->child[0]->offset - 4; 
				if( t->child[0]->attr.paramkind == ByRefer ) size += 2;	 
				else size += TypeSize[t->child[0]->type]; 
				fprintf(asmfile,"\tret\t%d\n",size); 
			}else fprintf(asmfile,"\tret\n"); 
 
			fprintf(asmfile,"%s\tENDP\n\n",t->name); 
			genCode(t->sibling); 
		} 
		break; 
    case Stmt: 
		switch (t->kind.stmt){ 
			case IfK: 
				t->lfalse = newLabel(); 
				t->ltrue = newLabel(); 
				t->child[0]->lfalse = t->lfalse; 
				genCode( t->child[0]); 
				genCode( t->child[1]); 
				fprintf(asmfile,"\tjmp\t%s\n",t->ltrue); 
				fprintf(asmfile,"\t%s:\n",t->lfalse); 
				genCode( t->child[2]); 
				fprintf(asmfile,"\t%s:\n",t->ltrue); 
				break; 
			case WhileK: 
				t->ltrue = newLabel(); 
				t->lfalse = newLabel(); 
				t->child[0]->lfalse = t->lfalse; 
				fprintf(asmfile,"\t%s:\n",t->ltrue); 
				genCode(t->child[0]); 
				genCode(t->child[1]); 
				fprintf(asmfile,"\tjmp\t%s\n",t->ltrue); 
				fprintf(asmfile,"\t%s:\n",t->lfalse); 
				break; 
			case CallK: 
				genCallK(t); 
				break; 
			case AssignK: 
			case ReturnK: 
				genAssignK(t); 
				break; 
		} 
		if(t->sibling) genCode(t->sibling); 
		break; 
	case Exp: 
		if(t->type == Real) return; //to do 
		switch (t->kind.exp) 
		{  
		case OpK: 
			switch(t->attr.op) { 
			case PLUS: case MINUS:case TIMES:case OVER: case DIV: case MOD: 
				genNumop(t); 
				break; 
			default:	//逻辑运算  AND OR EQ NE LT LE GT GE NOT等 
				if (!t->ltrue && !t->lfalse){   //赋值语句的右边语句,例如:flag := not(a>b and c>d); 
					isAssignStmt = TRUE; 
					t->lfalse = newLabel(); 
				} 
				switch(t->attr.op) { 
					case EQ: case NE:case LT: case LE: case GT: case GE:  
						genRelop(t); 
						break; 
					case AND: case OR: 
						genLogop(t); 
						break; 
					case NOT: 
						if(t->ltrue) t->child[0]->lfalse = t->ltrue; 
						if(t->lfalse)t->child[0]->ltrue  = t->lfalse; 
						genCode(t->child[0]); 
						break; 
				} 
				if(isAssignStmt){ 
					fprintf(asmfile,"\tmov\tax,1\n"); 
					t->ltrue = newLabel(); 
					fprintf(asmfile,"\tjmp\t%s\n",t->ltrue); 
					fprintf(asmfile,"\t%s:\n",t->lfalse); 
					fprintf(asmfile,"\tmov\tax,0\n"); 
					fprintf(asmfile,"\t%s:\n",t->ltrue); 
				} 
			} 
			break; 
        case IdK: 
			if(t->ltrue || t->lfalse){  //若为布尔型变量则判断是否跳转 
				if(t->child[2]->attr.paramkind == ByRefer){ 
					fprintf(asmfile,"\tmov\tsi,word ptr %s\n",t->child[2]->name); 
					fprintf(asmfile,"\tcmp\tword ptr [si],1\n"); 
					if(t->ltrue)						 
						fprintf(asmfile,"\tje\t%s\n",t->ltrue); 
					if(t->lfalse) 
						fprintf(asmfile,"\tjne\t%s\n",t->lfalse); 
				}else{ 
					fprintf(asmfile,"\tcmp\tword ptr %s,1\n",t->child[2]->name); 
					if(t->ltrue)						 
						fprintf(asmfile,"\tje\t%s\n",t->ltrue); 
					if(t->lfalse) 
						fprintf(asmfile,"\tjne\t%s\n",t->lfalse); 
				} 
				break; 
			} 
			if(t->child[2]->attr.paramkind == ByRefer){ //送到相应寄存器 
				fprintf(asmfile,"\tmov\tsi,word ptr %s\n",t->child[2]->name); 
				fprintf(asmfile,"\tmov\t%s,word ptr [si]\n",regint[regidx]); 
			}else fprintf(asmfile,"\tmov\t%s,%s ptr %s\n", 
						regint[regidx],TypePtr[t->type],t->child[2]->name); 
			break; 
		case BoolK: 
			if(t->ltrue || t->lfalse){ 
				if(t->ltrue && t->attr.intval == 1)					 
					fprintf(asmfile,"\tjmp\t%s\n",t->ltrue); 
				if(t->lfalse && t->attr.intval == 0) 
					fprintf(asmfile,"\tjmp\t%s\n",t->lfalse); 
			}else 
				fprintf(asmfile,"\tmov\t%s,%d\n",regint[regidx],t->attr.intval); 
			break; 
		case NumK: 
			fprintf(asmfile,"\tmov\t%s,%d\n",regint[regidx],t->attr.intval); 
			break; 
		case ArrayK: 
			if(t->ltrue || t->lfalse){  //若为布尔型变量则判断是否跳转 
				fprintf(asmfile,"\tcmp\tword ptr %s%s,1\n",t->child[2]->name,genArrayIndex(t)); 
				if(t->ltrue)						 
					fprintf(asmfile,"\tje\t%s\n",t->ltrue); 
				if(t->lfalse) 
					fprintf(asmfile,"\tjne\t%s\n",t->lfalse); 
				break; 
			} 
			fprintf(asmfile,"\tmov\t%s,%s ptr %s%s\n",regint[regidx], 
						TypePtr[t->type],t->child[2]->name,genArrayIndex(t)); 
			break; 
		case SignK: 
			switch(t->child[0]->kind.exp){ 
				case CallK: 
					saveReg(); 
					genCode(t->child[0]); 
					fprintf(asmfile,"\tmov\t%s,ax\n",regint[regidx]); 
					fprintf(asmfile,"\tneg\t%s\n",regint[regidx]); 
					resumeReg(); 
					break; 
				default:  
					genCode(t->child[0]); 
					fprintf(asmfile,"\tneg\t%s\n",regint[regidx]); 
					break; 
			} 
		} 
		break; 
	} 
}