引言
这个标题是俗点,但是,别误会,不是老生常谈。
都说数组和指针的区别啊,怎么定义指针啊,怎么定义数组啊,给你两个小程序让你说打印出来的是什么呀,等等之类的题目。本小节不打算说这些。整一个小例子,然后分别看一下数组和指针的汇编结果,自己体会一下。
数组VS指针(Arrays versus Pointers),开始......
2.1 C code
同样的功能,两段小代码:
clear1(int array[], int size)
{
int i;
for (i = 0; i < size; i += 1)
array[i] = 0;
}
clear2(int *array, int size)
{
int*p;
for (p = &array[0]; p < &array[size]; p = p + 1)
*p = 0;
}
2.2 clear1的MIPS汇编
需要说明一下,不考虑过程调用的汇编,保存SP啊之类的动作,我们主要关注循环本身。
假设array,size两个参数用$a0,$a1,i用$t0,三个寄存器。
1》for循环第一部分,i初始化
move $t0,$zero # i = 0 (register $t0 = 0)
2》为了把array[i]清零,我们要先得到他的地址,即i*4
loop1:sll $t1,$t0,2 # $t1 = i * 4
3》然后加上数组的起始地址,这个起始地址放在寄存器中
add $t2,$a0,$t1 # $t2 = address of array[i]
4》然后将这个地址清零
sw $zero, 0($t2) # array[i] = 0
5》i自增
addi $t0,$t0,1 # i = i + 1
6》最后循环条件判断
slt $t3,$t0,$a1 # $t3 = (i < size)
bne $t3,$zero,loop1 # if (i < size) go to loop1
咱们把上面的代码拼起来就是:
move $t0,$zero # i = 0
loop1:sll $t1,$t0,2 # $t1 = i * 4
add $t2,$a0,$t1 # $t2 = address of array[i]
sw $zero, 0($t2) # array[i] = 0
addi $t0,$t0,1 # i = i + 1
slt $t3,$t0,$a1 # $t3 = (i < size)
bne $t3,$zero,loop1# if (i < size) go to loop1
2.3 clear2的MIPS汇编
参数和clear1一样,p用$t0
1》先给指针赋值为数组的第一个元素的地址
move $t0,$a0 # p = address of array[0]
2》for循环开始,将0放入p
loop2:sw $zero,0($t0) # Memory[p] = 0
3》p自增4
addi $t0,$t0,4 # p = p + 4
4》循环判断之计算array最末元素的地址
add $t1,$a1,$a1 # $t1 = size * 2
add $t1,$t1,$t1 # $t1 = size * 4
5》然后将结果加到数组的开始地址
add $t2,$a0,$t1 # $t2 = address of array[size]
6》循环判断之p是否小于array最后一个元素的地址
slt $t3,$t0,$t2 # $t3 = (p<&array[size])
bne $t3,$zero,loop2 # if (p<&array[size]) go to loop2
再把上面的代码拼起来:
move $t0,$a0 # p = address of array[0]
loop2:sw$zero,0($t0) # Memory[p] = 0
addi $t0,$t0,4 # p = p + 4
add $t1,$a1,$a1 # $t1 = size * 2
add $t1,$t1,$t1 # $t1 = size * 4
add $t2,$a0,$t1 # $t2 = address of array[size]
slt $t3,$t0,$t2 # $t3 = (p<&array[size])
bne $t3,$zero,loop2 # if (p<&array[size]) go to loop2
再优化一下,将每次计算数组末端地址移到循环外边
move $t0,$a0 # p = address of array[0]
sll $t1,$a1,2 # $t1 = size * 4
add $t2,$a0,$t1 # $t2 = address of array[size]
loop2:sw $zero,0($t0) # Memory[p] = 0
addi $t0,$t0,4 # p = p + 4
slt $t3,$t0,$t2 # $t3 = (p<&array[size])
bne $t3,$zero,loop2 # if (p<&array[size]) go to loop2
2.4 放在一起比较一下
2.5 比较结果
1》左边的版本循环中必须有乘法运算,右面的版本指针直接加4。
2》数组方式循环体是7条指令,指针方式循环体是4条。
2.6 小结
以后尽量用指针吧。