3

MIPSでのポインタベースの配列アクセスとはどういう意味ですか?

4

2 に答える 2

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

つまり、アドレッシング モードは 2 つのレジスタと 1 つのオフセットを追加できます (これを示すために、構造体の例に任意にフィールドを追加しました)。

一体、レジスタの 1 つ、いわゆるインデックス レジスタをスケーリングすることさえできます。

  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

つまり、x86 が複雑なアドレッシング モードで 1 つの CISC 命令で行うことを達成するために、追加の RISC 命令を追加する必要がある場合があります。ただし、このようなアドレス指定は一般的ではなく、避けられることがよくあります。


さらに、固定アドレスで配列をアドレス指定するだけでも、MIPS で追加の命令が必要になる場合があります。x86 命令は 32 ビットのメモリ オフセットを持つことができます。この場合、これは実際には配列の絶対アドレスである可能性があります。MIPS 命令は 16 ビット オフセットに制限されています。MIPS 命令は固定幅で、32 ビット幅です。したがって、固定アドレスの配列にアクセスする場合でも、通常はアドレスの上位ビットをレジスタにロードするために別の命令が必要になる場合があります。

その他 - MIPS には、reg+reg アドレッシング モードを持つ LUXC1 などの新しい命令があります。ただし、スケーリングされたインデックスではなく、3 番目のオフセット コンポーネントはありません。


このようにアドレッシング モードが制限されているため、単純なコンパイラが次のような 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;
   }

たとえば、最初の 2 つはストアを実行する命令が 1 つしかないためです。(最後は通常、複数の配列をトラバースする場合にのみ勝利します。

さて、簡単な例では、優れたコンパイラがこの最適化を行ってくれます。ただし、コンパイラがそのようなポインターベースのアクセスを好む場合があります。

于 2012-05-02T01:05:59.623 に答える
0

値の配列の先頭を指すポインターがあります。配列をトラバースするには、ポインター演算 (通常は 1、2、または 4 の加算/減算) を使用して、ポインターを配列内の次/前の要素に進めます。

于 2011-02-04T15:35:38.427 に答える