C/C++拾遗录--查看关于_declspec(naked)与普通的函数在寄存器变化方面的不同点

#include 
/*
    >>>>>>   _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函数中可能已经压入了一些数据。这个具体压入了人多少参数,回头再研究一下~

你可能感兴趣的:(C/C++语言基础)