📄 pas.c
字号:
getch();
printf("\n**************变量表****************************\n");
for(tttt=0;tttt<tt1;tttt++)
printf("%d\t%s\n",tttt,ntab1[tttt]);
getch();
}
/*************************************************/
//文件:read.c
//从源文件中读取四元式,或从键盘输入四元式
/***************************************************/
//#include "globals.h"
m1 m1_line;//中间语言变量名
//char spelling[10]={""};//存放识别的字符
//从文件读取一个字到内存单元
void getword()
{
int i=0;
char ch;
ch=getc(source);
while(ch!='\t')
{
spelling[i]=ch;
i++;
ch=getc(source);
}
spelling[i]='\0';
}
//从文件读取四元式,输入到内存
void read_file(char *sourcefile)
{
int line;//四元式行号从100开始
m1 k,l;
char ch;
printf("\n正在读取四元式源文件%s!……",sourcefile);
m1_line=(m1)malloc(sizeof(struct MLanguage));
fscanf(source,"%d",&line);
m1_line->line=line;
fseek(source,2,1);
getword();
strcpy(m1_line->op,spelling);
fseek(source,1,1);
getword();
strcpy(m1_line->opv1,spelling);
fseek(source,1,1);
getword();
strcpy(m1_line->opv2,spelling);
fseek(source,1,1);
getword();
strcpy(m1_line->result,spelling);
m1_line->next=NULL;
ch=getc(source);
while((ch!='\n')&&(!feof(source)))
ch=getc(source);
k=m1_line;
while(!feof(source))
{
line++;
l=(m1)malloc(sizeof(struct MLanguage));
l->line=line;
ch=getc(source);
while(ch!='(')
ch=getc(source);
getword();
strcpy(l->op,spelling);
fseek(source,1,1);
getword();
strcpy(l->opv1,spelling);
fseek(source,1,1);
getword();
strcpy(l->opv2,spelling);
fseek(source,1,1);
getword();
strcpy(l->result,spelling);
l->next=k->next;
k->next=l;
k=l;
ch=getc(source);
while((ch!='\n')&&(!feof(source)))
ch=getc(source);
}
}
/*****************************************/
//文件:symtab.c
//为四元式代码变量产生符号表和建立汇编语言的数据段
//生成代码时选择寄存器的依据存储在符号表中
//符号表以链式的哈希表实现
/*****************************************/
//#include "globals.h"
//SHIFT是作为哈希函数乘数的权值
#define SHIFT 4
vr HashTable[26];//符号表的哈希表结构
vr HashTable_1[26];//临时变量的符号表
//extern m1 m1_line;
//产生键值的哈希函数
static int hash(char key[])
{
int temp=0;
int i=0;
while(key[i]!='\0')
{
temp=((temp<<SHIFT)+key[i])%26;
++i;
}
return temp;
}
//过程st_insert把程序变量插入符号表
void st_insert(char name[],vr Table[])
{
int h=hash(name);
vr l=Table[h];
while((l!=NULL)&&(strcmp(name,l->name)!=0))
{
l=l->next;
}
if(l==NULL) //变量还没有登记到符号表中
{
l=(vr)malloc(sizeof(struct VariableRec));
strcpy(l->name,name);
l->regstats=0;
l->regnum=0;
//以上三行是变量在符号表中的进行初始化
l->next=Table[h];
Table[h]=l;//把变量登记到符号表相应位置
}
else
return;//如果已经在符号表中存在,则返回
}//st_insert
//过程insert根据变量是变量还是临时变量,然后执行st_insert过程
//把不同的变量插入相应的符号表
void insert(char name[])
{
if((name[0]>='a')&&(name<='z'))
{
st_insert(name,HashTable);
}
else if((name[0]>='A')&&(name[0]<='Z'))
{
st_insert(name,HashTable_1);
}
else return;//如为其他,则不插入符号表中
}
//建立符号表的函数,变量和临时变量保存在不同的符号表中
void buildsymtab()
{
m1 l;
int i;
l=m1_line;
printf("\n正在进行一遍扫描,以提取变量,建立符号表!……");
for(i=0;i<26;i++)
{
HashTable[i]=NULL;
HashTable_1[i]=NULL;
}
while(l!=NULL)
{
insert(l->opv1);
insert(l->opv2);
insert(l->result);
l=l->next;
}
}
//在符号表中查找变量,返回所需变量在符号表中的地址
vr st_lookup(char name[],vr Table[])
{
int h=hash(name);
vr l=Table[h];
while((l!=NULL)&&(strcmp(name,l->name)!=0))
{
l=l->next;
}
return l;
}
//判断是变量还是临时变量,然后选择不同的参数查找符号表
vr lookup(char name[])
{
vr l;
if((name[0]>='a')&&(name[0]<='z'))
{
l=st_lookup(name,HashTable);
}
else if((name[0]>='A')&&(name[0]<='Z'))
{
l=st_lookup(name,HashTable_1);
}
else l=NULL;
return l;
}
//建立数据段的主程序,临时变量不存入数据段
void create_dataseg()
{
int i;
vr l;
printf("\n正在生成汇编语言的数据段!……");
for(i=0;i<26;i++)
{
l=HashTable[i];
while(l!=NULL)
{
fprintf(code," %-10s DW",l->name);//定义字变量
fprintf(code,"\n");
l=l->next;
}
}
}
/**********************************************************8/
//文件:block.c
//为中间语言建立基本块
/********************************************************/
//#include "globals.h"
int Block[100];//保存基本块的行号
//extern m1 m1_line;
int i,j=0,k;//n=0;
char *m;
m1 l;
//划分基本块的函数,产生基本块入口的四元式行地址,并按照行地址从小到大排列
void create_basicblock()
{
l=m1_line;
printf("\n正在进行二遍扫描,以生成基本块的入口地址!……");
for(i=0;i<100;i++)
{
Block[i]=-1;
}
Block[0]=1;
while(l!=NULL)
{
if(l->op[0]=='j')
{
m=l->result;
while(*m!='\0')
{
j=j*10+(*m-48);
m++;
}
Block[j%100]=1;
j=0;
i++;
Block[(l->next->line)%100]=1;
}
l=l->next;
}
}
/*********************************************/
//文件:code.c
//这里存放生成各类型代码的函数
//被cgen.c文件中的create_codeseg函数调用
/*********************************************/
//#include "globals.h"
//emitcomment函数在目标语言文件中添加注释
void emitcomment(char *c)
{
fprintf(code," %s",c);
}
//产生寄存器<-->寄存器的汇编指令
void emitRR(char *op,char *r1,char *r2,char *comment)
{
fprintf(code," %s %s,%s",op,r1,r2);
emitcomment(comment);
fprintf(code,"\n");
}
//产生寄存器<-->存储器的汇编指令
void emitRM(char *op,char *r,char *m,char *comment)
{
fprintf(code," %s %s,%s",op,r,m);
emitcomment(comment);
fprintf(code,"\n");
}
//产生立即数<-->寄存器的汇编指令
void emitRC(char *op,char *r,char *con,char *comment)
{
fprintf(code," %s %s,%s",op,r,con);
emitcomment(comment);
fprintf(code,"\n");
}
//产生乘法,除法的汇编指令
void emitTO(char *op,char *s,char *comment)
{
fprintf(code," %s %s,%s",op,s);
emitcomment(comment);
fprintf(code,"\n");
}
//产生跳转和条件跳转的汇编指令
void emitJ(char *op,char *s,char *comment)
{
fprintf(code," %s %s,%s",op,s);
emitcomment(comment);
fprintf(code,"\n");
}
/********************************************/
/*文件cgen.c */
/*执行中间语言的分析,调用相应的子程序, */
/*来完成汇编代码的产生 */
/********************************************/
//#include "globals.h"
//#include "symtab.h"
//#include "code.h"
/*保存CPU四个通用寄存器AX、BX、CX、DX的使用状态。*/
typedef struct Register
{
char reg[3];
int stats;
int alter;
char varname[10];
}reg;
reg regstats[4];
extern m1 m1_line;/*四元式中间语言代码的指针*/
extern vr HashTable[26];/*保存变量的符号表*/
extern vr HashTable_1[26];/*保存临时变量的符号表*/
extern int Block[100];/*保存基本快的行号*/
vr v1,v2,re,temp;
/*函数assign在生成汇编语言代码时为变量分配寄存器,返回所分配寄存器的名字*/
int assign(vr variable)
{
int i;
for(i=0;i<=3;i++)/*一次分配*/
{
if(regstats[i].stats==0)
{
variable->regstats=1;
variable->regnum=i;
regstats[i].stats=1;
strcpy(regstats[i].varname,variable->name);
return i;
}
}
if(variable->regstats==0)/*二次分配*/
{
for(i=0;i<=3;i++)
{
if((regstats[i].varname[0]>='A')&&(regstats[i].varname[0]<='Z'))
{
if((strcmp(regstats[i].varname,v1->name)!=0)&&(strcmp(regstats[i].varname,v2->name)!=0)&&(strcmp(regstats[i].varname,re->name)!=0))
{
temp=st_lookup(regstats[i].varname,HashTable_1);
temp->regstats=0;
variable->regstats=1;
variable->regnum=i;
regstats->stats=1;
strcpy(regstats[i].varname,variable->name);
return i;
}
}
}
}
if(variable->regstats==0)/*三次分配*/
{
for(i=0;i<=3;i++)
{
if((strcmp(regstats[i].varname,v1->name)!=0)&&(strcmp(regstats[i].varname,v2->name)!=0)&&(strcmp(regstats[i].varname,re->name)!=0))
{
temp=st_lookup(regstats[i].varname,HashTable);
if(regstats[i].alter==1)
{
emitRM("mov",temp->name,regstats[i].reg,";保存不用的变量,以空出寄存器供变量使用");
temp->regstats=0;
}
variable->regstats=1;
variable->regnum=i;
regstats[i].stats=1;
strcpy(regstats[i].varname,variable->name);
return i;
}
}
}
}
/*函数assign_1在生成汇编语言代码时为常数分配寄存器,返回 所分配寄存器的名字*/
/*只在生成算法、除法和条件跳转指令时可能需要*/
int assign_1()
{
vr con=(vr)malloc(sizeof(struct VariableRec));
int i;
for(i=1;i<=2;i++)/*一次分配*/
{
if(regstats[i].stats==0)
{
con->regstats=1;
return i;
}
}
if(con->regstats==0)/*二次分配*/
{
for(i=1;i<=2;i++)
{
if((regstats[i].varname[0]>='A')&&(regstats[i].varname[0]<='Z'))
{
if((strcmp(regstats[i].varname,v1->name)!=0)&&(strcmp(regstats[i].varname,v2->name)!=0)&&(strcmp(regstats[i].varname,re->name)!=0))
{
temp=st_lookup(regstats[i].varname,HashTable_1);
temp->regstats=0;
con->regstats=1;
regstats[i].stats=0;
return i;
}
}
}
}
if(con->regstats==0)/*三次分配*/
{
for(i=1;i<=2;i++)
{
if((strcmp(regstats[i].varname,v1->name)!=0)&&(strcmp(regstats[i].varname,v2->name)!=0)&&(strcmp(regstats[i].varname,re->name)!=0))
{
temp=st_lookup(regstats[i].varname,HashTable);
if(regstats[i].alter==1)
{
emitRM("mov",temp->name,regstats[i].reg,";保存不用的变量,以空出寄存器供变量使用");
temp->regstats=0;
}
con->regstats=1;
regstats[i].stats=0;
return i;
}
}
}
free(con);
}
/*产生代码段的主程序,通过对变量寄存器的分配,调用不同的函数来产生汇编语言*/
/*代码*/
void emit_code(m1 medline)
{
int j,reg;
switch(medline->op[0])
{
case '+':
v1=lookup(medline->opv1);
v2=lookup(medline->opv2);
re=lookup(medline->result);
/*以上三行是三个操作数在符号表中的定位*/
if(re->regstats==1)
reg=re->regnum;
else
reg=assign(re);
if(v1!=NULL)
{
if(v1->regstats==1)
emitRR("mov",regstats[reg].reg,regstats[v1->regnum].reg,";把在寄存器中的被加数赋给结果寄存器");
else
emitRM("mov",regstats[reg].reg,v1->name,";把在存储器中的被加数赋给结果寄存器");
}
else
{
emitRC("mov",regstats[reg].reg,medline->opv1,";把被加数立即数赋给结果寄存器");
}/*为结果寄存器赋被加数的值*/
if(v2!=NULL)
{
if(v2->regstats==1)
emitRR("add",regstats[reg].reg,regstats[v2->regnum].reg,";把被加数和在寄存器中的加数相加");
else
emitRM("add",regstats[reg].reg,v2->name,";把被加数和在存储器中的加数相加");
}
else
{
emitRC("add",regstats[reg].reg,medline->opv2,";把被加数和加数立即数相加");
}/*完成对加法的四元式编译。*/
regstats[reg].alter=1;
break;
case '-':
v1=lookup(medline->opv1);
v2=lookup(medline->opv2);
re=lookup(medline->result);
/*以上三行是三个操作数在符号表中的定位*/
if(re->regstats==1)
reg=re->regnum;
else
reg=assign(re);
if(v1!=NULL)
{
if(v1->regstats==1)
emitRR("mov",regstats[reg].reg,regstats[v1->regnum].reg,";把在寄存器中的被减数赋给结果寄存器");
else
emitRM("mov",regstats[reg].reg,v1->name,";把在存储器中的被减数赋给结果寄存器");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -