ARMアーキテクチャにとって基本的__asm__ __volatile__ ()
に何をし、何を意味するのでしょうか?"memory"
4 に答える
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 ordered
device
このシーケンスは、Udo が参照した記事に記載されているように、コンパイラのメモリ アクセス スケジューリング バリアです。これは GCC 固有のものです。他のコンパイラには、それらを記述する他の方法があり、そのうちのいくつかは、より明示的な (そして難解ではない) ステートメントを使用しています。
__asm__
は、アセンブリ言語ステートメントを C コード内にネストして入力できるようにする gcc 拡張機能です。ここでは、コンパイラが特定の種類の最適化を実行するのを防ぐ副作用を指定できるというプロパティのために使用されます (この場合、誤った結果が生成される可能性があります)。コード)。
__volatile__
asmステートメント自体が他の volatile アクセスと並べ替えられないようにする必要があります (C 言語での保証)。
memory
は、GCC への命令であり、インライン asm シーケンスにはグローバル メモリに副作用があるため、ローカル変数への影響だけでなく、考慮に入れる必要があることを (一種の) 伝えます。
意味は次のように説明されています。
http://en.wikipedia.org/wiki/Memory_ordering
基本的に、アセンブリ コードが期待どおりの場所で実行されることを意味します。これは、その周りの命令を並べ替えないようにコンパイラに指示します。これは、このコードが実行される前にコーディングされたものであり、後でコーディングされたものは後で実行されます。