x64 呼び出し規約の概要
更新 : 2007 年 11 月
x86 から x64 への 2 つの重要な変更点は、64 ビット アドレッシング機能と 16 個の 64 ビット汎用レジスタのフラットなセットです。拡張されたレジスタ セットを与えると、x64 は __fastcall 呼び出し規約および RISC ベースの例外処理モデルを使用します。__fastcall モデルは最初の 4 つの引数のためのレジスタと、その他のパラメータを渡すためのスタック フレームを使用します。
次のコンパイラ オプションを使用すると、x64 対応アプリケーションを最適化できます。
呼び出し規約
x64 ABI (Application Binary Interface) は 4 レジスタ fast-call 呼び出し規約であり、これらのレジスタのスタック バッキングを使用します。関数の引数と引数のレジスタは厳密に 1 対 1 で対応します。8 バイト以内に収まらない引数、または 1、2、4、8 バイト以外の引数は、参照により渡される必要があります。1 つの引数が複数のレジスタにわたって展開されることはありません。x87 レジスタ スタックは使用されません。使用することは可能ですが、関数呼び出しでは揮発性であると考える必要があります。すべての浮動小数点演算は、16 個の XMM レジスタを使用して行われます。引数は、RCX、RDX、R8、および R9 レジスタで渡されます。引数が float/double 型の場合は、XMM0L、XMM1L、XMM2L、および XMM3L で渡されます。16 バイトの引数は参照により渡されます。パラメータの引き渡しについては、「パラメータ渡し」で詳しく説明します。これらのレジスタに加えて、RAX、R10、R11、XMM4、および XMM5 は揮発性です。他のすべてのレジスタは不揮発性です。レジスタの使用については、「レジスタの使用」および「呼び出し元または呼び出し先保存済みレジスタ」で詳しく説明します。
呼び出し元は、パラメータに必要な領域を呼び出し先に割り当てる責任があり、呼び出し先がそれだけのパラメータを持たない場合でも、常に 4 つのレジスタ パラメータに対して十分な領域を割り当てる必要があります。これは、C のプロトタイプ宣言されていない関数、および vararg C/C++ 関数のサポートを簡略化します。vararg 関数またはプロトタイプ宣言されていない関数の場合、浮動小数点値は対応する汎用レジスタで重複される必要があります。最初の 4 つを超える任意のパラメータは、呼び出しの前に、最初の 4 つのバッキング ストアの上に保存されます。vararg 関数の詳細については、「vararg」を参照してください。プロトタイプ宣言されていない関数の詳細については、「プロトタイプ宣言されていない関数」を参照してください。
配置
ほとんどの構造体はそれらの自然な形式に配置されます。主な例外はスタック ポインタと malloc メモリまたは alloca メモリです。これらは、パフォーマンスを支援するために 16 バイトに配置されます。16 バイトを超える配置は手動で行う必要がありますが、16 バイトは XMM 演算の共通の配置サイズであるため、ほとんどのコードはこれで十分だといえます。構造体のレイアウトおよび配置の詳細については、「型とストレージ」を参照してください。スタック レイアウトの詳細については、「スタックの使用」を参照してください。
アンワインド可能性
リーフ関数 [関数を呼び出したり、任意のスタック空間に自身を割り当てたりしない関数] 以外のすべての関数には、不揮発性レジスタを回復するために、それらを正しくアンワインドする方法をオペレーティング システムに対して記述したデータで注釈を付ける必要があります。このデータは xdata または ehdata と呼ばれ、pdata から指されます。Prolog と epilog は、xdata で正しく記述されるように大幅に制限されます。スタック ポインタは、リーフ関数を除いて、epilog または prolog の一部でない任意のコード領域で 16 バイトに配置される必要があります。prolog および epilog 関数の正しい構造の詳細については、「プロローグとエピローグ」を参照してください。例外処理および例外処理/アンワインディング pdata および xdata の詳細については、「例外処理 (x64)」を参照してください。