60

ARMアーキテクチャにとって基本的__asm__ __volatile__ ()に何をし、何を意味するのでしょうか?"memory"

4

4 に答える 4

93
asm volatile("" ::: "memory");

コンパイラ レベルのメモリ バリアを作成し、オプティマイザがバリアを越えてメモリ アクセスの順序を変更しないように強制します。

たとえば、特定の順序でアドレスにアクセスする必要がある場合 (おそらく、そのメモリ領域がメモリではなく別のデバイスによって実際にバックアップされているため)、これをコンパイラに伝えることができる必要があります。そうしないと、ステップが最適化されるだけです。効率のために。

このシナリオでは、アドレスの値をインクリメントし、何かを読み取り、隣接するアドレスの別の値をインクリメントする必要があると仮定します。

int c(int *d, int *e) {
        int r;
        d[0] += 1;
        r = e[0];
        d[1] += 1;
        return r;
}

問題は、コンパイラ (gccこの場合) がメモリ アクセスを再配置して、必要に応じてパフォーマンスを向上させることができることです ( -O)。おそらく、以下のような一連の指示につながります。

00000000 <c>:
   0:   4603        mov r3, r0
   2:   c805        ldmia   r0, {r0, r2}
   4:   3001        adds    r0, #1
   6:   3201        adds    r2, #1
   8:   6018        str r0, [r3, #0]
   a:   6808        ldr r0, [r1, #0]
   c:   605a        str r2, [r3, #4]
   e:   4770        bx  lr

d[0]との上記の値d[1]は同時にロードされます。これが回避したいものであると仮定して、コンパイラにメモリ アクセスの順序を変更しないように指示する必要がありますasm volatile("" ::: "memory")

int c(int *d, int *e) {
        int r;
        d[0] += 1;
        r = e[0];
        asm volatile("" ::: "memory");
        d[1] += 1;
        return r;
}

したがって、必要に応じて命令シーケンスを取得できます。

00000000 <c>:
   0:   6802        ldr r2, [r0, #0]
   2:   4603        mov r3, r0
   4:   3201        adds    r2, #1
   6:   6002        str r2, [r0, #0]
   8:   6808        ldr r0, [r1, #0]
   a:   685a        ldr r2, [r3, #4]
   c:   3201        adds    r2, #1
   e:   605a        str r2, [r3, #4]
  10:   4770        bx  lr
  12:   bf00        nop

これは、メモリをフラッシュしたり、ロードやストアが完了するのを待ったりするための追加のハードウェアレベルの命令を配置しないため、コンパイラがメモリアクセスを並べ替えるのを回避するためのコンパイル時のメモリバリアのみであることに注意してください。CPU にアーキテクチャ機能があり、メモリ アドレスがor ( refnormal )の代わりに型にある場合、CPU はメモリ アクセスを並べ替えることができます。strongly ordereddevice

于 2013-02-20T15:20:16.457 に答える
27

このシーケンスは、Udo が参照した記事に記載されているように、コンパイラのメモリ アクセス スケジューリング バリアです。これは GCC 固有のものです。他のコンパイラには、それらを記述する他の方法があり、そのうちのいくつかは、より明示的な (そして難解ではない) ステートメントを使用しています。

__asm__は、アセンブリ言語ステートメントを C コード内にネストして入力できるようにする gcc 拡張機能です。ここでは、コンパイラが特定の種類の最適化を実行するのを防ぐ副作用を指定できるというプロパティのために使用されます (この場合、誤った結果が生成される可能性があります)。コード)。

__volatile__asmステートメント自体が他の volatile アクセスと並べ替えられないようにする必要があります (C 言語での保証)。

memoryは、GCC への命令であり、インライン asm シーケンスにはグローバル メモリに副作用があるため、ローカル変数への影響だけでなく、考慮に入れる必要があることを (一種の) 伝えます。

于 2013-02-19T07:53:06.307 に答える
9

意味は次のように説明されています。

http://en.wikipedia.org/wiki/Memory_ordering

基本的に、アセンブリ コードが期待どおりの場所で実行されることを意味します。これは、その周りの命令を並べ替えないようにコンパイラに指示します。これは、このコードが実行される前にコーディングされたものであり、後でコーディングされたものは後で実行されます。

于 2013-02-19T07:17:05.077 に答える