C および C++ コードのインラインアセンブラおよびレジスタアクセス

インラインアセンブラでは、ARM プロセッサの物理レジスタに直接アクセスできません。ARM レジスタの名前がインラインアセンブラ命令のオペラドとして使用されている場合、その名前は物理 ARM レジスタへの参照ではなく、同じ名前の変数への参照となります(変数は、仮想レジスタとし考えることができます)。

コンパイラは、最適化とコード生成の間に、必要に応じて物理レジスタの変数を宣言します。ただし、アセンブルされるコード内で使用される物レジスタが、命令内で指定されている物理レジスタと異なる場合や、スタックに格納されている場合があります。物理レジスタを表す変数を、常の C または C++ 変数として明示的に宣言できます。コンパイラは、レジスタ R0R12 および r0r12 を、使用されるかどうかに関係なく、auto signed int ローカル変数として暗黙的に宣言します。これらを別のデータ型として宣言することもできます。例えば、以下のコードでは、コンパイラは r1 および r2 を暗黙的に auto signed int として宣言しません。これは、これらはそれぞれ char 型および float 型として明示的に宣言されているからです。

void bar(float *);

int add(int x)
{
  int a = 0;
  char r1 = 0;
  float r2 = 0.0;

    bar(&r2);
    __asm
    {
      ADD r1, a, #100
    }
    ...
    return r1;
}

コンパイラは、他のレジスタに対して変数を暗黙的に宣言しないため、C または C++ コードの R0R12 および r0r12 以外のレジスタの変数は明示的に宣言する必要があります。spr13)、lrr14)、および pcr15)レジスタに対して変数は宣言されていないため、これらをインラインアセンブリコード内で読み出したり直接変更したりすることはできません

仮想プロセッサ状態レジスタ(PSR)は存在しません。PSR への参照は、常に物理 PSR への参照となります。

変数のサイズは、物理レジスタと同じです。

コンパイラによって宣言された変数には関数のローカル有効範囲が割り当てられます。つまり、1 つの関数内で、同じ変数名を参照する複数の asm ステートメントまたは宣言が、同じ仮想レジスタにアクセスします。

以前のガイドラインに準拠している既存のインラインアセンブラコードでは、古いバージョンのコンパイラと同じ機能が実行されますが、各命令使用される実際のレジスタが、異なる場合があります。

物理レジスタを表す各変数の初期値は予測不可能です。これらの変数を読み出すには、その前に書き込みを行う必要があります。このような変数の書き込みの前に読み出しを試みると、コンパイラによりエラーが生成されます。例えば、物理レジスタ r1 に関連付けられた変数を読み出そうとした場合などです。

レジスタを参照するためにインラインアセンブラ内で使用するすべての変数は、コンパイラによって暗黙的に宣言されていなければ、C または C++ コードで明示的に宣言する必要があります。ただし、これらの変数は、C または C++ コードで明示的に宣言することを推奨します。変数は、暗黙的な宣言と同じデータ型として宣言する必要はありません。例えば、レジスタ R0 はコンパイラによって signed int として暗黙的に宣言されますが、必要に応じて R0 を符号なし整数変数として明示的に宣言できます。

また、命令のオペランドには C または C++ の変数を使用することを推奨します。コンパイラは、暗黙的または明示的に宣言されているかに関係なく、各変換単位で 1 回だけ、変数または物理レジスタ名が初めて使用されたときに警告を生成します。例えば、レジスタ r3 を宣言しないで使用した場合、警告が表示されます。この警告は、--diag_suppress を使用して抑止できます。

Show/hide関連項目

Copyright © 2010-2011 ARM. All rights reserved.ARM DUI 0472EJ
Non-ConfidentialID081711