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;i value = 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; } }