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

📄 code.cpp

📁 c语言做的pl0编译器
💻 CPP
字号:
// code.cpp: implementation of the code class.
//////////////////////////////////////////////////////////////////////
#include "code.h"

void Ccode::Gen(enum fct x,int y,int z)
{
	if (cx>CODE_SIZE) {
		printf("error:program too long");
		}
	if (cx<CODE_SIZE)
	{
		code[cx].f=x;
		code[cx].l=y;
		code[cx].a=z;
		cx++;
	}
}
int Ccode::base(int l)
{
	int b1;
	b1=b;
	while (l>0)
	{
		b1=s[b1];
		l--;
	}
	return b1;
}
//解析code中的p-code代码并执行
void Ccode::Interpret()
{
	int p,t;
	fct f;
	int l,a;
	t=0;                             //p-code机的数据堆栈区
	b=1;                             //p-code机的栈顶寄存器
	p=0;                             //p-code机的基址寄存器
	s[1]=0;s[2]=0;s[3]=0;            //数据内存中为SL,DL,RA三个单元均为0,标识为主程序
	do{
		f=code[p].f;l=code[p].l;a=code[p].a;//开始获取一行目标代码
		p++;                                //指令指针加一,指向下一条代码
		switch (f)
		{
		case lit:                           //如果是lit指令
			s[++t]=a;                       //把常量值放到运行栈栈顶
			break;
		case opr:                           //如果是opr指令
			switch (a)
			{
			case 0:                         //0号操作为从子过程返回操作
				t=b-1;                      //释放这段子过程占用的数据内存空间
				p=s[t+3];                   //把指令指针取到RA的值,指向的是返回地址
				b=s[t+2];                   //把数据段基址取到DL的值,指向调用前子过程的数据段基址
				break;
			case 1:                         //1号操作为栈顶数据取反
				s[t]=-s[t];
				break;
			case 2:	t--;                    //2号操作为栈顶两个数据加法
				s[t]=s[t]+s[t+1];
				break;
			case 3:	t--;                    //3号操作为栈顶两个数据减法
				s[t]=s[t]-s[t+1];
				break;
			case 4:	t--;                    //4号操作为栈顶两个数据乘法
				s[t]=s[t]*s[t+1];
				break;
			case 5:	t--;                    //5号操作为栈顶两个数据除法
				s[t]=s[t]/s[t+1];
				break;
			case 6:                         //6号操作为判奇偶
				s[t]=s[t]%2;
				break;
			case 8:	t--;                    //8号操作为栈顶两个数据判等
				s[t]=(s[t]==s[t+1]);
				break;
			case 9:	t--;                    //9号操作为栈顶两个数据判不等
				s[t]=(s[t]!=s[t+1]);
				break;
			case 10: t--;                   //10号操作为栈顶两个数据判小于
				s[t]=(s[t]<s[t+1]);
				break;
			case 11: t--;                   //11号操作为栈顶两个数据判大于等于
				s[t]=(s[t]>=s[t+1]);
				break;
			case 12: t--;                   //12号操作为栈顶两个数据判大于
				s[t]=(s[t]>s[t+1]);
				break;
			case 13: t--;                   //13号操作为栈顶两个数据判小于等于
				s[t]=(s[t]<=s[t+1]);
				break;
			case 14:                        //14号操作为输出栈顶值
				printf("%d\t",s[t]);
				break;
			case 15:                        //15号操作为输出换行
				printf("\n");
				break;
			case 16:                        //16号操作为接受键盘值输入到栈顶
				t++;
				printf("?");
				scanf("%d",&s[t]);
				break;
			}
			break;
		case lod:                           //如果是lod指令:将变量放到栈顶
			t++;                            //栈顶上移,开辟空间
			s[t]=s[base(l)+a];              //通过数据区层差l和偏移地址a找到变量的数据,存入栈顶
			break;
		case sto:                           //如果是sto指令
			s[base(l)+a]=s[t];              //把栈顶的值存入位置在数据区层差l偏移地址a的变量内存
			t--;                            //栈项下移,释放空间
			break;
		case cal:                           //如果是cal指令
			s[t+1]=base(l);                 //在栈顶压入静态链SL
			s[t+2]=b;                       //然后压入当前数据区基址,作为动态链DL
			s[t+3]=p;                       //最后压入当前的断点,作为返回地址RA
			b=t+1;                          //把当前数据区基址指向SL所在位置
			p=a;                            //从a所指位置开始继续执行指令,即实现了程序执行的跳转
			break;
		case intint:                        //如果是int指令
			t+=a;                           //栈顶上移a个空间,即开辟a个新的内存单元
			break;
		case jmp:                           //如果是jmp指令
			p=a;                            //把jmp指令操作数a的值作为下一次要执行的指令地址,实现无条件跳转
			break;
		case jpc:                           //如果是jpc指令
			if (s[t]==0)                    //判断栈顶值
				p=a;                        //如果是0就跳转,否则不跳转
			t--;                            //释放栈顶空间
			break;
		}
	}while (p!=0);
}
void Ccode::ListCode()
{
	for (int i=0;i<cx;i++)
	{
		printf("%d\t",i);
		switch (code[i].f)
		{
		case lit:printf("lit\t");break;
		case lod:printf("lod\t");break;
		case sto:printf("sto\t");break;
		case cal:printf("cal\t");break;
		case intint:printf("int\t");break;
		case jmp:printf("jmp\t");break;
		case jpc:printf("jpc\t");break;
		case opr:printf("opr\t");break;
		}
		printf("%d\t%d\n",code[i].l,code[i].a);
	}
}

⌨️ 快捷键说明

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