レジスタ ([ar]ax、つまり) の値を保持する必要があります。関数呼び出しの後に変更されますが、値は後で使用する必要があります。私はそうする3つの方法を考えました(例は64ビットにあります):
1.スタックにプッシュします。
__asm__ ("pushq %rax\n\t"
"call function\n\t"
"popq %rax");
2.レジスタに保存します。
__asm__ ("movq %%rax, %%some_register\n\t"
"call function\n\t"
"movq %%some_register, %%rax"
: : : "%some_register");
3.変数に保存します。
unsigned long var;
__asm__ ("movq %%rax, %0" : "=m" (var) : : );
function();
__asm__ ("movq %0, %%rax" : : "m" (var) : );
現在、私は#1を使用しています。私の特定のケースでは意図したとおりに機能しますが、スタックにプッシュすることは悪いこと™ ではないかと心配しています。私の懸念のほとんどは、コンパイラがプッシュされていることを「認識」していないことでした。かなり制限されたスタックフレームのスペースを消費しているように見えるため、一般的に問題が発生する可能性があります。
レジスターに保存すると、コンパイラーはそれを独自のニーズに使用できなくなります。これは、x86 と比較して多くの追加レジスターがある x86-64 ではそれほど問題にならないかもしれません。ただし、x86 で使用する必要がある場合は、レジスタの量がはるかに制限されているため、パフォーマンスが低下する可能性があります。
変数に保存するのが最良の選択かもしれません。そして、コンパイラーはおそらく変数をスタックに保存し、レジスターを割り当てさえするので、それほど遅くはないかもしれません。しかし、コードが奇妙に見えるだけでなく、他の人が頭を悩ませる可能性のある変数が 1 つ追加されています。
問題は、どのソリューションが最適かということです。つまり、Right Thing™ は何をすべきでしょうか? それとも、私が考えていなかった、それを保存するためのいくつかの方法があります-さらに良い方法はありますか?
注: その関数は変数を取らず、問題がある場合は何も返しません。レジスタ内の値は、「より高いレベルの」ソリューションを介して単純に保存することはできません。したがって、インライン asm; 具体的には[er]axでなければなりません。3番目のソリューションはテストしていないため、少し不正確かもしれません.