次の方法で共有


プロローグ コードとエピローグ コードを記述する際の考慮事項

Microsoft 固有の仕様

独自のプロローグとエピローグのコード シーケンスを記述する前に、スタック フレームがどのように配置されるかを理解することが重要です。__LOCAL_SIZE シンボルの使用方法も知っておくと役立ちます。

スタック フレーム レイアウト

この例は、32 ビット関数で使用される標準プロローグ コードを示しています。

push        ebp                ; Save ebp
mov         ebp, esp           ; Set stack frame pointer
sub         esp, localbytes    ; Allocate space for locals
push        <registers>        ; Save registers

localbytes 変数は、ローカル変数のスタックで必要なバイト数を表します。また、<registers> 変数は、スタックに格納されるレジスタの一覧を表すプレースホルダーです。 レジスタをプッシュした後、スタックに他の適切なデータを配置できます。 対応するエピローグ コードは次のとおりです。

pop         <registers>   ; Restore registers
mov         esp, ebp      ; Restore stack pointer
pop         ebp           ; Restore ebp
ret                       ; Return from function

スタックは、常に下に (上位メモリ アドレスから下位メモリ アドレスに) 向かって大きくなります。 基本ポインター (ebp) は、プッシュされた ebp の値を指します。 ローカル領域は ebp-4 で始まります。 ローカル変数にアクセスするには、ebp からのオフセットを計算します。そのためには、ebp から適切な値を減算します。

__LOCAL_SIZE

コンパイラには、関数プロローグ コードのインライン アセンブラー ブロックで使用できる __LOCAL_SIZE シンボルが用意されています。 カスタム プロローグ コードで、スタック フレームにローカル変数の領域を割り当てるときに、このシンボルを使用します。

__LOCAL_SIZE の値は、コンパイラによって決定されます。 その値は、すべてのユーザー定義のローカル変数とコンパイラにより生成された一時変数の合計バイト数です。 __LOCAL_SIZE は、イミディエイト (即値) オペランドとしてのみ使用できます。式では使用できません。 このシンボルの値は、変更することも再定義することもできません。 次に例を示します。

mov        eax, __LOCAL_SIZE           ;Immediate operand--Okay
mov        eax, [ebp - __LOCAL_SIZE]   ;Error

カスタムのプロローグ シーケンスとエピローグ シーケンスを含む naked 関数の次の例では、プロローグ シーケンスで __LOCAL_SIZE シンボルを使用しています。

// the__local_size_symbol.cpp
// processor: x86
__declspec ( naked ) int main() {
   int i;
   int j;

   __asm {      /* prolog */
      push   ebp
      mov      ebp, esp
      sub      esp, __LOCAL_SIZE
      }

   /* Function body */
   __asm {   /* epilog */
      mov      esp, ebp
      pop      ebp
      ret
      }
}

Microsoft 固有の仕様はここまで

関連項目

naked 関数呼び出し