4.__declspec(naked)生成純アセンブリ使用方法
__declspec(naked)は、コンパイラ関数コードを教えるためのアセンブリ言語であり、コンパイラがアセンブリコードを追加する必要はなく、一般的には純粋なアセンブリを生成することができる.
MSDNはnakedキーワードを検索すればよい:
1.nakedキーワードを使用するには、EBPポインタを自分で構築する必要があります(使用した場合).
2.VOIDを使用しない限り、RETまたはRET n命令を自分で使用して返さなければならない.
これはコンパイラが直接持ってきたアセンブリ関数コードなので、最初にコンテキストフラグビット(スタックを押す)を保存し、最後にコンテキストを復元する(スタックを出る)ことを覚えておく必要があります.そして最後にretコマンドを追加します.
一般的なアセンブリ埋め込みコードでは、コンテキストを保存する必要はありません.保存しても大丈夫ですが、retコマンドを追加することはできません.コンパイラも1つ追加するので、retコマンドは同時に2回実行できません.境界を越えたエラーを引き起こす.
次のコードがあります.
C呼び出し:
そのdebugアセンブリは次のとおりです.
ebpはここではespの値であるはずなので、
MSDNはnakedキーワードを検索すればよい:
For functions declared with the naked attribute, the compiler generates code without prolog and epilog code. You can use this feature to write your own prolog/epilog code sequences using inline assembler code. Naked functions are particularly useful in writing virtual device drivers. Note that the naked attribute is only valid on x86, and is not available on x64 or Itanium.
例:#define NAKED __declspec(naked)
VOID NAKED MyFunc()
{
__asm
{
ret
}
}
1.nakedキーワードを使用するには、EBPポインタを自分で構築する必要があります(使用した場合).
2.VOIDを使用しない限り、RETまたはRET n命令を自分で使用して返さなければならない.
これはコンパイラが直接持ってきたアセンブリ関数コードなので、最初にコンテキストフラグビット(スタックを押す)を保存し、最後にコンテキストを復元する(スタックを出る)ことを覚えておく必要があります.そして最後にretコマンドを追加します.
一般的なアセンブリ埋め込みコードでは、コンテキストを保存する必要はありません.保存しても大丈夫ですが、retコマンドを追加することはできません.コンパイラも1つ追加するので、retコマンドは同時に2回実行できません.境界を越えたエラーを引き起こす.
次のコードがあります.
C呼び出し:
#define NAKED __declspec(naked)
int NAKED Add(int a,int b)
{
__asm
{
mov eax, a
add eax, b
ret
}
}
int _tmain(int argc, _TCHAR* argv[])
{
Add(1,2);
return 0;
}
このとき呼び出しアセンブリは次のとおりです. Add(1,2);
00A217EE push 2
00A217F0 push 1
00A217F2 call Add (0A21087h)
00A217F7 add esp,8 // C ,
return 0;
__stdcall呼び出し:#define NAKED __declspec(naked)
int NAKED __stdcall Add(int a,int b)
{
__asm
{
mov eax, a
add eax, b
ret 8 //
}
}
int _tmain(int argc, _TCHAR* argv[])
{
Add(1,2);
return 0;
}
このとき呼び出しアセンブリは次のとおりです. Add(1,2);
00D117EE push 2
00D117F0 push 1
00D117F2 call Add (0D111D1h)
return 0;
デバッグが細心の注意を払うと、前のAddの戻り結果が間違っていることに気づくはずです.そのdebugアセンブリは次のとおりです.
0:000:x86> u 01381380
test1!Add [f:\test1\test1\test1.cpp @ 9]:
01381380 8b4508 mov eax,dword ptr [ebp+8]
01381383 03450c add eax,dword ptr [ebp+0Ch]
01381386 c20800 ret 8
は、[ebp+8]および[ebp+c]がそれぞれaおよびbを表し、ebpはここではespの値であるはずなので、
#define NAKED __declspec(naked)
int NAKED __stdcall Add(int a,int b)
{
__asm
{
push ebp
mov ebp,esp
mov eax, a
add eax, b
leave
ret 8
}
}