资源描述
,编译原理,第二讲,PL/0,编译系统,PL/0,编译系统组成,PL/0,编译程序,类,P-code,虚拟机,输入数据,输出数据,PL/0,程序,类,P-code,程序,PL/0,编译程序,类,P-code,解释程序,类,P-code,虚拟机,PL/0,编译系统,PL/0,编译程序总体结构,PL/0,语言描述,PL/0,编译程序的词法分析,类,P-code,虚拟机,PL/0,编译系统,PL/0,编译程序的语法分析,PL/0,编译程序的语义分析和符号表,PL/0,编译程序的错误处理,PL/0,编译程序的目标代码生成,PL/0,编译程序,T-,型图,PL/0,类,P-code,C/Pascal,PL/0,程序示例,CONST A=10;,/*,主程序常量说明部分*,/,VAR B,C;,/*,主程序变量说明部分*,/,PROCEDURE,P,;,/*,主程序过程说明部分*,/,VAR D;,/*,过程,P,的局部变量说明部分*,/,PROCEDURE,Q,;,/*,过程,P,的局部过程说明部分*,/,VAR X;,/*,过程,Q,的局部变量说明部分*,/,BEGIN READ(X);,D:=X;,WHILE X#0,DO CALL P;END;,BEGIN WRITE(D);CALL Q;END,BEGIN CALL P;,END.,P,的过程体,Q,的过程体,主程序的过程体,PL/0,程序示例,var m,n,r,q;,计算,m,和,n,的最大公约数,procedure gcd;,begin,while r#0 do,begin,q:=m/n;,r:=m-q*n;,m:=n;,n:=r;,end,end;,begin,read(m);,read(n);,为了方便,规定,m=n,if m 0 then,begin,fact:=fact*m;,m:=m-1;,call factorial;,end;,end;,begin,读入,n,read(n);,sum:=0;,while n 0 do,begin,m:=n;,fact:=1;,call factorial;,sum :=sum+fact;,n:=n-1;,end;,输出,n!,write(sum);,end.,计算,sum=1!+2!+.+n!,(n,从控制台读入,),类,P-code,类,P-code,语言,一种,栈式机,的,语言,此类栈式机没有累加器和通用寄存器,,有一,个,栈式存储器,,有四个控制寄存器(,指令寄,存器,I,,,指令地址寄存器,P,,,栈顶寄存器,T,和,基址寄存器,B,),算逻运算都在栈顶进行,指令格式,f,l,a,f,:,操作码,l,:,层次差,(标识符引用层减去定义层),a,:,不同的指令含义不同,PL/0,程序和目标代码示例,const a=10;var b,c;procedure p;,begin c:=b+a;end;,begin read(b);while b#0 do begin call p;write(2*c);read(b);endend.,(0)jmp 0 8,转向主程序入口,(1)jmp 0 2,转向过程,p,入口,(2)int 0 3,过程,p,入口,为过程,p,开辟空间,(3)lod 1 3,取变量,b,的值到栈顶,(4)lit 0 10,取常数,10,到栈顶,(5)opr 0 2,次栈顶与栈顶相加,(6)sto 1 4,栈顶值送变量,c,中,(7)opr 0 0,退栈并返回调用点,(16),(8)int 0 5,主程序入口开辟,5,个栈空间,(9)opr 0 16,从命令行读入值置于栈顶,(10)sto 0 3,将栈顶值存入变量,b,中,(11)lod 0 3,将变量,b,的值取至栈顶,(12)lit 0 0,将常数值,0,进栈,(13)opr 0 9,次栈顶与栈顶是否不等,(14)jpc 0 24,相等时转,(24),(条件不满足转),(15)cal 0 2,调用过程,p,(16)lit 0 2,常数值,2,进栈,(17)lod 0 4,将变量,c,的值取至栈顶,(18)opr 0 4,次栈顶与栈顶相乘,(2*c),(19)opr 0 14,栈顶值输出至屏幕,(20)opr 0 15,换行,(21)opr 0 16,从命令行读取值到栈顶,(22)sto 0 3,栈顶值送变量,b,中,(23)jmp 0 11,无条件转到循环入口,(11),(24)opr 0 0,结束退栈,PL/0,编译程序总体结构,PL/0,编译程序的组织:,一个以语法、语义,分析程序为中心的,单遍编译程序,PL/0,程序,类,P-code,程序,语法、语义分析程序,词法分析程序,代码生成程序,PL/0,语言简介,PL/0,语言,为,Pascal,语言的子集,PL/0,程序示例,PL/0,语言的语法描述图,PL/0,语言的,EBNF,表示,PL/0,语言的语义规则,PL/0,语言的语法描述图,内的文字表示所用到的其他,语法单位,或,内的文字表示,单词符号,每个,语法单位,对应一个,语法描述图,一个入口和一个出口的有向图,从入口可到达任何节点,每个节点都可以到达出口,从入口到出口的路径表示该语法单位的,一种合法中间形式(短语),有两种类型的节点,PL/0,语言的语法描述图,程序,分程序,.,例:程序,和,分程序,语法单位的语法描述图,分程序,const,ident,number,=,,,;,var,ident,,,;,;,procedure,ident,;,分程序,语句,PL/0,语言,的,EBNF,表示,EBNF,的元符号,是用左右尖括号括起来的中文字表示语法构造,成分,或称,语法单位,,为非终结符,。,:=,该符号的左部由右部定义,可读作,定义为,|,表示,或,,即左部可由多个右部定义,表示花括号内的语法成分可以,重复,;在不加上,下界时可重复,0,到任意次数,有上下界时为可重复次,数的限制,表示方括号内的成分为,任选,项,(),表示圆括号内的成分,优先,例:,PL/0,语言的,EBNF,表示片断,PL/0,语言,的,EBNF,表示,:=.,:=,:=,CONST,;,:=,:=,:=,VAR,;,:=|,:=;,:=,PROCEDURE,;,PL/0,语言的语义规则,类型、上下文约束与作用域规则,数据类型只有,整数类型,数据结构只支持,简单变量,和,常数,所支持的数字为最长,9,位的十进制数,标识符的有效长度为,10,标识符引用前先要声明,过程无参数,过程可嵌套,最多嵌套,3,层,过程可递归调用,内层过程可以引用包围它的外层过程的标识符,词法分析子程序,int getsym(),功能,从当前输入符号起,扫描下一个,词法单位,即,单词,通过下列全局变量传递单词的类别,enum symbol,sym,;,通过下列全局变量传递标识符单词的值,char,id,al+1;/*al,为标识符的最大长度,*,/,通过下列全局变量传递常量单词的值,int,num,;,PL/0,编译程序的词法分析,单词类别,保留字,BEGIN,、,END,、,IF,、,THEN,、,.,运算符,、,:=,、,=,、,标识符,自定义的变量名、常数名、过程名,常数,如:,10,,,25,,,100,等整数,界符,如:,,,、,.,、,;,、,(,、,),、,PL/0,编译程序的词法分析,PL/0,编译程序的词法分析,词法分析子程序,getsym(),的处理流程,从源程序扫描下一个字符,(,调用,getch,子程序,),忽略空格、换行和,TAB,(,每忽略一个,扫描下一个,),enum symbol,sym,;,识别单词,(,每扫描过一个字符,调用一次,getch,子程序,),识别保留字,识别标识符,拼数,识别单字符单词,拼双字符单词,根据单词类别设置,sym,,,id,和,num,PL/0,编译程序的词法分析,单词的识别,可以借助于,状态转换图,进行设计,状态转换图类似于有限状态自动机,识别标识符单词、数字单词、单字符单词和,双字符单词的状态转换图见下页,保留字单词的识别可以在识别标识符单词的,基础上,再去检索保留字表,PL/0,编译程序的词法分析,实现单词识别的状态转换图,PL/0,编译程序的语法分析,功能,分析,PL/0,源程序的单词流是否符合,PL/0,语法,报告语法错误,(,上下文无关文法)句型的分析,句型分析就是识别一个符号串是否为某文法的句型的过程,或者说是某个推导的构造过程。,对于一个给定的文法,要想判定一个符号串是否为该文法的句子,需要考察是否可以从该文法的开始符号派生出(推导出)此符号串。这就是编译程序的语法分析工作。,分析算法分类,分析算法可分为:,自上而下分析法,:,从文法的开始符号出发,,,寻找,与,输入符号串,匹配,的,推导,,或者说,为输入串寻找一个最左推导。,自下而上分析法,:,从,输入符号串,开始,,,逐步进行,归约,,直至,归约,到,文法的,开始符号,。,语法分析(从概念上讲)建立一棵与输入串相匹配的语法树。语法树推导的几何表示,句型,a,a,bbaa,的可能,推导,序列和语法树,例,:GS:,S,a,AS,A,S,b,A,A,SS,S,a,A,ba,S,a,A S,S,b,A,a,a,b,a,S,a,A,S,a,A,a,a,S,b,A,a,a,S,b,ba,a,a,a,bbaa,S,a,A,S,a,S,b,A,S,a,a,b,A,S,aab,ba,S,aabba,a,S,a,A,S,a,S,b,A,S,a,S,b,A,a,a,a,b,A,a,aab,ba,a,两种方法反映了语法树的两种构造过程,自上而下方法,是从文法符号开始,将它做为语法树的根,向下逐步建立语法树,使语法树的结果正好是输入符号串,自下而上方法,则是从输入符号串开始,以它做为语法树的结果,自底向上的构造语法树,例:文法,G,:,S,c,A,d,A,ab,A,a,识别输入串,w=,cabd,是否为该文法的,句子,SSS,c,A,d,c,A,d,a,b,推导过程:,S,c,A,d,c,A,d,c,ab,d,自上而下的语法分析的一般过程,PL/0,编译程序的语法分析,分析方法,借助于,PL/0,的语法描述图或,EBNF,表示进行,自顶向下分析,合法的,PL/0,程序都可以对应一棵自顶向下构,造的,语法分析树,语法分析树的根节点为,,叶节点为构,成源程序的单词,每个内部节点代表构成源,程序的各种不同的语法单位,语法分析,(,上下文文法的句型分析,),产生源程序的语法分析结果,以语法分析树或,与之等价的形式体现出来,PL/0,编译程序的语法分析,VAR A;,BEGIN,READ(A),END.,自顶向下分析举例,.,VAR,;,BEGIN,END,(,),READ,A,A,自顶向下进行,递归下降分析,PL/0,编译程序的语法分析,实现方法,递归子程序法,可以自然实现递归下降分析过程,每个语法单位都对应一个分析子程序,其设,计基于该语法单位的语法描述图或,EBNF,表示,递归下降分析过程从调用语法单位,对,应的子程序开始,运行时的调用关系反映了,语法分析树的结构,PL/0,编译程序的语法分析,递归子程序的设计,沿语法分析图箭头所指方向进行如下工作:,遇到一个语法单元,调用相应的子程序,遇到一个词法单位,则判断当前读入的单词,是否与该词法单位相匹配,若匹配,再读取,下一个单词继续分析;若不匹配,则进行出,错处理,利用,EBNF,的方法与此相似,PL/0,编译程序的语法分析,递归子程序的设计实例,:=+|-,(,+|-,),int expression(,),if(sym=plus|sym=minus)/*,此时表达式被看作正的或负的项,*,/,getsym();,term(,);/*,处理,*/,else/*,此时表达式被看作项的加减,*,/,term(,);/*,处理,*/,while(sym=plus|sym=minus),getsym;,term(,);/*,处理,*/,return 0;,PL/0,编译程序的语法分析,递归子程序的设计实例,:=,(*,|/,),int term(,),factor,(,),;/*,处理,*/,while(sym=times|sym=slash),getsym();,factor(,);/*,处理,*/,return 0;,PL/0,编译程序的语法分析,递归子程序的设计实例,:=id_token|num_token|,(,),int factor(,),if(sym=ident)/*,为常量或变量,*,/,getsym();,elseif(sym=number)/*,为立即数,*,/,getsym();,else if (sym=lparen);/*,为立即数,*,/,expression(,);,if(sym=rparen),getsym();,else error();/*,缺少右括号,*,/,else error();/*,非,开始符号*,/,return 0;,PL/0,编译程序的语法分析,递归子程序的设计实例,(,in PASCAL,),:=+|-,(,+|-,),procedure expr;begin if sym in plus,minus then begin getsym;term;end else term;while sym in plus,minus do begin getsym;term;endend;,PL/0,编译程序的语法分析,递归子程序的设计实例,(,in PASCAL,),:=,(*,|/,),procedure term;begin factor;while sym in times,slash do begin getsym;factor;endend;,PL/0,编译程序的语法分析,递归子程序的设计实例,(,in PASCAL,),:=id_token|num_token|,(,),procedure factor;begin if sym ident then begin if sym number then begin,if sym=,(,then begin getsym;expr;if sym=,),then,getsym else error()/*,表达式后根符应是右括号*,/end else error()/*,不是表达式的开始符号*,/,end,else getsym,end,else getsym,end;,PL/0,编译程序的语法分析,PL/0,语法分析程序入口,:=,.,int main(),/*,初始化,*,/,/*,读写文件,*,/,getsym(),;,block(,)/*,处理,*/,if(sym!=period),error(9);/*,提示,9,号出错信息:缺少程序结束符,.,*/,return 0;,PL/0,编译程序的语法分析,主要语法单位相应子程序之间的调用关系,PL/0,编译程序的语义分析和符号表,功能,借助,符号表,进行上下文相关的,静态语义分析,确保符号表可以体现,作用域规则,确保,标识符属性与上下文环境一致,确保,标识符先声明后引用,确保,标识符的长度,、,数字的位数,、,过程嵌套,说明的层数,符合,PL/0,语言的约定,提示,语义错误,信息,符号表结构,Enum object,constant,variable,procedur,;,Struct tablestruct,char nameal;/*al-,名字最大长度,*,/,enum object kind;,int val;/*constant,标识符的数值,*,/,int level;/*,标识符所在的层,,constant,标识符不用,*,/,int adr;/*,标识符相对地址,,constant,标识符不用,*,/,int size;/*,需分配的数据区大小,仅,procedur,标识符用到,*,/,;,Struct tablestruct tabletxmax;/*txmax-,符号表容量,*,/,PL/0,编译程序的语义分析和符号表,CONST A=35,,,B=49,;,VAR C,,,D,,,E,;,PROCEDURE P,;,VAR G,,,X,,,Y,,,Z,;,符号表结构,例:,右边程序的说明,部分分析后的符,号表如下所示,PL/0,编译程序的语义分析和符号表,const a=25;,var x,y;,procedure p;,var z;,begin,end;,procedure r;,var x,s;,procedure t;,var v;,begin,end;,begin,/*here*/,end;,begin,end.,例:,右边程序在处理,到,/*here*/,时的符,号表如下所示,符号表与作用域规则,PL/0,编译程序的语义分析和符号表,符号表管理,void enter(enum object k,int*ptx,int lev,int*pdx),/*,k:,名字种类,const,var or procedure,ptx:,名字表尾指针的指针,lev:,名字所在的层次,pdx:,当前应分配变量的相对地址,分配后增加,1,*/,-,登录,(,在符号表中插入一项,),-,查询,int position(char*idt,int tx),/*,idt:,被查标识符名字串,tx:,符号表栈当前栈顶的位置,返回所查标识符在符号表栈中的位置,没查到则返回,0,*/,PL/0,编译程序的语义分析和符号表,PL/0,编译程序的语义分析,语义处理举例,变量,声明语句的处理,:=,var ,;,if(sym=varsym),/*,遇到变量声明符号,开始处理变量声明*,/,getsymdo;,/*,调用,getsym(),的宏*,/,do,vardeclarationdo(/*,见下页,*,/,while(sym=comma),getsymdo;,vardeclarationdo(,if(sym=semicolon),getsymdo;,else error(5);,while(sym=ident);,PL/0,编译程序的语义分析,语义处理举例,变量,声明语句的处理,(,接上页,),int vardeclaration(int*ptx,int lev,int*pdx),/*ptx:,符号表尾位置,;,lev:,当前层,;,pdx:,在当前层的偏移量,;*,/,if(sym=ident),enter(variable,ptx,lev,pdx);,/,填写名字表,getsymdo;,else,error(4);/*var,后应是标识,符,*,/,return 0;,PL/0,编译程序的语义分析,语义处理举例,变量,引用的处理,当遇到标识符的引用时就调用,POSITION,函数,查,符号,表,看是否有过正确定义,若已有,,则从表中取相应的有关信息,供代码的生成,使用,;若无定义则报错,若在符号表,有过正确定义,检查引用与说明,的属性是否一致,,若不一致则报错,PL/0,编译程序的语义分析,语义处理举例,变量引用的处,理,(,以赋值语,句中的变量引,用为例,),if(sym=ident),/*,准备按照赋值语句处理,*/,i=position(id,*ptx);,if(i=0),error(11);/*,变量未找到,*/,else,if(tablei.kind!=variable),error(12);/*,赋值语句格式错误,*/,i=0;,else,.,gendo(sto,);/*,生成目标代码,*,/,.,PL/0,编译程序的错误处理,错误处理的原则,尽可能准确指出错误位置和错误属性,尽可能进行校正,PL/0,编译程序的错误处理,短语层恢复,(,phase-level error recovery,),PL/0,编译程序的错误处理,短语层恢复,在进入某个,语法单位,时,调用,TEST,函数,检查当前,符号是否属于该语法单位的,开始符号集合,.,若不属,于,则,滤去开始符号和后跟符号集合外的所有符号,在语法单位分析结束时,调用,TEST,函数,检查当前,符号是否属于调用该语法单位时应有的,后跟符号集,合,.,若不属于,则滤去后跟符号和开始符号集合外,的所有符号,TEST,TEST,PL/0,编译程序的错误处理,开始符号集合与后跟符号集合,语法单位,开始符号集合,后跟符号集合,分程序,const var procedure ident I f call begin while read write,.;,语句,ident call begin,if while read write,.;end,条件,odd+-(,ident number,Then do,表达式,+-(,ident number,.;)rop end then do,项,ident number(,.;)rop+-end then do,因子,ident number(,.;)rop+-*/end then do,PL/0,编译程序的错误处理,test,函数,int test(bool*s1,bool*s2,int n),/*,s1,-,需要的集合,,,s2,-,补救的集合,*,/,if(!inset(sym,s1),error(n);,while(!inset(sym,s1)&(!inset(sym,s2),getsymdo;,return 0;,PL/0,编译程序的错误处理,例:因子的处理过程,int factor(bool*fsys,),/*fsys-,后跟符号集合,*,/,int i;,testdo(facbegsys,fsys,24);,/*facbegsys-,开始符号集合,*,/,while(inset(sym,facbegsys),/*,循环直到不是因子开始符号,*,/,if(),testdo(fsys,facbegsys,23);,/*,跳过因子后的非法符号,*,/,return 0;,PL/0,编译程序的错误处理,后跟符号集,随调用深度逐层增加,增加的符号与调用位置相关,例:,调用,expression(fsys,,,),;,在,write,语句的下一层,则为,expression(,rparen,comma,+fsys,,,),;,在,factor,的下一层,则为,expression(,rparen,+fsys,,,);,附:,write,语句的,语法,write(,),;,factor,的语法,:,factor=.|(exp),PL/0,编译程序的目标代码生成,目标代码生成函数,#define,gendo,(a,b,c)if(-1=gen(a,b,c)return-1,int,gen,(enum fct x,int y,int z),if(cx=cxmax),printf(Program too long);,return-1;,codecx.f=x;,codecx.l=y;,codecx.a=z;,cx+;,return 0;,PL/0,编译程序的目标代码生成,例,int statement(bool*fsys,int*ptx,int lev),if(sym=ident)/*,准备按照赋值语句处理,*,/,i=position(id,*ptx);,gendo(sto,lev-tablei.level,tablei.adr);,PL/0,编译程序的目标代码生成,跳转指令与地址返填,if(sym=ifsym)/*,准备按照,if c then s,语句处理,*,/,getsymdo;,conditiondo(.);/*,调用条件处理(逻辑运算)函数,*,/,if(sym=thensym),getsymdo;,else,error(16);/*,缺少,then*/,cx1=cx;/*,保存当前指令地址,*,/,gendo(jpc,0,0);/*,生成条件跳转指令,跳转地址未知,暂时写,0*/,statementdo(fsys,ptx,lev);/*,处理,then,后的语句,*,/,codecx1.a=cx;/*,地址返填,*,/,PL/0,编译程序的目标代码生成,例,const a=10;var b,c;procedure p;,begin c:=b+a;end;,begin read(b);while b#0 do begin call p;write(2*c);read(b);endend.,(0)jmp 0 8,转向主程序入口,(1)jmp 0 2,转向过程,p,入口,(2)int 0 3,过程,p,入口,为过程,p,开辟空间,(3)lod 1 3,取变量,b,的值到栈顶,(4)lit 0 10,取常数,10,到栈顶,(5)opr 0 2,次栈顶与栈顶相加,(6)sto 1 4,栈顶值送变量,c,中,(7)opr 0 0,退栈并返回调用点,(16),(8)int 0 5,主程序入口开辟,5,个栈空间,(9)opr 0 16,从命令行读入值置于栈顶,(10)sto 0 3,将栈顶值存入变量,b,中,(11)lod 0 3,将变量,b,的值取至栈顶,(12)lit 0 0,将常数值,0,进栈,(13)opr 0 9,次栈顶与栈顶是否不等,(14)jpc 0 24,相等时转,(24),(条件不满足转),(15)cal 0 2,调用过程,p,(16)lit 0 2,常数值,2,进栈,(17)lod 0 4,将变量,c,的值取至栈顶,(18)opr 0 4,次栈顶与栈顶相乘,(2*c),(19)opr 0 14,栈顶值输出至屏幕,(20)opr 0 15,换行,(21)opr 0 16,从命令行读取值到栈顶,(22)sto 0 3,栈顶值送变量,b,中,(23)jmp 0 11,无条件转到循环入口,(11),(24)opr 0 0,结束退栈,类,P-code,虚拟机,输入数据,输出数据,PL/0,程序,类,P-code,程序,PL/0,编译程序,类,P-code,解释程序,类,P-code,虚拟机,类,P-code,虚拟机,类,P-code,语言,一种,栈式机,的,语言,此类栈式机没有累加器和通用寄存器,,有一,个,栈式存储器,,有四个控制寄存器(,指令寄,存器,I,,,指令地址寄存器,P,,,栈顶寄存器,T,和,基址寄存器,B,),算逻运算都在栈顶进行,指令格式,f,l,a,f,:,操作码,l,:,层次差,(标识符引用层减去定义层),a,:,不同的指令含义不同,目标代码解释执行时数据栈的布局(运行栈的存储分配),在每个过程调用时在栈顶分配,3,个联系单元:,SL,:,静态链,,指向,定义,该过程的,直接外过程,(或主程序)运行时,最新,数据段的基地址,。,DL,:,动态链,,指向,调用,该过程前正在运行过 程的数据段基地址。,RA,:,返回地址,,记录调用该过程时,目标程序的,断点,,即调用过程指令的下一条指令的地址。,例,Var x,y;,Procedure P;,var a;,procedure Q;,var b;,begin(*Q*),b:=10;,end(*Q*);,procedure S;,var c,d;,procedure R;,var e,f;,begin(*R*),call Q;,end(*R*);,begin(*S*),call R;,end(*S*);,begin(*P*),call S;,end;(*P*),begin(*MAIN*),call P;,end(*MAIN*).,目标代码的解释执行 运行栈,S,布局,M,调用过程,P M,调用过程,P P,调用过程,S,RA,DL,SL,b,t,t,b,P,M,P,M,S,类,P-code,虚拟机,指令,“,INT 0 A”,在栈顶开辟,A,个存储单元,服务于被调用的过程,A,等于该过程的,局部变量数加,3,3,个,特殊的,联系单元,类,P-code,虚拟机,指令,“,OPR 0 0”,过程调用结束后,返回调用点并退栈,重置基址寄存器和栈顶寄存器,类,P-code,虚拟机,指令,“,CAL L A”,调用地址为,A,的过程(置指令地址寄存器为,A,),L,为调用过程与被调用过程的,层差,设置被调用过程的,3,个联系单元,类,P-code,虚拟机,指令,“,LIT 0 A”,立即数存入栈顶,即置,T,所指存储单元的值为,A,T,加,1,指令,“,LOD L A”,将层差为,L,、,偏移量为,A,的存储单元的值取到栈顶,T,加,1,指令,“,STO L A”,T,减,1,将栈顶的值存入层差为,L,、,偏移量为,A,的存储单元,注:,层差为,L,、,偏移量为,A,的存储单元,即沿当前层静,态链,SL,开始向前第,L,层的,SL,作为基址,加上,A,,即为该,单元的地址,类,P-code,虚拟机,指令,“,OPR 0 1”,求栈顶元素的相反数,结果值留在栈顶,指令,“,OPR 0 6”,栈顶元素的奇偶判断,若为奇数,结果为,1,;若为偶,数,结果为,0,;结果值留在栈顶,类,P-code,虚拟机,指令,“,OPR 0 2”,次栈顶与栈顶的值相加,结果存入次栈顶,T,减,1,指令,“,OPR 0 3”,次栈顶的值减去栈顶的值,结果存入次栈顶,T,减,1,指令,“,OPR 0 4”,次栈顶的值乘以栈顶的值,结果存入次栈顶,T,减,1,指令,“,OPR 0 5”,次栈顶的值除以栈顶的值,结果存入次栈顶,T,减,1,类,P-code,虚拟机,指令,“,OPR 0 8”,比较次栈顶与栈顶是否相等,若相等,结果为,0,;存结果至次栈顶;,T,减,1,指令,“,OPR 0 9”,比较次栈顶与栈顶是否不相等,若不相等,结果为,0,;存结果至次栈顶;,T,减,1,指令,“,OPR 0 10”,比较次栈顶是否小于栈顶,若小于,结果为,0,;存结果至次栈顶;,T,减,1,指令,“,OPR 0 11”,比较次栈顶是否大于等于栈顶,若大于等于,结果为,0,;存结果至次栈顶;,T,减,1,指令,“,OPR 0 12”,比较次栈顶是否大于栈顶,若大于,结果为,0,;存结果至次栈顶;,T,减,1,指令,“,OPR 0 13”,比较次栈顶是否小于等于栈顶,若小于等于,结果为,0,;存结果至次栈顶;,T,减,1,类,P-code,虚拟机,指令,“,JMP 0 A”,无条件转移至地址,A,,即置,指令地址寄存器为,A,指令,“,JPC 0 A”,条件转移指令,若栈顶为,0,,则转移至地址,A,,即置指令地址寄存,器为,A,类,P-code,虚拟机,指令,“,OPR 0 14”,栈顶的值输出至控制台屏幕,指令,“,OPR 0 15”,控制台屏幕输出一个换行,指令,“,OPR 0 16”,从控制台读入一行输入,置入栈顶,T,加,1,类,P-code,虚拟机,类,P-code,解释程序,数据结构,运行栈,int sstacksize,指令寄存器,struct instruction,enum fct f;/*,操作码,*,/,int l;/*,引用层与声明层的层差,*,/,int a;/*,因不同的,f,各异,*,/,i,指令地址寄存器,int p;,基址寄存器,int b;,栈顶寄存器,int t,;,虚拟机代码段,struct instruction codecxmax;,类,P-code,虚拟机,类,P-code,解释程序,处理流程,(,1,),初始化,p=b=t=0,;,s0=s1=s2=0,;,(,2,),取指令到指令寄存器,i=codep,;,p+,;,(,3,),分析并解释执行指令,i,(,4,),若程序未结束(,p!=0,),转,(,2,),(,5,),返回,课后作业,5%,修改,PL/0,编译程序和类,P-code,解释程序文本,以支持,PL/0,语言所进行的如下扩充,并调试通过,.,(,1,),增加整型一维数组变量,形式为,:,:=,(:),其中,和,是常量名或整数,(,请注意相应的变量说明和赋值语句形式,!),(,2,),条件语句改为,:=IF,THEN ELSE,三月份之内完成后随时提交,提交方式另通知,.,Thank You,
展开阅读全文