#include "StdAfx.h"
#include ".\code.h"
#include
#include
#include
using namespace std;
CCode::CCode(CPl0*p)
{
cx = 0;
pl=p;
}
/*目标代码生成过程gen
参数:x:要生成的一行代码的助记符
y, z:代码的两个操作数
本过程用于把生成的目标代码写入目标代码数组,供后面的解释器解释执行 */
void CCode::Gen(enum fct x,int y,int z)
{
if (cxcxmax表示当前生成的代码行号大于允许的最大代码行数
{
code[cx].f=x;
code[cx].l=y;
code[cx].a=z;
cx++; //移动cx指针指向下一个空位
}
}
/* 通过静态链求出数据区基地址的函数base
参数说明:l:要求的数据区所在层与当前层的层差
返回值:要求的数据区基址 */
int CCode::base(int l)
{
int b1;
b1=b; //首先从当前层开始
while (l>0)
{
b1=s[b1]; //用当前层数据区基址中的内容(正好是静态链SL数据,为上一层的基址)
//的作为新的当前层,即向上找了一层
l--; //向上了一层,l减一
}
return b1; //把找到的要求的数据区基址返回
}
void CCode::Interpret()
{
int p,t;
fct f;
int l,a;
t=0;b=1;p=0; //程序开始运行时栈顶寄存器置0,数据段基址为1,从0号代码开始执行程序
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) //如果i的f,即指令助记符是下面的某种情况,执行不同的功能
{
case lit:
s[++t]=a; //栈顶指针上移,在栈中分配了一个单元
break; //该单元的内容存放i指令的a操作数,即实现了把常量值放到运行栈栈顶
case opr:
switch (a)
{
case 0:
t=b-1; //释放这段子过程占用的数据内存空间
p=s[t+3]; //把指令指针取到RA的值,指向的是返回地址
b=s[t+2]; //把数据段基址取到DL的值,指向调用前子过程的数据段基址
break;
case 1:
s[t]=-s[t]; //对栈顶数据进行取反
break;
case 2:
t--;
s[t]=s[t]+s[t+1]; //把两单元数据相加存入栈顶
break;
case 3:
t--;
s[t]=s[t]-s[t+1]; //把两单元数据相减存入栈顶
break;
case 4: t--;
s[t]=s[t]*s[t+1]; //把两单元数据相乘存入栈顶
break;
case 5:
t--;
s[t]=s[t]/s[t+1]; //把两单元数据相整除存入栈顶
break;
case 6:
s[t]=s[t]%2; //数据栈顶的值是奇数则把栈顶值置1,否则置0
break;
case 8:
t--;
s[t]=(s[t]==s[t+1]);//判等,相等栈顶置1,不等置0
break;
case 9:
t--;
s[t]=(s[t]!=s[t+1]);//判不等,不等栈顶置1,相等置0
break;
case 10:
t--;
s[t]=(s[t] break;
case 11:
t--;
s[t]=(s[t]>=s[t+1]);//判大于等于,如果下面的值大于等于上面的值,栈顶置1,否则置0
break;
case 12:
t--;
s[t]=(s[t]>s[t+1]); //判大于,如果下面的值大于上面的值,栈顶置1,否则置0
break;
case 13:
t--;
s[t]=(s[t] break;
case 14:
cout break;
case 15:
cout break;
case 16:
t++;
cout cin>>s[t]; //16号操作是接受键盘值输入到栈顶
break;
}
break;
case lod: //如果是lod指令:将变量放到栈顶
t++; //栈顶上移,开辟空间
s[t]=s[base(l)+a]; //通过数据区层差l和偏移地址a找到变量的数据,存入上面开辟的新空间(即栈顶)
break;
case sto:
s[base(l)+a]=s[t]; //把栈顶的值存入位置在数据区层差l偏移地址a的变量内存
t--; //栈项下移,释放空间
break;
case 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 tint:
t+=a; //栈顶上移a个空间,即开辟a个新的内存单元
break;
case jmp:
p=a; //把jmp指令操作数a的值作为下一次要执行的指令地址,实现无条件跳转
break;
case jpc:
if (s[t]==0) //判断栈顶值
p=a; //如果是0就跳转,否则不跳转
t--; //释放栈顶空间
break;
}
}while (p!=0);
}
//逐行输出代码
void CCode::ListCode()
{
FILE *fp;
//int i;
char c[1];
char *filename = pl->flnm;
strcat(filename,".txt");
if((fp=fopen(filename,"wb"))==NULL)
{
printf("cant open the file");
exit(0);
}
for (int i=0;i {
cout switch (code[i].f)
{
case lit:
cout fwrite("lit ",sizeof(char),strlen("lit "),fp);
break;
case lod:
cout fwrite("lod ",sizeof(char),strlen("lod "),fp);
break;
case sto:
cout fwrite("sto ",sizeof(char),strlen("sto "),fp);
break;
case cal:
cout fwrite("cal ",sizeof(char),strlen("cal "),fp);
break;
case tint:
cout fwrite("int ",sizeof(char),strlen("int "),fp);
break;
case jmp:
cout fwrite("jmp ",sizeof(char),strlen("jmp "),fp);
break;
case jpc:
cout fwrite("jpc ",sizeof(char),strlen("jpc "),fp);
break;
case opr:
cout fwrite("opr ",sizeof(char),strlen("opr "),fp);
break;
}
cout c[0] = static_cast('0'+ code[i].l);
fwrite(c,sizeof(char),1,fp);
fwrite(" ",sizeof(char),strlen(" "),fp);
if(code[i].a >= 10)
{
c[0] = static_cast('0'+ code[i].a / 10);
fwrite(c,sizeof(char),1,fp);
}
c[0] = static_cast('0'+ code[i].a%10);
fwrite(c,sizeof(char),1,fp);
fwrite("\t\t",sizeof(char),strlen("\t\t"),fp);
}
}
CCode::~CCode(void)
{
}