次のc++コードがあるとしましょう。
int var1;
__asm {
mov var1, 2;
}
さて、私が知りたいのは、var1を__asmディレクティブの外側で定義したくない場合、それをその中に入れるために何をしなければならないかということです。それも可能ですか?
ありがとう
次のc++コードがあるとしましょう。
int var1;
__asm {
mov var1, 2;
}
さて、私が知りたいのは、var1を__asmディレクティブの外側で定義したくない場合、それをその中に入れるために何をしなければならないかということです。それも可能ですか?
ありがとう
これを行うには、_declspec(naked)を使用して「naked」メソッドを作成し、通常はコンパイラーによって作成されるプロローグとエピローグを自分で作成する必要があります。
プロローグの目的は次のとおりです。
エピローグは次のことを行う必要があります。
これが標準のプロローグです
push ebp ; Save ebp
mov ebp, esp ; Set stack frame pointer
sub esp, localbytes ; Allocate space for locals
push <registers> ; Save registers
および標準エピローグ:
pop <registers> ; Restore registers
mov esp, ebp ; Restore stack pointer
pop ebp ; Restore ebp
ret ; Return from function
その後、ローカル変数はで始まり(ebp - 4)
、まで下がっていき(ebp - 4 - localbytes)
ます。関数パラメータはで始まり、(ebp + 8)
上に向かっていきます。
アセンブラでC変数を作成することは不可能です。Cコンパイラは変数(つまり、その型とアドレス)を認識している必要があります。つまり、Cコードで宣言する必要があります。
実行できるのはextern
、Cの宣言を介してアセンブラーで定義されたシンボルにアクセスすることです。ただし、これらの変数は固定アドレスを持たず、ベースポインターを基準にして参照されるため、自動保存期間のある変数では機能しません。
ブロック外の変数にアクセスしたくない場合はasm
、スタックを使用してアセンブラーローカルデータを格納できます。asm
ブロックを離れるときは、スタックポインタを以前の値に復元する必要があることに注意してください。
sub esp, 12 ; space for 3 asm-local 32bit vars
mov [esp-8], 42 ; set value of local var
[...]
push 0xdeadbeaf ; use stack
[...] ; !!! 42 resides now in [esp-12] !!!
add esp, 16 ; restore esp
スタックを操作するたびにローカル変数の相対アドレスを変更したくない場合(つまり、push
またはを使用する場合pop
)、スタックフレームを確立する必要があります(つまり、スタックのベースを保存し、ebp
この値に関連するローカルアドレスを指定します)cedrouの回答で説明されているように。
ローカル変数は、ESPレジスタを介してコールスタックの使用可能なスペースを操作することによって割り当てられ、解放されます。
__asm
{
add esp, 4
mov [esp], 2;
...
sub esp, 4
}
一般に、これは、代わりに呼び出し元の関数の「スタックフレーム」を確立し、ESPレジスタを直接使用する代わりに、フレーム内のオフセットを使用してローカル変数(および関数パラメーター)にアクセスすることで、より適切に処理されます。
__asm
{
push ebp
mov ebp, esp
add esp, 4
...
mov [ebp-4], 2;
...
mov esp, ebp
pop ebp
}