#include <stdio.h>
/*
>>>>>> _declspec(naked) 使用 <<<<<<<<
*/
#define Reg ebp //通过改变该宏定义值来查看不同的寄存器
unsigned int retaddr;
int i=0;
unsigned int temp;
_declspec(naked) void test1 ()
{
__asm mov temp,Reg
printf("[TEST1()]进入test1(),未弹出返回地址之前的Reg : 0x %x \n",temp);
__asm pop retaddr;
__asm mov temp,Reg
printf("[TEST1()]进入test1(),弹出返回地址之后的Reg : 0x %x \n",temp);
for (i=0;i<100;)
{
i++;
// printf("test1 () i = %d \n",i);
}
__asm mov temp,Reg
printf("[TEST1()]进入test1(),离开test1()之前的Reg : 0x %x \n",temp);
__asm jmp retaddr;
}
void test2 ()
{
__asm mov temp,Reg
printf("[TEST2()]进入test2()之后的Reg : 0x %x \n",temp);
for (i=0;i<100;)
{
i++;
// printf("test2 () i = %d \n",i);
}
__asm mov temp,Reg
printf("[TEST2()]离开test2()之前的Reg : 0x %x \n",temp);
}
int main()
{
__asm mov temp,Reg
printf("看是进入main函数时的Reg : 0x %x \n",temp);
printf("未进入test1()时的Reg : 0x %x \n",temp);
test1();
__asm mov temp,Reg
printf("离开test1()时的Reg : 0x %x \n",temp);
printf("未进入test2()时的Reg : 0x %x \n",temp);
test2 ();
__asm mov temp,Reg
printf("离开test2()时的Reg : 0x %x \n",temp);
return 0;
}
经过研究发现在_declspec(naked)函数运行时的EBP与main的EBP是一致的。但是在调用_declspec(naked)时,先会将返回地址压入栈中。但是弹出后的ESP与main的ESP相同。也就是说在调用_declspec(naked)时,只将<返回地址>压入栈中了。只要弹出返回地址后,ESP和EBP就会恢复为原来的状态。在函数返回值,函数不会处理关于堆栈的信息。所以要手动恢复现场,手法类似于普通函数。在普通函数运行时ESP与EBP都发生变化。函数调用要先将一部分寄存器压入栈中,特殊提出的是EBP也会被压入栈中。然后函数会将当前的ESP定义为EBP,进行下一步操作。所以说在该函数体中的ESP和EBP与main函数中均不相同。但是函数执行结束后又将ESP和EBP自动复原。我计算的是可能压入了21个参数。因为栈顶位置相差了54H,但是这不能就说压入了21个参数,因为在main函数中可能已经压入了一些数据。这个具体压入了人多少参数,回头再研究一下~