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

📄 ex86asm.cpp

📁 一个面向对像语言的编译器
💻 CPP
字号:
// Ex86asm.cpp: implementation of the Ex86asm class.
//
//////////////////////////////////////////////////////////////////////

#include "Ex86asm.h"
#include "stdarg.h"
#include "scope.h"
#include "type.h"
#include "decllist.h"
#include "errors.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

void PraseString(const char * s,char *t)
{
     int i,j,len;
	 len=strlen(s);
	 for(i=0,j=0;i<len-1;i++,j++)
	 {
		if(s[i]!='\\')
		{
			t[j]=s[i];
		}
		else
		{

			if(s[i+1]=='t')
			{
				t[j]='\t';
				i++;
			}
			else if(s[i+1]=='\\')
			{
				t[j]='\\';
				i++;
			}
			else if(s[i+1]=='n')
			{
				t[j]='\r';
				t[j+1]='\n';
				j++;
				i++;
			}
			else if(s[i+1]=='r')
			{
				t[j]='\r';
				t[j+1]='\n';
				j++;
				i++;
			}
			else if(s[i+1]=='"')
			{
				t[j]='"';
				i++;
			}
			else if(s[i+1]<='9'	&& s[i+1]>='0')
			{
				if(s[i+2]<='9'	&& s[i+2]>='0')
				{
				    if(s[i+3]<='9'	&& s[i+3]>='0')
					{
						char buf[4]={s[i+1],s[i+2],s[i+3],'\0'};
						t[j]=(char)atoi(buf);
						i+=3;
					}
					else
					{
						char buf1[3]={s[i+1],s[i+2],'\0'};
						t[j]=(char)atoi(buf1);
						i+=2;
					}
				}
				else
				{
					t[j]=s[i+1]-'0';
					i++;
				}

				if(t[j]=='\0')
					j--;
			}
			else
			{
			   j--;
			}
		}

	 }
	 t[j]='\0';
}



Ex86asm::Ex86asm()
{
	nStringCount=0;

}

Ex86asm::~Ex86asm()
{

}
void Ex86asm::EmitPreamble()
{
	FILE * fp;
	char buf[1024];
	fp=fopen("lib32.asm","r");
	if(fp==NULL)
	{
		printf("Fail to find the standard libray of PC ASM");
		exit(0);
	}
	while(!feof(fp))
	{
		fgets(buf,1024,fp);
		printf("%s",buf);
	}

}
void Ex86asm::Emit(const char *fmt, ...)
{
  va_list args;
  char buf[1024];
  
  va_start(args, fmt);
  vsprintf(buf, fmt, args);
  va_end(args);
  if (buf[strlen(buf) - 1] != ':') printf("\t"); // don't tab in labels
  if (buf[0] != ';') printf("  ");   // outdent comments a little
  printf("%s", buf);
  if (buf[strlen(buf)-1] != '\n') printf("\n"); // end with a newline
}

void Ex86asm::EmitACall(Declaration *dst, Declaration *fn, int bytes)
{
	StoreVarInEAX(fn);
	EmitOp1("CALL","EAX","Call the function");
	if(dst!=NULL)
		StoreEAXInVar(dst);
}

void Ex86asm::EmitLCall(Declaration *dst, const char *label, int bytes)
{ 
	EmitOp1("CALL",label,"Call the function");
	if(dst!=NULL)
		StoreEAXInVar(dst);
}

void Ex86asm::EmitArg(Declaration *arg)
{ 
	StoreVarInEAX(arg);
	EmitOp1("PUSH","EAX","Push this parameter to stack");
}

void Ex86asm::EmitBeginFunction(Declaration * fun,int frameSize)
{
  Assert(frameSize >= 0);
  char buf[32];
  Emit(";--------------------------------------------");
  Emit("; The start of function %s",fun->GetFunctionLabel());
  Emit(";--------------------------------------------");
  printf("\n.code\n%s proc \n",fun->Getx86FunctionLabel());
  EmitOp1("PUSH","EBP","Save old EBP in stack");
  EmitOp2("MOV","EBP","ESP","EBP <==== current ESP");
  sprintf(buf,"%d",frameSize);
  EmitOp2("SUB","ESP",buf,"Make room for local and temp variables");
  
}

void Ex86asm::EmitEndFunction(Declaration * fun)
{ 
	char buf[32];
	EmitOp2("MOV","ESP","EBP","Restroe ESP");
	EmitOp1("POP","EBP","Restore EBP");
	if(fun->IsGlobal()||!strcmp(fun->GetName(),"New"))
		sprintf(buf,"%d",fun->GetType()->GetFnFormals()->NumElements()*4);
	else
		sprintf(buf,"%d",fun->GetType()->GetFnFormals()->NumElements()*4+4);
	EmitOp1("RET",buf,"Return from function and clean the stack that hold by parameters");
	printf("%s ENDP\n",fun->Getx86FunctionLabel() );
}


void Ex86asm::StoreVarInEAX(Declaration *decl)
{
	Scope * s;
	s=decl->GetScope();
	Assert(!s->IsClassScope());
	char buf[128];
	if(s->IsGlobalScope())
	{
		sprintf(buf,"_%s",decl->GetName());
		EmitOp2("MOV","EAX",buf,"EAX <==== Global variable",decl->GetName());
	}
	else 
	{
		int off=decl->GetOffset();
		if(off>=0)
			sprintf(buf,"[EBP+%d]",off);
		else
			sprintf(buf,"[EBP-%d]",-off);
		EmitOp2("MOV","EAX",buf,"EAX <==== Local variable",decl->GetName());
	}

}

void Ex86asm::StoreVarInEDX(Declaration *decl)
{
	Scope * s;
	s=decl->GetScope();
	Assert(!s->IsClassScope());
	char buf[128];
	if(s->IsGlobalScope())
	{
		sprintf(buf,"_%s",decl->GetName());
		EmitOp2("MOV","EDX",buf,"EDX <==== Global variable",decl->GetName());
	}
	else 
	{
		int off=decl->GetOffset();
		if(off>=0)
			sprintf(buf,"[EBP+%d]",off);
		else
			sprintf(buf,"[EBP-%d]",-off);
		EmitOp2("MOV","EDX",buf,"EDX <==== Local variable",decl->GetName());
	}

}

void Ex86asm::StoreEAXInVar(Declaration *decl)
{
	Scope * s;
	s=decl->GetScope();
	Assert(!s->IsClassScope());
	char buf[32];
	if(s->IsGlobalScope())
	{
		sprintf(buf,"_%s",decl->GetName());
		EmitOp2("MOV",buf,"EAX","EAX ====> Global variable",decl->GetName());
	}
	else 
	{
		int off=decl->GetOffset();
		if(off>=0)
			sprintf(buf,"[EBP+%d]",off);
		else
			sprintf(buf,"[EBP-%d]",-off);
		EmitOp2("MOV",buf,"EAX","EAX ====> Local variable",decl->GetName());
	}

}


void Ex86asm::StoreEDXInVar(Declaration *decl)
{
	Scope * s;
	s=decl->GetScope();
	Assert(!s->IsClassScope());
	char buf[32];
	if(s->IsGlobalScope())
	{
		sprintf(buf,"_%s",decl->GetName());
		EmitOp2("MOV",buf,"EDX","EDX ====> Global variable",decl->GetName());
	}
	else 
	{
		int off=decl->GetOffset();
		if(off>=0)
			sprintf(buf,"[EBP+%d]",off);
		else
			sprintf(buf,"[EBP-%d]",-off);
		EmitOp2("MOV",buf,"EDX","EDX ====> Local variable",decl->GetName());
	}
}

void Ex86asm::EmitBinaryOp(Tac::OpCode code, Declaration *dst, 
				 Declaration *op1, Declaration *op2)
{
	StoreVarInEAX(op1);
	StoreVarInEDX(op2);
//Add, Sub, Mul, Div, Mod, Eq, Less, And, Or
	switch(code)
	{
		case Tac::Add:
			EmitOp2("ADD","EAX","EDX","Add them:)");
		break;

		case Tac::Sub:
			EmitOp2("SUB","EAX","EDX","Sub them:)");
		break;

		case Tac::Mul:
			EmitOp2("MOV","ECX","EDX","Move the multiplier to ECX");
			EmitOp2("SUB","EDX","EDX","Clean EDX");
			EmitOp1("IMUL","ECX","Multiply EAX by ECX,and the result stored in EDX:EAX");
		break;

		case Tac::Div:
			EmitOp2("MOV","ECX","EDX","Move the divider to ECX");
			EmitOp2("SUB","EDX","EDX","Clean EDX");
			EmitOp1("IDIV","ECX","Divide EDX:EAX by ECX,and the result stored in EAX");
		break;

		case Tac::Mod:
			EmitOp2("MOV","ECX","EDX","Move the devider to ECX");
			EmitOp2("SUB","EDX","EDX","Clean EDX");
			EmitOp1("IDIV","ECX","Divide EDX:EAX by ECX");
			EmitOp2("MOV","EAX","EDX","Move the arithmetical compliment in EDX to EAX");
		break;

		case Tac::Eq:
			EmitOp2("MOV","EBX","EAX","Move OP1 to EBX");
			EmitOp2("SUB","EAX","EAX","Clean EAX");
			EmitOp2("SUB","EBX","EDX","Compare the OP1 in EBX and the OP2 in EDX");
			EmitOp0("LAHF","Load flag to AH");
			EmitOp2("AND","AH","40H","And AH with 40H");
			EmitOp2("SHR","EAX","14","Shift the result to the lowest bit of EAX");

		break;

		case Tac::Less:
			EmitOp2("SUB","EAX","EDX","Compare the OP1 in EAX and the OP2 in EDX, if OP1 < OP2 then the highest bit of result in EAX should be 1,or else be 0");
			EmitOp2("AND","EAX","80000000H","And ah with 80000000H");
			EmitOp2("ROL","EAX","1","Shift the result bit to the lowest bit of EAX");
		break;

		case Tac::And:
			EmitOp2("AND","EAX","EDX","And them :)");
		break;

		case Tac::Or:
			EmitOp2("OR","EAX","EDX","Or them :)");
		break;
	}
	StoreEAXInVar(dst);
}

void Ex86asm::EmitGoto(const char *label)
{
	char buf[256];
	sprintf(buf,"_@@%s",label);
	EmitOp1("JMP",buf,"Uncondition jump");
}

void Ex86asm::EmitIfZ(Declaration *test, const char *label)
{ 
  char buf[256];
  sprintf(buf,"_@@%s",label);
  StoreVarInEAX(test);
  EmitOp2("CMP","EAX","0","Test the condition");
  EmitOp1("JZ",buf,"Jump when the condition is zero");
}

void Ex86asm::EmitLabel(const char *label)
{ 
  Emit("_@@%s:", label);
}

void Ex86asm::EmitLoad(Declaration *dst, Declaration *reference, int offset)
{
	StoreVarInEAX(reference);
	if(offset!=0)
	{
		char buf[32];
		sprintf(buf,"%d",offset);
		EmitOp2("ADD","EAX",buf,"Add the offset");
	}
	EmitOp2("MOV","EDX","[EAX]","Load the valiable to EDX");
	StoreEDXInVar(dst);

}

void Ex86asm::EmitLoadConstant(Declaration *dst, int val)
{
	char buf[32];
	sprintf(buf,"%d",val);
	EmitOp2("MOV","EAX",buf,"Load constant to EAX");
	StoreEAXInVar(dst);
}

void Ex86asm::EmitLoadStringConstant(Declaration *dst, const char *str)
{
	static int strNum = 1;
  char label[32];
  char buf[64];
  char * sptr;

  
  
	if(!strcmp(str,err_arr_out_of_bounds)||
		!strcmp(str,"\"Decaf runtime error: Array subscript out of bounds\n\""))
	{
		EmitOp2("MOV","EAX","offset _@strRTErrWrongIndex");
		StoreEAXInVar(dst);
	}
	else if(!strcmp(str,err_arr_neg_size)||
		!strcmp(str,"\"Decaf runtime error: Cannot create negative-sized array\n\""))
	{
		EmitOp2("MOV","EAX","offset _@strRTErrWrongSize");
		StoreEAXInVar(dst);
	}
	else
	{
		sprintf(label,"_@StringL@%d",nStringCount);
		nStringCount++;
		sptr=new char [strlen(str)+1];
		PraseString(str+1,sptr);
		Emit("; String constant for %s",str);
		printf("\n.data\n %s db ",label);
		int i,c=strlen(sptr);
		for(i=0;i<c;i++)
		{
		  if(i==0)
			  printf("%d",(int) sptr[i]);
		  else if(i%16==0)
				printf("\n\t\tdb %d",(int) sptr[i]);
		  else
			printf(",%d",(int) sptr[i]);
		}
		delete []sptr;
		printf(",0\n");
		printf("\n.code\n");
		sprintf(buf,"Offset %s",label);
		EmitOp2("MOV","EAX",buf,"Load the string constant to EAX");
		StoreEAXInVar(dst);
	}



}


void Ex86asm::EmitStore(Declaration *reference, Declaration *value, int offset)
{


	StoreVarInEDX(value);
	StoreVarInEAX(reference);

	if(offset!=0)
	{
		char buf[32];
		sprintf(buf,"%d",offset);
		EmitOp2("Add","EAX",buf);
	}
	EmitOp2("MOV","[EAX]","EDX","Store EDX back to memory");

}

void Ex86asm::EmitVTable(const char *label, DeclList *methods)
{
	int i,c=methods->NumElements();
	printf("\n.data\n");
	
	for(i=0;i<c;i++)
	{
		if(i==0)
			printf("_%s",label);
		Emit("\tdd offset %s",methods->Nth(i)->Getx86FunctionLabel());
	}
	if(c==0)
	{
		if(i==0)
			printf("_%s dd ?",label);
	}
		


	printf("\n.code\n");
}

void Ex86asm::EmitGVar(Declaration *decl)
{
	printf("\n.data\n");
	Emit("_%s dd ?",decl->GetName());
	printf("\n.code\n");
}


void Ex86asm::EmitCopy(Declaration *dst, Declaration *src)
{
	StoreVarInEAX(src);
	StoreEAXInVar(dst);
}
void Ex86asm::EmitReturn(Declaration *returnVal)
{
	if(returnVal!=NULL)
	{
		Emit(";Return value store in EAX");
		StoreVarInEAX(returnVal);
		
	}
}

void Ex86asm::EmitLoadLabel(Declaration *dst, const char *label)
{
	char buf[1024];
	sprintf(buf,"offset _%s", label);
	EmitOp2("MOV","EAX",buf,"Load label to EAX");
	StoreEAXInVar(dst);

}

⌨️ 快捷键说明

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