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 thenaked attribute is only valid on x86, and is not available on x64 or Itanium.
在网上搜了些资料后不是很理解,写了测试代码并反汇编了下:
#include
void call_me(int x, int y)
{
int a = x;
static int b;
int c;
b = y;
c = a+b;
}
void __declspec (naked) kkk(int a, int b) {
static int c;
int d;
c = a + b;
d = c;
call_me(a, d);
}
void aaa(int a, int b) {
static int c;
int d;
c = a + b;
d = c;
call_me(a, d);
}
int main()
{
kkk(5, 6);
aaa(5, 6);
getchar();
return 1;
}
.text:00401000 sub_401000 proc near ; CODE XREF: .text:0040104Cp
.text:00401000 ; sub_401060+20p
.text:00401000
.text:00401000 var_8 = dword ptr -8
.text:00401000 var_4 = dword ptr -4
.text:00401000 arg_0 = dword ptr 8
.text:00401000 arg_4 = dword ptr 0Ch
.text:00401000
.text:00401000 push ebp
.text:00401001 mov ebp, esp
.text:00401003 sub esp, 8
.text:00401006 mov eax, [ebp+arg_0]
.text:00401009 mov [ebp+var_4], eax
.text:0040100C mov ecx, [ebp+arg_4]
.text:0040100F mov dword_4033B4, ecx
.text:00401015 mov edx, [ebp+var_4]
.text:00401018 add edx, dword_4033B4
.text:0040101E mov [ebp+var_8], edx
.text:00401021 mov esp, ebp
.text:00401023 pop ebp
.text:00401024 retn
.text:00401024 sub_401000 endp
.text:00401024
.text:00401024 ; ---------------------------------------------------------------------------
.text:00401025 align 10h
.text:00401030
.text:00401030 loc_401030: ; CODE XREF: _main+7p
.text:00401030 mov eax, [ebp+8]
.text:00401033 add eax, [ebp+0Ch]
.text:00401036 mov dword_4033B0, eax
.text:0040103B mov ecx, dword_4033B0
.text:00401041 mov [ebp-4], ecx
.text:00401044 mov edx, [ebp-4]
.text:00401047 push edx
.text:00401048 mov eax, [ebp+8]
.text:0040104B push eax
.text:0040104C call sub_401000
.text:00401051 add esp, 8
.text:00401051 ; ---------------------------------------------------------------------------
.text:00401054 db 0Ch dup(0CCh)
.text:00401060
.text:00401060 ; =============== S U B R O U T I N E =======================================
.text:00401060
.text:00401060 ; Attributes: bp-based frame
.text:00401060
.text:00401060 sub_401060 proc near ; CODE XREF: _main+13p
.text:00401060
.text:00401060 var_4 = dword ptr -4
.text:00401060 arg_0 = dword ptr 8
.text:00401060 arg_4 = dword ptr 0Ch
.text:00401060
.text:00401060 push ebp
.text:00401061 mov ebp, esp
.text:00401063 push ecx
.text:00401064 mov eax, [ebp+arg_0]
.text:00401067 add eax, [ebp+arg_4]
.text:0040106A mov dword_4033AC, eax
.text:0040106F mov ecx, dword_4033AC
.text:00401075 mov [ebp+var_4], ecx
.text:00401078 mov edx, [ebp+var_4]
.text:0040107B push edx
.text:0040107C mov eax, [ebp+arg_0]
.text:0040107F push eax
.text:00401080 call sub_401000
.text:00401085 add esp, 8
.text:00401088 mov esp, ebp
.text:0040108A pop ebp
.text:0040108B retn
.text:0040108B sub_401060 endp
.text:0040108B
.text:0040108B ; ---------------------------------------------------------------------------
.text:0040108C align 10h
.text:00401090
.text:00401090 ; =============== S U B R O U T I N E =======================================
.text:00401090
.text:00401090 ; Attributes: bp-based frame
.text:00401090
.text:00401090 ; int __cdecl main(int argc, const char **argv, const char **envp)
.text:00401090 _main proc near ; CODE XREF: ___tmainCRTStartup+10Ap
.text:00401090
.text:00401090 argc = dword ptr 8
.text:00401090 argv = dword ptr 0Ch
.text:00401090 envp = dword ptr 10h
.text:00401090
.text:00401090 push ebp
.text:00401091 mov ebp, esp
.text:00401093 push 6
.text:00401095 push 5
.text:00401097 call loc_401030
.text:0040109C add esp, 8
.text:0040109F push 6
.text:004010A1 push 5
.text:004010A3 call sub_401060
.text:004010A8 add esp, 8
.text:004010AB call ds:getchar
.text:004010B1 mov eax, 1
.text:004010B6 pop ebp
.text:004010B7 retn
.text:004010B7 _main endp
仔细阅读汇编代码,可以知道:
1.naked声明的函数,编译后缺少prolog and epilog code,见代码红色部分。
2.naked声明的函数,不会进行局部变量的栈空间分配(没有push cx),而是直接进行使用(mov [ebp-4], ecx),对比代码绿色部分。
3.naked声明的函数,不会影响编译器对它所调用的函数的栈平衡,见代码紫色部分。
4.naked声明的函数,因为缺少epilog code,没有ret,所以函数必须是void类型。在实际操作中,可在依据需要在函数中自己加入ret指令。
编译工具是VS2008,设置属性如下:
/Ob1 /GL /D "_AFXDLL" /D "_UNICODE" /D "UNICODE" /FD /MD /GS- /Gy /FAs /Fa"Release\\" /Fo"Release\\" /Fd"Release\vc90.pdb" /W3 /nologo /c /Zi /Gd /TC /errorReport:prompt