📄 execute.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 + -