5.7含数组元素的算术表达式及 赋值语句的翻译 在5.4节中,我们已讨论了仅含简单变量的算术表达式和 赋值语句的翻译问题。现在,我们进一步讨论含有数 组元素(下标变量)的算术表达式和赋值语句的翻译。 ·在编译过程中,下标变量的处理可以有两种方案: 1.在语义分析阶段进行即在此阶段中,根据下标变量在赋值 语句中的作用,产生相应的中间代码; 2.在目标代码生成阶段进行即在语义分析阶段,把源程序中 下标变量的有关信息保留在中间代码中,待生成目标代码时, 再对它们产生相应的目标指令。 。 本课中我们将采取前一种方式。因为它有利于进行代 码的优化,以便产生高效的目标代码。特别是当数组 元素出现在循环中时,代码优化的效果尤为显著
5.7 含数组元素的算术表达式及 赋值语句的翻译 • 在5.4节中,我们已讨论了仅含简单变量的算术表达式和 赋值语句的翻译问题。现在,我们进一步讨论含有数 组元素(下标变量)的算术表达式和赋值语句的翻译。 • 在编译过程中,下标变量的处理可以有两种方案: 1.在语义分析阶段进行 即在此阶段中,根据下标变量在赋值 语句中的作用,产生相应的中间代码; 2.在目标代码生成阶段进行 即在语义分析阶段,把源程序中 下标变量的有关信息保留在中间代码中,待生成目标代码时, 再对它们产生相应的目标指令。 • 本课中我们将采取前一种方式。因为它有利于进行代 码的优化,以便产生高效的目标代码。特别是当数组 元素出现在循环中时,代码优化的效果尤为显著
变量的左值和右值 ,一般说来,源程序中的每个变量(包括简单变量和下标 变量)除它们的名字、类型等属性外,还有两种重要的 属性: ()它们在数据区所分配的存储单元地址(称为变量的左值) (2)在程序运行时存放在相应单元中的值(称为变量的右值) ·一个变量出现在源程序中的环境不同,则它所代表的特 征也就不同。例如,赋值语句A:=B的语义为:把变量 B的值(即B的数据单元的内容,也即B的右值)送入A所代 表的数据单元(A的左值)中去
变量的左值和右值 • 一般说来,源程序中的每个变量(包括简单变量和下标 变量)除它们的名字、类型等属性外,还有两种重要的 属性: (1)它们在数据区所分配的存储单元地址(称为变量的左值) (2)在程序运行时存放在相应单元中的值(称为变量的右值) • 一个变量出现在源程序中的环境不同,则它所代表的特 征也就不同。例如,赋值语句 A:=B的语义为:把变量 B的值(即B的数据单元的内容,也即B的右值)送入A所代 表的数据单元(A的左值)中去
变量的左值和右值(续) 。) 对于含有下标变量的赋值语句,无论它出现在赋 值号的左侧或右侧,在进行翻译时都要计算它的 地址。 出现在赋值语句右部表达式的下标变量,应同时具 有左值和右值;出现在左部的下标变量,可只具 有左值,但出现在左部下标变量的下标表达式中 的下标变量,仍具有左值和右值。 。】 对下标变量进行翻译的核心是计算它们的地址。 因此,我们将首先讨论数组元素的地址计算方法 及数组元素引用的中间代码形式,然后再介绍含 有数组元素的赋值语句的语法制导翻译方法
变量的左值和右值(续) • 对于含有下标变量的赋值语句,无论它出现在赋 值号的左侧或右侧,在进行翻译时都要计算它的 地址。 • 出现在赋值语句右部表达式的下标变量,应同时具 有左值和右值;出现在左部的下标变量,可只具 有左值,但出现在左部下标变量的下标表达式中 的下标变量,仍具有左值和右值。 • 对下标变量进行翻译的核心是计算它们的地址。 因此,我们将首先讨论数组元素的地址计算方法 及数组元素引用的中间代码形式,然后再介绍含 有数组元素的赋值语句的语法制导翻译方法
5.7.1下标变量地址的计算 数组元素在计算机中是按某种顺序存储的,即不管 数组是几维的,一般总是把它映射为存储空间的一 个向量, ·数组的存储通常有两种方式:(1)按行存放,如 PASCAL、C等语言;(2)按列存放,如FORTRAN 语言 。1 程序中可以用下标变量的形式访问一数组的任意 元素。因此,在编译时,就必须计算相应的下标变量 的地址或该变量在数组存储映象中的位置。 ·显然,计算地址的方法与数组的存储方式有关
5.7.1 下标变量地址的计算 • 数组元素在计算机中是按某种顺序存储的,即不管 数组是几维的,一般总是把它映射为存储空间的一 个向量. • 数组的存储通常有两种方式:(1)按行存放,如 PASCAL、C等语言; (2)按列存放,如FORTRAN 语言. • 程序中可以用下标变量的形式访问一数组的任意 元素。因此,在编译时,就必须计算相应的下标变量 的地址或该变量在数组存储映象中的位置。 • 显然,计算地址的方法与数组的存储方式有关
下标变量[i,i2,,in]的地址计算 公式 。 假定数组按行存放,每个数组元素占用一个机器 字,并假定计算机是按字编址的,则对于用 VAR A:ARRAYL,12..u...u OF REAL 所说明的n维PASCAL数组A,下标变量A[i,i2,,in] 的地址计算公式为 LOC (A[ipiz,...,in])=LOC (A[L,l2,...,n])+ 24-1e4+g k=i+ (5.18)
下标变量A[i1 ,i2 ,…,in ]的地址计算 公式 • 假定数组按行存放,每个数组元素占用一个机器 字,并假定计算机是按字编址的,则对于用 VAR A: ARRAY[l1 ..u1 , l2 ..u2 , …, ln ..un ] OF REAL; 所说明的n维PASCAL数组A,下标变量A[i1 ,i2 ,…,in] 的地址计算公式为 LOC(A[i1 ,i2 ,…,in])=LOC(A[l1 ,l2 ,…,ln])+ (5.18) ( ) ( 1) ( ) 1 1 1 n n n k j k k n j j j i − l u − l + + i − l = + − =
下标变量A[i,i,in]的地扯计算 公式 如果我们用a表示数组A的首地址 LOC(A[L,l2,,In]),用dk表示数组第k维的 下标界差,则上式可写成: LOC(A[ipi2...n)= a+∑6-,)几d.+n-,) k=+】 或 LOC(Aliniz)=-IId+)+d
下标变量A[i1 ,i2 ,…,in ]的地址计算 公式 • 如果我们用a表示数组A的首地址 LOC(A[l1 ,l2 ,…,ln ]),用dk表示数组第k维的 下标界差,则上式可写成: LOC(A[i1 ,i2 ,…,in ])= − = = + + − + − 1 1 1 ( ) ( ) n j n k j j j k n n a i l d i l 或 LOC(A[i1 ,i2 ,…,in ])= ( ) ( ) 1 1 1 1 1 1 − = = + − = = + − + + + n j n k j j k n n j n k j j k n a l d l i d i
地址计算公式的改写 若仅考虑静态数组,则ld均为常量,这时 前页中的等式右侧第一个括号内的值为一 常量,在编译时己可计算出。因此,公式 可改写为 LOC(A[i,i2,...,in])=CONSTPART+VARPART (5.21) 其中,CONSTPART=a-C,且 c-21,d+l. VARPART-i,IId.+i i= k=i+
地址计算公式的改写 若仅考虑静态数组,则l k , uk , dk均为常量,这时 前页中的等式右侧第一个括号内的值为一 常量,在编译时已可计算出。因此,公式 可改写为 LOC(A[i1 ,i2 ,…,in])=CONSTPART+VARPART (5.21) 其中,CONSTPART=a – C,且 − = = + = + 1 1 1 n j n k j j k n C l d l − = = + = + 1 1 1 n j n k j j k n VARPART i d i
数组的内情向量 ·为了按上述公式计算数组元素的地址,在编译程 序对数组说明进行语义处理时,须把数组的类型 ype、雅数n、各雅的业、下得lk、u,等有关信息记 录下来。 ·此外,如果数组是常界的,还可将各雅的器差d以 及上面公式中的常量C记录下来. 为了便于引用,通常是把上述信息存放于数组相 应的“肉情向量”之中.对数组内情向量的访问, 可通过数组在符号表中相应登记项的ADDR域以 间接寻址方式进行(即将其ADDR域作为指针用 于存放内情向量的首地址)
数组的内情向量 • 为了按上述公式计算数组元素的地址,在编译程 序对数组说明进行语义处理时,须把数组的类型 type、维数n、各维的上、下界lk、uk等有关信息记 录下来。 • 此外,如果数组是常界的,还可将各维的界差dk以 及上面公式中的常量C记录下来. • 为了便于引用,通常是把上述信息存放于数组相 应的“内情向量”之中.对数组内情向量的访问, 可通过数组在符号表中相应登记项的ADDR域以 间接寻址方式进行(即将其ADDR域作为指针用 于存放内情向量的首地址)
数组的内情向量 对于一个常界数组而言,有了 上述内情向量之后,在计算 W1 d A[i,i2,in]的地址时,只须 根据相应的下标i,i2,,in以 及各维界差d,产生计算 VARPART的中间代码,并 从内情向量中查出a和C,产 生计算的中间代码即可。 为简单起见,在下面的讨论 中,我们假定数组各维的下 界均为1
数组的内情向量 对于一个常界数组而言,有了 上述内情向量之后,在计算 A[i1 ,i2 ,…,in]的地址时,只须 根据相应的下标i1 ,i2 ,…,in以 及各维界差dk,产生计算 VARPART的中间代码,并 从内情向量中查出a和C,产 生计算的中间代码即可。 为简单起见,在下面的讨论 中,我们假定数组各维的下 界均为1 l 1 u1 d1 l 2 u2 d2 ... ... ... l n un dn n C a
l=I时计算A[i,i,,in]的地址的 公式 A[ij,i2....]=C_PART+V_PAR CONSTPART=a-C, a=LOC(A[1,l,.,1]), 2d.+1 j=1k=j+1 VARPART=】 ,d,+ dk =uk j=1k=j+1 为了提高效率,我们可将其按霍纳格式进行改写 C=(.(d2+l)*d3+l)*d4.+)*dn+l (5.24) VARPART=(..((i*d2+iz)*d3+...+in)*dntin (5.25)
l k=1时计算A[i1 ,i2 ,…,in ]的地址的 公式 A[i1 ,i2 ,…,in]=C_PART+V_PAR T CONSTPART=a-C, a=LOC(A[1,1,…,1]), − = = + = + 1 1 1 1 n j n k j C dk − = = + = + 1 1 1 n j n k j j k n VARPART i d i dk = uk 为了提高效率,我们可将其按霍纳格式进行改写 C=(…((d2+1)*d3+1)*d4…+1)*dn+1 (5.24) VARPART= (…((i1*d2+i2 )*d3+…+in-1 )*dn+in (5.25)