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

📄 execute.cpp

📁 Win32 Console下C++实现的PL/0语言编译程序
💻 CPP
字号:
/*
FileName:		execute.cpp
Author:			LiWen
Create:			2005-12-22
Last Modified:	2005-12-24
Discription:	代码解释执行模块
*/
#include "compiler.h"
////////////////////////////////////////////////////////////////////////////////
//解释执行中间代码,并报告运行时错误
//本模块在处理递过程归调用问题上采用了逐层链接寻址方法:
//由于生成的PCODE代码中对变量的操作时所指明的层数差,仅仅是在定义中
//的层差,而调用过程中这种层数差可能会有所不同,如在递归调用里,当内
//层过程被两次调用之后,第二次被自身调用的过程其与主过程的层数差已经
//有所改变,而如果直接根据指令取址,将会访问到其上层,而不是main过程
//针对该问题,进行了如下思考
//在子过程调用时,CAL L A,其中L表示被调用过程与本过程的层数差,
//如果在过程调用时,将被调用过程的层数差入栈,并在计算基址时加上该层
//数差将很好的解决这个问题。即累计计算 与调用时的上层层数差 即可访问
//到指令中指定的定义时的层差中的变量
//测试程序请见recursion.txt,该程序定义了两个过程p,q互相调用,根据输
//入来选择是否继续递归,并打印出调用层数
//recursion1.txt是自递归
//
extern INSTRUCTION codelist[];			//代码表

int sp,ip,bx;					//堆栈指针,代码指针,当前函数基址
int stack[EXESTACKSIZ]={0};		//堆栈

/*=======================================================
函数:execute
参数:无
描述:供主函数调用,循环取指,并执行,执行模块接口
返回:正常0,Run Time Error返回TMNT
========================================================*/
int execute(){
	int tip;
	ip = bx = 0;
	do{
		tip = ip ++;
		PRT_RUN(codelist[tip].f,codelist[tip].l,codelist[tip].a);
	}while(ip>0);
	printf("\nProgram end normally!\n");
	return 0;
}

/*=======================================================
函数:pushtruy
参数:欲入栈数目
描述:入栈测试程序,防止堆栈溢出
返回:正常当前sp,否则TMNT
========================================================*/
int pushtry(int n){
	if(sp+n >= EXESTACKSIZ){
		printf("RunTime Error:运行堆栈溢出!\n");
		return TMNT;
	}
	return sp;
}
/*=======================================================
函数:getbx
参数:层数差,当前函数基址
描述:根据指令中要求的层数差,和当前基址,计算寻址层基址
返回:被寻址层基址
========================================================*/
int getbx(int l,int b){
	int bx = b;
	while(l>0){
		l+=stack[bx];		//加上每一层被调用时与上一层函数的层数差
		bx = stack[bx+1];	//置bx为上一层基址
		l--;
	}
	return bx;
}
/*=======================================================
函数:run
参数:PCODE指令的三元素
描述:执行一条PCODE指令
返回:正常0,否则TMNT
========================================================*/
int run(enum instruction f, int l, int a){
	int t;
	switch(f){
	case LIT://取常数
		stack[sp++] = a;
		break;
	case LOD://取变量
		t = getbx(l,bx)+a;
		stack[sp++] = stack[t];
		break;
	case STO://存储变量
		t = getbx(l,bx)+a;
		stack[t] = stack[--sp];
		break;
	case CAL://过程调用
		stack[sp] = l;		//!!!!!!层数差
		stack[sp+1] = bx;
		stack[sp+2] = ip;
		bx = sp;
		ip = a;
		break;
	case INT://分配存储单元
		PRT_PUSHTRY(a);
		sp += a;
		break;
	case JMP://无条件跳转
		ip = a;
		break;
	case JPC://如假跳转
		if(!stack[--sp]){
			ip = a;
		}
		break;
	case OPR://操作类
		switch(a){
		case 0://函数返回,恢复sp,ip,bx
			sp = bx;
			ip = stack[bx+2];
			bx = stack[bx+1];
			break;
		case 1://取负
			stack[sp-1] = -stack[sp-1];
			break;
		case 2:// add
			stack[sp-2] += stack[sp-1];
			sp --;
			break;
		case 3:// sub
			stack[sp-2] -= stack[sp-1];
			sp --;
			break;
		case 4:// mul
			stack[sp-2] *= stack[sp-1];
			sp --;
			break;
		case 5:// div
			if(stack[sp]-1 == 0){
				printf("RunTime Error:除零错误!\n");
				return TMNT;
			}
			stack[sp-2] /= stack[sp-1];
			sp --;
			break;
		case 6:// mod2
			stack[sp-1] %= 2;
			break;
		case 8:// ==
			stack[sp-2] = (stack[sp-2]==stack[sp-1]);
			sp --;
			break;
		case 9:// # 很奇怪,写成stack[sp-2] = (stack[sp-2]!=stack[sp-1]);会有问题
			if(stack[sp-2]!=stack[sp-1])
				stack[sp-2] = 1;
			else
				stack[sp-2] = 0;
			sp --;
			break;
		case 10:// <
			stack[sp-2] = (stack[sp-2]<stack[sp-1]);
			sp --;
			break;
		case 11:// <=
			stack[sp-2] = (stack[sp-2]<=stack[sp-1]);
			sp --;
			break;
		case 12:// >
			stack[sp-2] = (stack[sp-2]>stack[sp-1]);
			sp --;
			break;
		case 13:// >=
			stack[sp-2] = (stack[sp-2]>=stack[sp-1]);
			sp --;
			break;
		case 14:// echo
			printf("%d ",stack[--sp]);
			break;
		case 15:// endl
			printf("\n");
			break;
		case 16:// input
			printf(">:");
			fflush(stdin);		//清缓冲区,防止非法输入死循环
			scanf("%d",&stack[sp]);
			sp ++;
			break;
		}
		break;
	}
	return 0;
}

⌨️ 快捷键说明

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