9

最新のプロセッサーでは、メモリーからレジスターをロードしてから、インデックス・ポインターを目的の値で事後変更することができます。たとえば、組み込みプロセッサでは、これは次のように行われます。

ldr r0, [r1], +12

つまり、r1 が指す値を r0 にロードし、r1 を 12 ずつ増やします。

r0 = [r1]
r1 = r1 + 12

C 言語では、ポインター演算を使用して、ポインターを使用して値を代入し、ポインターを 1 進めることができます。

char i, *p, a[3]={10, 20, 30};

p = &(a[0]);
i = *p++;
// now i==10 and p==&(a[1]).

ポインターを 1 以外のオフセットで事後変更しながら逆参照する方法を探しています。これは C で可能ですか?同様の asm 命令にうまくマップされますか?

ご了承ください:

i = *p+=2;

ポインターを変更せずに a[0] の値を増やします。

i = *(p+=2);

はポインターを事前に変更するため、この場合はi==30.

4

4 に答える 4

7
  1. はい、これは可能です。

  2. あなたはそれを実現するために奇妙なポインタ計算をするべきではありません。

  3. 最適化設定だけでなく、GCCバックエンドはGCCにそのような機能があることを通知する必要があります(つまり、GCC自体がコンパイルされているとき)。この知識に基づいて、GCCは関連するシーケンスを1つの命令に自動的に結合します。

つまり、バックエンドが正しく記述されている場合は、次のようになります。

 a = *ptr;
 ptr += SOME_CONST;

単一の変更後の命令になるはずです。

バックエンドを作成するときにこれを正しく設定するにはどうすればよいですか?(あなたの友好的な近所のGCCバックエンド開発者にあなたのためにそれをするように頼んでください):

GCCバックエンドが呼び出された場合foo

  1. GCCソースツリーでは、バックエンドの説明とフックはにありますgcc/config/foo/
  2. そこにあるファイル(GCCと一緒にコンパイルされる)の中には、通常、マシンの機能を説明foo.hする多くの内容を含むヘッダーがあります。#defines
  3. GCCは、ポストインクリメントをサポートするバックエンドがマクロHAVE_POST_INCREMENTを定義してtrueと評価し、ポストモディファイをサポートする場合はマクロHAVE_POST_MODIFY_DISPをtrueと定義することを想定しています。(post-increment => ptr++、post-modify => ptr += CONST)。たぶん、他にも処理すべきことがいくつかあります。

プロセッサのバックエンドがこれを正しく行っていると仮定して、上記の変更後のシーケンスを含むコードをコンパイルしたときに何が起こるかに移りましょう。

このカテゴリに分類される命令ペアを通過し、それらを組み合わせる特定のGCC最適化パスがあります。そのパスのソースはここにあり、GCCが何をするのか、そしてそれをどのように実行するのかについてのかなり明確な説明があります。

しかし、これは最終的に、GCCユーザーとしての管理下にはありません。GCCバックエンドを作成したのは開発者の管理下にあります。最も賛成のコメントが言うように、あなたがしなければならないのは:

 a = *ptr;
 ptr += SOME_CONST;
于 2012-06-26T14:45:01.373 に答える
3

この方法で実行できますが、実行しないでください。

i = *((p += 2) - 2);

(厳密には事後変更ではありません)

于 2012-06-26T10:56:20.743 に答える
1
i = *p; 
p = (unsigned char*)p + 12;

ここで、iは任意の種類の型であり、pはその型へのポインタです。

型キャストを追加しない場合、ポインターのインクリメントはsize ==のステップで実行されますsizeof(*p)。これにより、コードは投稿されたアセンブラーとは完全に異なります。

たとえば、pがint*32ビットシステム上にある場合、型キャストなしでポインタは4*12バイトインクリメントされます。

于 2012-06-26T13:53:42.637 に答える
1

私が考えることができる最も近い:

#define POST_INDEX_ASSIGN(lhs, ptr, index)  (lhs = *(ptr), (ptr) += (index))

POST_INDEX_ASSIGN(i, p, 2);
于 2012-06-26T11:59:54.090 に答える