📄 pl0run.cpp
字号:
///////////////////////////////////////////////////////////////
// PL/0 ASM Interpreter 0.1 (2003.12.27) [Source File]
// Author:Dwing
///////////////////////////////////////////////////////////////
#include<stdio.h> //For <printf> ...
#include<string.h> //For <strcmp>
///////////////////////////////////////////////////////////////
typedef struct //汇编指令格式
{
char opr; //指令操作码
char lvl; //级数
unsigned short adr; //地址码/操作数
}ASM;
enum{OP_LIT,OP_LOD,OP_STO,OP_CAL,OP_INT,OP_JMP,OP_JPC,OP_OPR};
enum{
OPR_RET,OPR_NEG,OPR_ADD,OPR_SUB,OPR_MUL,OPR_DIV,
OPR_ODD,OPR_NUL,OPR_EQL,OPR_NE ,OPR_LT ,OPR_LGE,
OPR_LG ,OPR_LTE,OPR_WRT,OPR_WRN,OPR_RED
};
///////////////////////////////////////////////////////////////
int getbase(short *s,int base,int lvl) //取基址
{
while(lvl--) base=s[base];
return base;
}
///////////////////////////////////////////////////////////////
int _main() //Program Entry
{
int i,num;
char b[4];
ASM a[16384];
FILE *fp;
fp=fopen("temp.pl0","rb");
if(!fp)
{
printf("PL/0 ASM Interpreter 0.1\n");
printf("Can't open \"temp.pl0\"!\n");
return 0;
}
fscanf(fp,"%u",&num);
for(i=0;i<num;i++)
{
fscanf(fp,"%*4u:%s%u%u",b,&a[i].lvl,&a[i].adr);
if(!strcmp(b,"LIT")) a[i].opr=OP_LIT;
if(!strcmp(b,"LOD")) a[i].opr=OP_LOD;
if(!strcmp(b,"STO")) a[i].opr=OP_STO;
if(!strcmp(b,"CAL")) a[i].opr=OP_CAL;
if(!strcmp(b,"INT")) a[i].opr=OP_INT;
if(!strcmp(b,"JMP")) a[i].opr=OP_JMP;
if(!strcmp(b,"JPC")) a[i].opr=OP_JPC;
if(!strcmp(b,"OPR")) a[i].opr=OP_OPR;
}
fclose(fp);
short s[16384]={0},bp=0,sp=3,ip=0;
do{
switch(a[ip].opr)
{
case OP_INT:sp+=a[ip].adr; break;
case OP_LIT:s[++sp]=a[ip].adr; break;
case OP_LOD:s[++sp]=s[getbase(s,bp,a[ip].lvl)+a[ip].adr];break;
case OP_STO:s[getbase(s,bp,a[ip].lvl)+a[ip].adr]=s[sp--];break;
case OP_JMP:ip=a[ip].adr-1; break;
case OP_JPC:if(!s[sp--]) ip=a[ip].adr-1; break;
case OP_CAL:
s[sp++]=getbase(s,bp,a[ip].lvl);//静态链
s[sp++]=bp; //动态链
s[sp++]=ip+1; //返回地址
bp=sp-3;
ip=a[ip].adr-1;
break;
case OP_OPR:
switch(a[ip].adr)
{
//过程返回
case OPR_RET:sp=bp; ip=s[bp+2]-1; bp=s[bp+1]; break;
//栈顶元素取负数
case OPR_NEG:s[sp]=-s[sp];break;
//次栈顶和栈顶相加,结果为栈顶
case OPR_ADD:sp--;s[sp]=s[sp]+s[sp+1];break;
//次栈顶和栈顶相减,结果为栈顶
case OPR_SUB:sp--;s[sp]=s[sp]-s[sp+1];break;
//次栈顶和栈顶相乘,结果为栈顶
case OPR_MUL:sp--;s[sp]=s[sp]*s[sp+1];break;
//次栈顶和栈顶相除,结果为栈顶
case OPR_DIV:sp--;s[sp]=s[sp]/s[sp+1];break;
//栈顶是否为奇数,结果入栈(0或1)
case OPR_ODD:s[sp]=s[sp]&1;break;
//次栈顶和栈顶是否相等,结果入栈(0或1)
case OPR_EQL:sp--;s[sp]=(s[sp]==s[sp+1]);break;
//次栈顶和栈顶是否不等,结果入栈(0或1)
case OPR_NE: sp--;s[sp]=(s[sp]!=s[sp+1]);break;
//次栈顶是否比栈顶小,结果入栈(0或1)
case OPR_LT: sp--;s[sp]=(s[sp]<s[sp+1]);break;
//是否次栈顶大于等于栈顶,结果入栈(0或1)
case OPR_LGE:sp--;s[sp]=(s[sp]>=s[sp+1]);break;
//是否次栈顶大于栈顶,结果入栈(0或1)
case OPR_LG: sp--;s[sp]=(s[sp]>s[sp+1]);break;
//是否次栈顶小于等于栈顶,结果入栈(0或1)
case OPR_LTE:sp--;s[sp]=(s[sp]<=s[sp+1]);break;
//打印栈顶元素
case OPR_WRT:printf("%u",s[sp--]);break;
//打印回车
case OPR_WRN:putchar('\n');break;
//从键盘读取数
case OPR_RED:putchar('?');scanf("%u%*c",&s[++sp]);break;
}
}
ip++; //得到下条指令
}while(ip);
printf("\nProgram terminated!\nPress ENTER to return...");
getchar();
return 0;
}
///////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -