第07章_中间代码生成精.ppt
第07章_中间代码生成第1页,本讲稿共93页例如:表达式 A+B*C对运算对象进行类型检查,对变量进行先定义后使用检查 如果静态语义正确,语义处理则要执行真正的翻译,即生成程序的某种中间代码的形式或直接生成目标代码。执行真正的翻译执行真正的翻译第7章 语法制导翻译技术和中间代码生成第2页,本讲稿共93页 目前多数编译程序进行语义分析的方法是采用语法制导翻译法采用语法制导翻译法。它不是一种形式系统,但它比较接近形式化。语法制导翻译法使用属性文法为工具来描述程序设计语言的语义。第7章 语法制导翻译技术和中间代码生成第3页,本讲稿共93页(1)属性 对文法的每一个符号,引进一些属性,这些属性代表与文法符号相关的信息,如类型、值、存储位置等。与属性相关的信息,即属性值,可以在语法分析过程中计算和传递。1.属性文法第7章 语法制导翻译技术和中间代码生成第4页,本讲稿共93页属性分为两类:综合属性其计算规则按“自下而上”方式进行,即规则左部符号的某些属性根据其右部符号的属性和(或)自己的其他属性计算得到。属性加工的过程即是语义的处理过程。属性加工的过程即是语义的处理过程。综合属性和继承属性。第7章 语法制导翻译技术和中间代码生成第5页,本讲稿共93页继承属性其计算规则按“自上而下”方式进行,即规则右部符号的某些属性根据其左部符号的属性和(或)右部其他符号的某些属性计算得到。第7章 语法制导翻译技术和中间代码生成第6页,本讲稿共93页(2)属性文法 为文法的每一个规则配备的计算属性的计算规则,称为语义规则(描述语义处理的加工动作)。属性文法包含一个上下文无关文法和一系列语义规则。语义规则:第7章 语法制导翻译技术和中间代码生成第7页,本讲稿共93页 这些语义规则附在文法的每个产生式上,在语法分析过程中,执行语义规则描述的动作,从而实现语义处理。也就是说,附在文法的每个产生式上语义规则描述了语义处理的加工动作。目前流行的语义描述和语义处理的方法主要是属性文法和语法制导翻译方法。第7章 语法制导翻译技术和中间代码生成第8页,本讲稿共93页2.语法制导翻译法语法制导翻译法 为文法的每个产生式都配备一个语义动作或语义子程序。在语法分析的过程中,每当使用一条产生式进行推导或归约时,就执行相应产生式的语义动作,从而实现语义处理。第7章 语法制导翻译技术和中间代码生成(1)语法制导翻译法的基本思想第9页,本讲稿共93页S Axy a1 a2 a3 ai ai+1 an语义处理的加工动作 语法制导翻译法使用属性文法为工具来说明程序设计语言的语义。第7章 语法制导翻译技术和中间代码生成第10页,本讲稿共93页(2)语法制导翻译法语法制导翻译法 在语法分析过程中,依随分析的过程,根据每个产生式所对应的语义子程序(或语义规则描述的语义处理的加工动作)进行翻译的方法。第7章 语法制导翻译技术和中间代码生成第11页,本讲稿共93页为文法每一产生式设计相应的求值的语义描述(语义动作):例如,设有简单算术表达式的文法:EEE|E*E|(E)|digit1.E E(1)E(2)E.val E(1).val E(2).val 2.E E(1)*E(2)E.val E(1).val*E(2).val 3.E (E(1)E.val E(1).val 4.E digit E.val Lex.digit 第7章 语法制导翻译技术和中间代码生成第12页,本讲稿共93页E.val=47E.val=8E.val=40E.val=7E.val=5+5*871.E E(1)E(2)E.val E(1).val E(2).val 2.E E(1)*E(2)E.val E(1).val*E(2).val 3.E (E(1)E.val E(1).val 4.E digit E.val Lex.digit 句子 7+8*5 EEEEE第13页,本讲稿共93页3.编译中常用的中间代码:逆波兰式四元式三元式树形表示第7章 语法制导翻译技术和中间代码生成第14页,本讲稿共93页逆波兰式逆波兰式 逆波兰式除去了原表达式中的括号,并将运算对象写在前面,运算符写在后面,因而又称为后缀式后缀式。例如:逆波兰式a*bab*(a+b)*(c+d)ab+cd+*中缀表达式第7章 语法制导翻译技术和中间代码生成第15页,本讲稿共93页 逆波兰式表示法同中缀表示法相比其优点是:1.不再有括号,且运算符出现的顺序体 现了中缀表达式的运算顺序2.易于计算机处理第7章 语法制导翻译技术和中间代码生成第16页,本讲稿共93页 一般表达式计值时,要处理两类符号,一类是运算对象,另一类是运算符,通常用两个工作栈分别处理。但处理用逆波兰式表示的表达式却只用一个工作栈。第7章 语法制导翻译技术和中间代码生成第17页,本讲稿共93页 当计算机自左到右顺序扫描逆兰波式时,若当前符号是运算对象则进栈,若当前符号是运算符,设为K元运算符,则将栈顶的K个元素依次取出,同时进行K元运算,并将运算结果置于栈顶,表达式处理完毕时,其计算结果自然呈现在栈顶。第7章 语法制导翻译技术和中间代码生成第18页,本讲稿共93页逆波兰式ab+c*的处理过程如下图:baT1第7章 语法制导翻译技术和中间代码生成cT1T2第19页,本讲稿共93页逆波兰形式可以推广到其他语法结构:赋值语句V=E逆波兰式VE=条件语句逆波兰式if E S1;else S2ES1S2¥第7章 语法制导翻译技术和中间代码生成第20页,本讲稿共93页三元式和树形表示三元式三元式主要由三部分组成:(OP,arg1,arg2)其中OP是运算符,arg1,arg2分别是第一和第二个运算对象。当OP是一目运算时,常常将运算对象定义为arg1。第7章 语法制导翻译技术和中间代码生成第21页,本讲稿共93页例如 a+b*c 的 三元式序列:(1)(*,b,c)(2)(+,a,(1)运算对象是指向符号表的某一项或指向三元式表的某一项。第7章 语法制导翻译技术和中间代码生成第22页,本讲稿共93页 1.三元式出现的顺序和语法成分的 计值顺序相一致。三元式的特点:2.三元式之间的联系是通过指示器 实现的。第7章 语法制导翻译技术和中间代码生成第23页,本讲稿共93页间接三元式(1)间接三元式表:用来存放各三元式本身。(2)间接码表:按执行各三元式的顺序,依次 列出各三元式在三元式表中的位置。注意注意:间接三元式表中不存放重复的间接三元式表中不存放重复的 三元式。三元式。第7章 语法制导翻译技术和中间代码生成第24页,本讲稿共93页 例如 语句X=(A+B)*C Y=D(A+B)三元式序列(1)(+,A,B )(2)(*,(1),C )(3)(=,X,(2)(5)(,D,(4)(4)(+,A,B )(6)(=,Y,(5)间接三元式间接码表三元式表(1)(2)(3)(1)(4)(5)(1)(+,A,B )(2)(*,(1),C )(3)(=,X,(2)(4)(,D,(1)(5)(=,Y,(4)第7章 语法制导翻译技术和中间代码生成第25页,本讲稿共93页 树形表示 A*B+C*D+C*A*BD 末端结点表示一个运算对象,每一个内结点表示一个一元或二元运算符。树形表示是三元式的翻版(3)+(1)*(2)*CABD第7章 语法制导翻译技术和中间代码生成第26页,本讲稿共93页四元式四元式主要由四部分组成:(OP,arg1,arg2,result)其中OP是运算符,arg1,arg2分别是第一和第二两个运算对象。当OP是一目运算时,常常将运算对象定义为arg1。第7章 语法制导翻译技术和中间代码生成第27页,本讲稿共93页 四元式的第四个分量result是编译程序为存放中间运算结果而临时引进的变量,常称为临时变量,如Ti,也可以是用户自定义变量,如X。例如 X a*bc/d 的 四元式序列:(1)(*,a,b,T1 )(2)(/,c,d,T2 )(3)(+,T1,T2,T3 )(4)(=,T3,-,X )第7章 语法制导翻译技术和中间代码生成第28页,本讲稿共93页2.四元式之间的联系是通过临时变量实 现的,这样易于调整和变动四元式。1.四元式出现的顺序和语法成份的计值 顺序相一致。四元式的特点:3.便于优化处理。第7章 语法制导翻译技术和中间代码生成第29页,本讲稿共93页 编译系统中,有时将四元式表示成另一种更直观,更易理解的形式三地址代码或三地址语句。result:arg1 OP arg2 三地址语句三地址语句:语句中是三个量的赋值语句,每个量占一个地址。三地址代码形式定义为:第7章 语法制导翻译技术和中间代码生成第30页,本讲稿共93页例如 X a*bc/d 的 四元式序列:(1)(*,a,b,T1 )(2)(/,c,d,T2 )(3)(+,T1,T2,T3 )(4)(=,T3,-,X )相应的三地址语句序列为:(1)T1a*b(2)T2c/d(3)T3T1T2(4)XT3 第7章 语法制导翻译技术和中间代码生成第31页,本讲稿共93页例1.a+b*(c+d)的逆波兰式 a bc d+*+第7章 语法制导翻译技术和中间代码生成第32页,本讲稿共93页t1=a t2=c t3=t2+dt5=t1+t4 a+b*(c+d)的四元式表示 t4=b*t3 第7章 语法制导翻译技术和中间代码生成第33页,本讲稿共93页i(i/(i i)的逆波兰式 i(i/(i i)的四元式 t1=i i t2=i/t1t3=i t2i i i i /例2.第7章 语法制导翻译技术和中间代码生成第34页,本讲稿共93页4.采用自下而上的语法制导翻译法语义动作的设计(1)搞清楚源结构和目标结构(2)自下而上的语法制导翻译特点:栈顶形成句柄,归约时执行相应语义 动作(3)给出从源结构到目标结构的变换 方法第7章 语法制导翻译技术和中间代码生成第35页,本讲稿共93页例1.设文法及其相应的语义动作如下:SbTc print“1”Sa print“2”TR print“3”RR/S print“4”RS print“5”采用自下而上语法制导翻译,给出输入串bR/bTc/bSc/ac的翻译结果 第7章 语法制导翻译技术和中间代码生成第36页,本讲稿共93页分析:首先对输入串 bR/bTc/bSc/ac画出规范规约的语法树:ScTbRS/R/RS/RcTbaScTbRS再考虑归约时执行相应语义动作第7章 语法制导翻译技术和中间代码生成第37页,本讲稿共93页 SbTc print“1”Sa print“2”TR print“3”RR/S print“4”RS print“5”1 4翻译结果为:53142431第7章 语法制导翻译技术和中间代码生成cTbRS/R/RS/RcTbaScTbRSS第38页,本讲稿共93页 RR/S SbTc Sa TR RS 输出为:1 4 5 3 1 4 2 4 3 1输入是bR/bTc/bSc/ac给出相应语义动作(翻译方案)print“1”print“2”print“3”print“4”print“5”第7章 语法制导翻译技术和中间代码生成cTbRS/R/RS/RcTbaScTbRSS第39页,本讲稿共93页例2 简单算术表达式求值的语义描述例如,设有简单算术表达式的文法:EEE|E*E|(E)|digit1.E E(1)E(2)E.val E(1).val E(2).val 2.E E(1)*E(2)E.val E(1).val*E(2).val 3.E (E(1)E.val E(1).val 4.E digit E.val Lex.digit 第7章 语法制导翻译技术和中间代码生成第40页,本讲稿共93页例3 简单算术表达式翻译到四元式的 语义描述例如,设有简单算术表达式的文法:EEE|E*E|(E)|i第7章 语法制导翻译技术和中间代码生成第41页,本讲稿共93页E EEE*E(E)|i 源结构目标结构(1)T1a*b(2)T2c*d(3)T3T1T2 a*bc*d 第7章 语法制导翻译技术和中间代码生成第42页,本讲稿共93页语义函数 emit(Targ1 OP arg2)功能是生成一个三地址语句,并送到输出文件中。语义函数 newtemp()功能是产生一个新的临时变量名字,并回送新的临时变量名的整数码。如T1,T2等。第7章 语法制导翻译技术和中间代码生成第43页,本讲稿共93页 (2)不进符号表,临时变量单词值部 分用整数码表示。(1)送到符号表。对临时变量有两种不同的处理方法:第7章 语法制导翻译技术和中间代码生成第44页,本讲稿共93页语义过程 Lookup(i.name)功能是审查i.name是否出现在符号表中,在则返回其指针,否则返回NULL。语义变量 E.place 表示存放非终结符E值的变量名在符号表中的入口地址或临时变量名的整数码。第7章 语法制导翻译技术和中间代码生成第45页,本讲稿共93页 1.E E(1)E(2)2.E E(1)*E(2)E.place newtemp();emit(E.placeE(1).placeE(2).place)E.place newtemp();emit(E.placeE(1).place*E(2).place)第7章 语法制导翻译技术和中间代码生成第46页,本讲稿共93页3.E(E(1))E.place E(1).place;4.E i p Lookup(i.name);if (p!=NULL)E.place p;else error();第7章 语法制导翻译技术和中间代码生成第47页,本讲稿共93页90状态ACTIONGOTO+i*()#ES3S9S5S4S2S3S2S3S5S4S2S5S2S3r4r4r4r4r1r1r1r2r3r2r3r3r2r2r3123456781678acc2.为文法构造LR分析表如下图:第7章 语法制导翻译技术和中间代码生成第48页,本讲稿共93页3.算术表达式a+b*c翻译到三地址语句的过程:030#a01#E014#E+0143#E+baaa状态栈符号栈语义栈输入串a+b*c#+b*c#+b*c#b*c#*c#变量在符号表的入口用变量本身表示第7章 语法制导翻译技术和中间代码生成EEE|E*E|(E)|i第49页,本讲稿共93页*c#c#t1=b*c t2=a+t1 状态栈符号栈语义栈输入串014750147#E+E#E+E*014753#E+E*c014758#E+E*E0147#E+E01#Eab abcat1ababt2acc第7章 语法制导翻译技术和中间代码生成EEE|E*E|(E)|i第50页,本讲稿共93页布尔表达式到四元式的翻译一.布尔表达式的文法 计算逻辑值程序设计语言中布尔表达式有两个作用:用作控制语句中的条件式布尔表达式是由布尔算符(、和)施于布尔变量或关系表达式而成。第51页,本讲稿共93页布尔表达式到四元式的翻译 E E(1)E(2)E E(1)E(2)E E(1)E(E(1)E i(1)rop i(2)E true E false E i第52页,本讲稿共93页布尔表达式到四元式的翻译 二.布尔表达式的计值方法 1.如同计算算术表达式一样,逐步计算出各部分真、假值,最后计算出整个表达式的值。2.根据布尔运算的特殊性,采取某种优化措施,可避免计算整个表达式的值。第53页,本讲稿共93页布尔表达式到四元式的翻译 AB 解释成 AB 解释成 A 解释成if A then true else Bif A then B else falseif A then false else true 三.布尔表达式的翻译方法 1.同翻译算术表达式一样,翻译布尔表达式。第54页,本讲稿共93页布尔表达式到四元式的翻译 1.E E(1)E(2)E.place newtemp();emit(E.placeE(1).placeE(2).place)2.E E(1)E(2)E.place newtemp();emit(E.placeE(1).placeE(2).place)第55页,本讲稿共93页布尔表达式到四元式的翻译3.E(E(1)E.place E(1).place;4.E i(1)rop i(2)E.place newtemp();emit(if i(1).place rop.op i(2).place goto next+3);emit(E.place 0);emit(goto next+2);emit(E.place1);当前四元式的编号第56页,本讲稿共93页布尔表达式到四元式的翻译5.E true E.place newtemp();emit(E.place 1)E.place newtemp();emit(E.place 0)6.E false 或 E.place i.place;6.E i 第57页,本讲稿共93页布尔表达式到四元式的翻译例如布尔表达式 a=bc d 对应如下四元式序列:101 if a=b goto 104102 t1=0103 goto 105104 t1=1105 t2=c d106 t3=t1 t2 第58页,本讲稿共93页布尔表达式到四元式的翻译2.控制语句中布尔表达式的翻译条件语句的语法为:根据条件语句的语义,条件语句的代码结构为:if E then S(1)else S(2)E的代码S(1)的代码S(2)的代码Jump out out:真 假第59页,本讲稿共93页布尔表达式到四元式的翻译 E是布尔表达式,根据布尔运算的特殊性,布尔表达式的目标结构为:假E(1)的代码E(2)的代码真S(1)S(2)真假真E(1)的代码E(2)的代码假S(2)S(1)假真第60页,本讲稿共93页 (1)真出口和假出口:真出口表示布尔表达式E为真时控制流向的转移目标假出口表示布尔表达式E为假时控制流向的转移目标布尔表达式到四元式的翻译第61页,本讲稿共93页(2)作为条件转移的E,把E翻译成的代码 是一串条件转或无条件转的四元式对于E为 a rop b 的形式生成代码为:if a rop b goto 真出口 goto 假出口布尔表达式到四元式的翻译第62页,本讲稿共93页(q)例如语句 if a bc d then S(1)else S(2)的四元式为:100 if a b goto 真出口 101 goto 假出口102 if c E(1)V E(2)E(2)的真出口第63页,本讲稿共93页(q)例如语句 if a bc d then S(1)else S(2)的四元式为:100 if a b goto 104101 goto 102102 if c d goto 104 103 goto (p+1)104 (关于 S(1)的四元式)(p)goto (q)(p+1)(关于 S(2)的四元式)E(1)的真出口为104,E(1)的假出口为102E(2)的真出口为104,E(2)的假出口为(p+1)E的真出口为104,E的假出口为(p+1)布尔表达式到四元式的翻译第64页,本讲稿共93页布尔表达式到四元式的翻译布尔表达式的真、假出口不能在产生其四元式的同时得知。例如 E(1)的真出口为104需分析到S(1)时才能得知,因此需回填出口地址E.tr:记录表达式 E 所对应的四元式需回填真出口的四元式的地址所构成的链E.fa:记录表达式 E 所对应的四元式需回填假出口的四元式的地址所构成的链(3)设置两个语义变量:第65页,本讲稿共93页布尔表达式到四元式的翻译E(1).tr=100,E(1).fa=101E(2).tr=102,E(2).fa=103(q)例如语句 if a bc d then S(1)else S(2)的四元式为:100 if a b goto 真出口 101 goto 假出口102 if cd goto 真出口 103 goto 假出口104 (关于 S(1)的四元式)(p)goto (q)(p+1)(关于 S(2)的四元式)第66页,本讲稿共93页布尔表达式到四元式的翻译E.fa=103;E.tr=100和102所构成的链 E(1)E(2)归约E时,第67页,本讲稿共93页布尔表达式到四元式的翻译把以 p1,p2为链首的两条链合并为一,返回合并后的链首(4)链结函数和回填函数:merg(p1,p2):第68页,本讲稿共93页布尔表达式到四元式的翻译 merg(int p1,int p2)if p2=0 return(p1);else p=p2;while(四元式p的第四分量内容不为0)p=四元式p的第四分量内容;把p1填进四元式p的第四分量;return(p2);返回的链首应该是回填相同数字的四元式最后一个的编号第69页,本讲稿共93页布尔表达式到四元式的翻译r1 (0)q1 (r1)q2 (r2)p1 (q1)r2 (0)p2 (q2)p1第70页,本讲稿共93页布尔表达式到四元式的翻译 merg(int p1,int p2)if p2=0 return(p1);else p=p2;while(四元式p的第四分量内容不为0)p=四元式p的第四分量内容;把p1填进四元式p的第四分量;return(p2);100102102第71页,本讲稿共93页(q)例如语句 if a bc d then S(1)else S(2)的四元式为:100 if a b goto 0101 goto 102102 if c d goto 100 103 goto (p+1)104 (关于 S(1)的四元式)(p)goto (q)(p+1)(关于 S(2)的四元式)布尔表达式到四元式的翻译第72页,本讲稿共93页布尔表达式到四元式的翻译 bp(int p,int t):将 p 所链结的每个四元式的第四分量都回填 t;第73页,本讲稿共93页布尔表达式到四元式的翻译 bp(int p,int t)q=p;while(q!=0)r=四元式 q 的第四分量内容;把 t 填进四元式 q 的第四分量;q=r;1021041000 102100第74页,本讲稿共93页(q)例如语句 if a bc d then S(1)else S(2)的四元式为:100 if a b goto 104101 goto 102102 if c d goto 104 103 goto (p+1)104 (关于 S(1)的四元式)(p)goto (q)(p+1)(关于 S(2)的四元式)布尔表达式到四元式的翻译第75页,本讲稿共93页布尔表达式到四元式的翻译(5)为及时回填转移地址,使用语义变量 E.code 记录表达式E的第一个四元式语句序号。(6)定义语义变量 next 为四元式表指针。E(1).code=100E(2).code=102E.code=100第76页,本讲稿共93页布尔表达式到四元式的翻译布尔表达式语义动作的设计 1.E E(1)E(2)bp(E(1).fa,E(2).code);E.code=E(1).code;E.tr=merg(E(1).tr,E(2).tr);E.fa=E(2).fa;第77页,本讲稿共93页布尔表达式到四元式的翻译布尔表达式语义动作的设计 2.E E(1)E(2)bp(E(1).tr,E(2).code);E.code=E(1).code;E.tr=E(2).tr;E.fa=merg(E(1).fa,E(2).fa);第78页,本讲稿共93页布尔表达式语义动作的设计 3.E(E(1)E.code=E(1).code;E.tr=E(1).tr;E.fa=E(1).fa;布尔表达式到四元式的翻译第79页,本讲稿共93页布尔表达式语义动作的设计 4.E i(1)rop i(2)E.tr=next;E.code=next;E.fa=next+1;emit(if i(1).place rop.op i(2).place goto _);emit(goto _);布尔表达式到四元式的翻译第80页,本讲稿共93页布尔表达式语义动作的设计 5.E true E.tr=next;E.code=next;emit(goto _);布尔表达式到四元式的翻译第81页,本讲稿共93页布尔表达式到四元式的翻译布尔表达式语义动作的设计 6.E false E.fa=next;E.code=next;emit(goto _);第82页,本讲稿共93页布尔表达式到四元式的翻译布尔表达式语义动作的设计 5.E i E.tr=next;E.fa=next+1;E.code=next;emit(if i.place goto-);emit(goto _);5.E true 6.E false第83页,本讲稿共93页布尔表达式到四元式的翻译例如布尔表达式 a bc d 的翻译过程如下:第84页,本讲稿共93页布尔表达式到四元式的翻译a bc d E(1)c d 100 if a b goto 0101 goto 0 E(1).tr=100;E(1).fa=101;E(1).code=100;E(1)E(2)102 if c d goto 0103 goto 0 E(2).tr=102;E(2).fa=103;E(2).code=102;第85页,本讲稿共93页布尔表达式到四元式的翻译 E bp(E(1).fa,E(2).code)=bp(101,102);E.fa=E(2).fa=103;E.tr=merg(E(1).tr,E(2).tr)=merg(100,102)=102;E.code=E(1).code=100100 if a b goto 0101 goto 0102 if c d goto 100103 goto 0102E(1)E(2)归约为E第86页,本讲稿共93页布尔表达式到四元式的翻译102 if c d goto 100103 goto 0100 if a b goto 0101 goto 102布尔表达式 a bc d E.tr=102E.fa=103第87页,本讲稿共93页简单说明语句的翻译 程序设计语言中,程序中的每个名字(变量名)都必须在使用前进行说明。说明语句的功能就是告知编译程序每一个变量的类型信息。翻译说明语句时,设计的语义动作应将变量的类型信息填入符号表中。第88页,本讲稿共93页简单说明语句的翻译简单说明语句文法 ,id|idD int real 第89页,本讲稿共93页简单说明语句的翻译 用上述文法的规则式进行归约时,按照自下而上制导翻译,首先将所有名字id归约为一个名字表namelist后,才能将namelist中所有名字的性质登录在符号表里。这样必须用一个队列(或栈)来保存namelist中的所有名字。第90页,本讲稿共93页简单说明语句的翻译 我们希望在扫描过程中,每遇到一个名字,就把它及其性质及时登录在符号表中。归约过程中涉及到这些名字及其性质时,就可以直接到符号表中进行查找,而无需占用额外空间保存namelist 中名字的信息第91页,本讲稿共93页简单说明语句的翻译文法改写:DD(1),idint id real id(1)函数FILL(id,A)的功能是把名字 id和性质A登录在符号表中。对文法设计语义动作如下:(2)设置非终结符D的语义变量D.ATT,记录说明语句所规定的相关名字性质。第92页,本讲稿共93页简单说明语句的翻译(1)Dint id(2)Dreal id(3)DD(1),id FILL(id,int);D.ATTint FILL(id,real);D.ATT=real FILL(id,D(1).ATT);D.ATT=D(1).ATT 第93页,本讲稿共93页