我的__declspec总结

      __declspec是微软的编译指示符,可以使用__declspec关键字来指定扩展属性。该扩展属性语法简化并标准化了对于CC++语言的微软特定扩展。

      declspecdeclaration spec(声明说明),还是declaration specific的缩写?


__declspec (naked)

 

naked 属性,Microsoft

      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.

      也就是若函数声明了naked这个属性,则编译器生成的代码中没有prolog and epilog code。(网上找到的资料翻译为“不包含任何注释或标记”,这翻译的是错误的!很容易误导人啊)(《IDA Pro代码破解解密》书中,prologue译为预处理,epilogue译为扫尾。)

      prolog and epilog code到底是什么?熟悉汇编的很容易弄清楚,如下:


观察VC6 Console Code (Debug):

 

void Test(int i)

{

      i++;

}

int main(int argc, char* argv[])

{

      Test(2);

      return 0;

}

反汇编对Test的调用:

14:       Test(2);

00401048   push        2

0040104A   call        @ILT+0(Test) (00401005)

0040104F   add         esp,4

15:       return 0;

00401052   xor         eax,eax

16:   }

反汇编Test代码:

6:    void Test(int i)

7:    {

0040D470   push        ebp

0040D471   mov         ebp,esp              

0040D473   sub         esp,40h

0040D476   push        ebx

0040D477   push        esi

0040D478   push        edi

0040D479   lea         edi,[ebp-40h]

0040D47C   mov         ecx,10h

0040D481   mov         eax,0CCCCCCCCh

0040D486   rep stos    dword ptr [edi]

8:        i++;

0040D488   mov         eax,dword ptr [ebp+8]

0040D48B   add         eax,1

0040D48E   mov         dword ptr [ebp+8],eax

9:    }

0040D491   pop         edi

0040D492   pop         esi

0040D493   pop         ebx

0040D494   mov         esp,ebp

0040D496   pop         ebp

0040D497   ret

       则绿色的部分则为prolog code,蓝色的部分为epilog code

●prolog code:  这部分主要为保存原始栈指针esp,这部分是所有函数共有的。而该VC6的(DebugConsole程序,sub esp,40h该条指令为该函数预留了40h,即64bytes的临时存储空间,并初始化为cch

●epilog code:  恢复原寄存器内容,很重要的是原esp,维持堆栈平衡。然后ret指令返回原调用函数指令处。


若将Test定义为_declspec (naked) Test(int ),观察反汇编代码:

调用_declspec (naked)Test的指令跟普通Test相同:

14:       Test(2);

00401048   push        2

0040104A   call        @ILT+0(Test) (00401005)

0040104F   add         esp,4

15:       return 0;

00401052   xor         eax,eax

16:   }

 

6:    _declspec (naked) void Test(int i)

7:    {

00401020   mov         eax,dword ptr [ebp+8]

00401023   add         eax,1

00401026   mov         dword ptr [ebp+8],eax

---Nosourcefile----------------------------------------------------------------------

00401029   int         3

0040102A   int         3

0040102B   int         3

0040102C   int         3

0040102D   int         3

0040102E   int         3

0040102F   int         3

---F:/Test3/Test3.cpp---------------------------------------------------------------

8:

9:        i++;

10:   }

11:

       观察上面指定为_declspec (naked)属性的函数Test,编译器生成的汇编代码只有对于语句“i++;”的实现,前面没有prolog code,后面也没有epilog code。这就是意味着_declspec (naked)修饰的函数无法自动返回到函数调用处,得编码者手动添加代码,才能正确返回。这也就给了我们更加灵活的编码空间。


■总结

    ●_declspec (naked)关键字修饰的函数,编译器生成的汇编代码中,只生成了对应函数代码的具体实现,并没有添加任何保存栈指针esp等prolog code,也没有添加任何函数结束后恢复相关寄存器、维护栈平衡、ret等epilog code。

      若指定我们的函数为naked属性,则在函数中得通过内嵌汇编代码手动编写prolog code和epilog code来保存现场和恢复现场步骤。

       ●naked属性对于驱动开发是很有用的。如在Kernel inline Hook中,Hook Rountine的头5个字节,实现对OriginalRountine的调用上。

   ●naked属性只适用于X86系统上。


相关链接:

        http://msdn.microsoft.com/en-us/library/dabb5z75(v=vs.80).aspx

        http://blog.csdn.net/syf442/archive/2011/01/14/6137508.aspx

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值