4.4.4 数组的分配和访问

4.4.4 数组的分配和访问

数组是将同类基本数据类型的数据组合而成的。因此在指令级这个层面上,数组不可能存放在立即数或寄存器中,而是分配在存储器中。对于数组的访问和处理,编译器最重要的是找到一种简便的数组元素地址的计算方法。

1.数组元素在内存的存放和访问

一维数组的定义如下:

存储类型 数据类型 数组名[元素个数]

例如,定义一个具有4个元素的静态存储型short数据类型数组A,可以写成“static short A[4];”,我们知道,第i(0≤i≤3)个元素的地址计算公式为&A[0]+2∗i。那么在指令中如何取数组的第i个元素呢?

假定数组A 的首地址存放在EDX 中,i存放在ECX 中,现要将A[i]取到AX 中,则所用的汇编指令是:

其中,ecx为变址(索引)寄存器,在循环体中增量。表4.7给出了数组定义及其内存存放情况示例。

表4.7 数组定义及其内存存放情况示例

2.分配在静态区的数组的初始化和访问

数组的存储类型可以为静态存储型(static)、外部存储型(extern)、自动存储型(auto)。其中,只有auto型的数组被分配在栈中,其他的存储类型都被分配在静态数据区。

分配在静态数据区的数组在编译、链接时就可以确定在静态区中的数组的地址,所以在编译、链接阶段就可将数组首地址和数组变量建立联系。例如:

ary是静态存储型的数组,因此是在静态区分配的数组,链接后,ary在可执行目标文件的数据段中分配了空间:

此时,buf=&buf[0]=0x08048908

编译器通常将其先存放到寄存器(如EDX)中,假定i被分配在ecx中,sum 被分配在eax中,则“sum+=buf[i];”可用以下指令实现:

3.数组与指针

在C语言中,指针与数组的关系非常密切。在指针变量目标数据类型与数组类型相同的前提下,指针变量可以指向数组或数组中任意元素。

以下两个程序段功能完全相同,都是使ptr指向数组a的第0个元素a[0]。a的值就是其首地址,即a=&a[0],因而a=ptr,从而有&a[i]=ptr+i=a+i以及a[i]=ptr[i]=∗(ptr+i)=∗(a+i)。

假定数组A 的首地址sa在ecx中,i在edx中,int型占4个字节,表达式结果在eax中,表4.8给出了各表达式的计算方式以及汇编代码。序号为2、3、6和7对应汇编指令都需访存,指令中源操作数的寻址方式分别是“基址”“基址加比例变址”“基址加比例变址”和“基址加比例变址加位移”的方式,因为数组元素的类型为int型,故比例因子为4。

表4.8 数组元素及指针变量的表达式计算示例