アセンブリの手続きと関数
インライン アセンブリ言語コードを使用すると、begin...end
文を使わずに完全な手続きや関数を記述できます。
コンパイラによる最適化
次に挙げるのは、そのようにして記述できる関数の例です。
function LongMul(X, Y: Integer): Longint;
asm
MOV EAX,X
IMUL Y
end;
このようなルーチンに対して、コンパイラで次のような最適化が行われます。
- 値パラメータをローカル変数にコピーするコードは生成されません。 これによって影響を受けるのは、文字列型のすべての値パラメータと、サイズが 1、2、4 バイト以外のその他の値パラメータです。 このようなパラメータは、ルーチン内部では var パラメータと同様に扱う必要があります。
- 関数が文字列、バリアント、インターフェイス参照を返す場合を除いて、コンパイラでは関数の result 変数が割り当てられません。そのため、@Result シンボルを参照するとエラーになります。 文字列、バリアント、インターフェイスの場合には、呼び出し側で常に @Result ポインタを割り当てます。
- コンパイラがスタック フレームを生成するのは、ネストしたルーチン、ローカル パラメータを持つルーチン、スタック上にパラメータを置くルーチンの場合だけです。
- Locals はローカル変数のサイズであり、Params はパラメータのサイズです。 Locals と Params の両方が 0 の場合には、エントリ コードは存在せず、終了コードは RET 命令だけになります。
上記のルーチンに対して自動生成されるエントリ コードと終了コードは次のようなものです。
PUSH EBP ;Present if Locals <> 0 or Params <> 0
MOV EBP,ESP ;Present if Locals <> 0 or Params <> 0
SUB ESP,Locals ;Present if Locals <> 0
; …
MOV ESP,EBP ;Present if Locals <> 0
POP EBP ;Present if Locals <> 0 or Params <> 0
RET Params ;Always present
ローカル変数にバリアント、長い文字列、またはインターフェイスが含まれている場合には、それらは 0 に初期化されますが、終了処理は行われません。
関数の結果
アセンブリ言語の関数では、次のようにして結果が返されます。
32 ビット
- 順序値は AL(8 ビット値)、AX(16 ビット値)、または EAX(32 ビット値)に返されます。
- 実数値はコプロセッサのレジスタ スタックの ST(0) に返されます。 (Currency 値は 10000 倍されます。)
- ポインタ(長い文字列を含む)は EAX に返されます。
- 短い文字列とバリアントは、@Result が指す一時的な場所に返されます。
64 ビット
- サイズが 8 バイト以下の値は RAX に返されます。
- 実数値は XMM0 に返されます。
- その他の型は参照で返され、そのポインタ値は RAX に置かれます(メモリは呼び出し側ルーチンで割り当てます)。
Intel 64 固有事項(疑似命令)
x64 関数はすべてをアセンブリまたは Pascal で記述する必要があります。つまり、アセンブラ文はサポートされず、インライン アセンブリ関数だけがサポートされています。
x64 でのスタック使用状況を管理するために、.PARAMS、.PUSHNV、.SAVENV、.NOFRAME という疑似命令が用意されています。
疑似命令 |
説明 |
---|---|
|
x64 呼び出し規約に従ってレジスタ パラメータ外部記憶装置をセットアップする目的で外部関数を呼び出す際に使用します(セットアップは通常デフォルトでは行われません)。 この疑似命令を使用する場合、呼び出された関数にスタック パラメータを渡すのに、疑似変数 @params を使用できます。 @params はバイト配列として使用します。最初のスタック パラメータが @params[32] となり、位置 0 ~ 31 は 4 つのレジスタ パラメータを表します。 |
|
プロローグおよびエピローグで不揮発性の汎用レジスタを保存したり復元するコードを生成します。 |
|
.PUSHNV と同じ機能ですが、不揮発性の XMM レジスタが対象です。 |
|
宣言されたローカル変数がなく、パラメータ数が 4 以下であれば、スタック フレームの生成を強制的に無効にします。 リーフ関数に対してのみ使用します。 |
PC マップ例外用のスタックのアンワインド
詳細は、「PC マップ例外#アセンブリ ルーチンのアンワインド」を参照してください。