MIPS中基于指针的数组访问

时间:2010-08-24 08:28:52

标签: assembly mips computer-architecture

MIPS中基于指针的数组访问是什么意思?

2 个答案:

答案 0 :(得分:1)

“基于指针的阵列访问”还有其他可能的含义或含义:

您可能有一个指向数组的指针,而不是固定地址的数组。实际上,在C / C ++中,“指向数组的指针”实际上通常只是指向数组第一个元素的指针。基本上,你有一个数组作为函数的参数,或指向一个结构或类的成员的数组的指针:

 void Foo(char a[]); 
   /*or*/ void Foo(char *a);
 struct Bar {  int offset4bytes; char* a; };

通常,当您想要使用这样的数组时,数组的基址将被加载到寄存器中。

现在说你要访问这样一个数组的元素i,

 char tmp = a[i];

假设r1包含数组地址。 (实际上,可能是由调用约定指定的函数参数的不同寄存器。无论编译器发现其他代码可用。)

假设我住在登记册r2。

而且,为了更好的衡量,让tmp为r3。

在某些指令集上,例如Intel x86,有一种看起来像

的寻址模式
  MOV r3, (r2,r1)4

即。寻址模式可以添加两个寄存器和一个偏移量(我在结构示例中任意添加了一个字段,以便我可以显示这个)。

哎呀,他们甚至可以扩展其中一个寄存器,即所谓的索引寄存器:

  MOV r3, (r2*2,r1)4

或者我喜欢写它

  r3 := load( Memory[r2<<1+r1+4]
但是,MIPS没有这种base + _index * scale + offset寻址模式。大多数MIPS存储器访问指令仅限于寄存器+偏移。因此,对于MIPS,您可能必须执行

  ADDU r10, r1,r1    ; dest on left. r10 = 2*r1
  ADDU r11, r2,r10  
  LB r3,(r11)4

即。您可能需要添加额外的RISC指令来完成x86在具有复杂寻址模式的一条CISC指令中所执行的操作。然而,这种寻址并不常见,通常可以避免这种情况。


此外,即使只是在固定地址寻址阵列,也可能需要MIPS中的额外指令。 x86指令可以具有32位内存偏移量 - 在这种情况下实际上可能是数组的绝对地址。 MIPS指令限于16位偏移 - MIPS指令是固定宽度,32位宽。因此,即使访问固定地址的数组,也可能需要单独的指令,通常是将地址的高位加载到寄存器中。

还有更多 - MIPS有更新的指令,如LUXC1,具有reg + reg寻址模式。但不是缩放索引,也没有第三个偏移组件。


由于这种受限制的寻址模式,天真编译器为lop生成的代码,例如

   for(int i=0;i<N;i++) {
      this->a[i] = 0;
   }
如果循环包含上面提到的多指令序列,则

效率低下。

诸如

之类的循环
   for(char *p=this->a;p<&(this->a[N]);p++) {
      *p=0;
   }

或等同于

   for(char *p=this->a;p<this->a+N;p++) {
      *p;
   }

甚至有时候

   for(i=-N,*p=this->a;i<0;i++,p++) {
      *p=0;
   }

可能更有效,因为,例如在前两个中只有一条指令来做商店。 (如果遍历几个数组,最后一个通常只会获胜。

现在,在一个简单的例子中,任何好的编译器都会为您做这个优化。但有时编译器更喜欢这种基于指针的访问。

答案 1 :(得分:0)

您将有一个指向值数组开头的指针。要遍历数组,您将使用指针算法(通常添加/减去1,2或4)来将指针前进到数组中的下一个/上一个元素。