asm volatile 呼び出し内から静的変数に直接アクセスしようとすると、未定義の参照エラーが発生します。入力レジスタと出力レジスタを使用せずにこれを行う方法があると思いますが、検索が空になります。
int main() {
static unsigned int a = 0;
__asm__ __volatile__("push a" : : :);
return 0;
}
error: undefined reference to a
本当に古い質問ですが、受け入れられた答えがないので...
まず、インライン asm を使用することは、通常は悪い考えです。しかし、もしあなたがしなければならないなら...
a
static は関数内で宣言されるため、gccは main() で指定された static 変数と foo() で指定された static 変数を区別する何らかの方法が必要です。これを行う方法は実装で定義されていますが、私のマシンでのビルドでは a.2499 という名前を使用しました。だから使用:
__asm__ __volatile__("push a.2499" : : :);
働きました。少なくとも1分間はそうでした。周りのコードを少し変更したら、a.2500に変更しました。もちろん、このステートメントを実行した直後に、スタックの破損が原因でアプリがクラッシュしました。
しかし、このアプローチには他にも問題があります。それらのいくつかは、gcc docsの次のステートメントから来ています。
GCC はアセンブラー命令自体を解析せず、それらが何を意味するのか、あるいはそれらが有効なアセンブラー入力であるかどうかさえ知りません。
その結果、次のことを行います。
a++;
__asm__ __volatile__("push a.2500" : : :);
a++;
あなたが期待することをしません。-O1 からの最小限の最適化でさえ、2 つのa++
ステートメントを 1つの に結合しaddl $2, a.2500(%rip)
ます。これは、入力として使用すると提供されるa
asm での使用法をコンパイラが認識できないためです。a
a
揮発性として宣言することで、これを回避できます。また、グローバルを使用することで、(おそらく) 命名の問題を回避できます。
しかし、最善の解決策 (本当にインライン asm を使用する必要がある場合) はa
、入力として指定することです。代替手段には何のメリットもありません。
__asm__ __volatile__("push %0"
: /* no outputs */
: "g" (a) /* input as a register, memory, or immediate operand */
: /* no clobbers, because there's no way to tell gcc we're unbalancing the stack and clobbering the red-zone */
);
試す:
__asm__ __volatile__ ("push " (a) : : :);