9

これがどのように機能するのかわかりません。

GCC インライン アセンブラーは正しく理解するのが面倒ですが、コンパイラーが何をしているかを認識できるように、クロバー情報のマーキングについては非常に具体的です。

Microsoft Visual C++ のインライン アセンバーは非常に使いやすい (常に動作しているように見える) が、コードに関してどのような種類の保証や仮定が行われるかはわかりません。

VC++ は、どのレジスタが破壊されているかを「自動検出」しようとしますか? レジスタとスタックポインタがどのように変更されるかをどのように知るのですか? それは何らかの仮定をしますか?もしそうなら、どのようにそれらの仮定を回避しますか?

4

2 に答える 2

20

GCC が MSVC のようにそれを行わない理由については、いくつかの理由があります。

  1. GCC は再ターゲット可能なコンパイラですが、アセンブリ構文は単なる生のテキストです。破壊検出を自動化するために、GCC はアセンブリ言語を解析して、どのレジスターが破壊されているかを理解する必要があります (オペコードがレジスターを指定しない命令によって暗黙的に破壊されたレジスターを含む)。これは、すべてのアーキテクチャで機能する必要があります。現在、GCC はアセンブリ言語を解析しません。%置換を実行した後、アセンブリ出力に貼り付けるだけです。アイデアは、生成し、解析を回避することです。

  2. GCC インライン アセンブリ言語では、レジスタの破壊は規則ではなく例外です。その理由は、MSVC よりも洗練された言語だからです。GCC のインライン アセンブリ言語は、レジスタを割り当てます。したがって、通常は%eax直接のようなものを使用するのではなく、%0GCC が使用可能なレジスターを代用するようなコードを使用します。(そして、それを行うために、コンパイラはアセンブリ言語を理解する必要はありません! GCC%0が使用法に適合する適切なレジスタを代用することを保証する制約を表現します。) アセンブリ コードがハードコーディングされたものを上書きする場合にのみ clobber が必要です。 GCC によって割り当てられた出力オペランドを上書きしている場合ではありません

GCC インライン アセンブリを使用すると、初期値を生成する C 式からアセンブリ言語オペランドをロードするコードや、結果オペランドを C の宛先に格納するコードを記述する必要がないことに注意してください。たとえば"r"、式 から派生した型 (レジスタ)の入力オペランドがあることを表現しただけfoo->bar + 1です。GCC はレジスタを割り当て、コードを生成して からロードし、アセンブリ テンプレート内の をそのレジスタの名前にfoo->bar + 1置き換えます。%0

于 2012-05-08T20:02:17.470 に答える
5

ドキュメントからの引用:

__asmを使用してC/C ++関数でアセンブリ言語を記述する場合、EAX、EBX、ECX、EDX、ESI、またはEDIレジスタを保持する必要はありません。たとえば、インラインアセンブリを使用した関数の記述のPOWER2.Cの例では、power2関数はEAXレジスタの値を保持しません。ただし、レジスタアロケータはこれらのレジスタを使用して__asmブロック全体に値を格納できないため、これらのレジスタを使用するとコードの品質に影響します。さらに、インラインアセンブリコードでEBX、ESI、またはEDIを使用することにより、コンパイラにこれらのレジスタを関数プロローグおよびエピローグに保存および復元するように強制します。

__asmブロックのスコープには、使用する他のレジスタ(DS、SS、SP、BP、フラグレジスタなど)を保持する必要があります。ESPおよびEBPレジスタを変更する理由がない限り(たとえば、スタックを切り替えるため)、それらを保持する必要があります。インラインアセンブリの最適化も参照してください。

于 2012-05-08T19:20:37.433 に答える