VC 中函数调用保留现场问题
int mabs(int number)
{
int numberRtn =number<0?-number:number;
return numberRtn;
}
45: absnegInt =mabs(negInt);
004018B6 mov eax,dword ptr [ebp-4]
004018B9 push eax
004018BA call @ILT+605(mabs) (00401262) //call函数前将下一个指令地址004018BF(函数返回后的EIP) 压入栈中
004018BF add esp,4 //处理之前函数参数栈
004018C2 mov dword ptr [ebp-0Ch],eax
00401262 jmp mabs (00401840)
004018BA call :**************************************
29: int mabs(int number)
30: {
00401840 push ebp //保存主函数的堆栈数据区指针,ebp入栈
00401841 mov ebp,esp //将ebp 指向当前函数体的栈数据区
00401843 sub esp,48h //将栈顶向低地址偏移,从而可以
00401846 push ebx //保留一些栈空间为本函数使用,
00401847 push esi //依次保留现场,ebx,esi,edi
00401848 push edi
00401849 lea edi,[ebp-48h]
0040184C mov ecx,12h
00401851 mov eax,0CCCCCCCCh
00401856 rep stos dword ptr [edi] //这4句格式化为本函数保留的栈空间
31: int numberRtn =number<0?-number:number;
00401858 cmp dword ptr [ebp+8],0
0040185C jge mabs+28h (00401868)
0040185E mov eax,dword ptr [ebp+8]
00401861 neg eax
00401863 mov dword ptr [ebp-8],eax
00401866 jmp mabs+2Eh (0040186e)
00401868 mov ecx,dword ptr [ebp+8]
0040186B mov dword ptr [ebp-8],ecx
0040186E mov edx,dword ptr [ebp-8]
00401871 mov dword ptr [ebp-4],edx
32: return numberRtn;
00401874 mov eax,dword ptr [ebp-4]
33: }
00401877 pop edi //本函数体结束后,esp的值同于函数体开始时的esp;
00401878 pop esi //逐个恢复现场
00401879 pop ebx
0040187A mov esp,ebp //恢复到主函数入口处;将栈顶置保存入口地址处;
0040187C pop ebp //恢复主函数数据基址指针;
0040187D ret //函数返回,将当前栈顶的值送到EIP,也就是pop当前栈顶值到EIP;
***********************************************************************
***********************************************************************
int my_asmabs(int number)
{
//int numberRtn =number<0?-number:number;
//return number;
__asm
{ //这里VC在传递参数经来的时候已经自动保留了现场;
//并开辟一定栈区(ebp-4~ebp-4*N),保留供本函数使用
//并且将参数放在ebp+8开始的栈区里面;
mov eax, dword ptr [ebp+8]
cmp dword ptr [ebp+8], 0
jge abs_end
neg eax
abs_end:
}
}
:::CALL:::
43: abspotInt =my_asmabs(potInt);
004018C5 mov ecx,dword ptr [ebp-8]
004018C8 push ecx
004018C9 call @ILT+190(my_asmabs) (004010c3)
004018CE add esp,4
004018D1 mov dword ptr [ebp-10h],eax
//上面call 转到跳到 “004010C3 jmp my_asmabs (004017f0)”
//的时,又有一个dwords 入栈[esp],也就是后来在__asm{}段时,的[ebp+04h]
//函数体完毕后,由ret 来自动退这个栈空间。
004017F0 push ebp
004017F1 mov ebp,esp
004017F3 sub esp,40h
004017F6 push ebx
004017F7 push esi
004017F8 push edi
004017F9 lea edi,[ebp-40h]
004017FC mov ecx,10h
00401801 mov eax,0CCCCCCCCh
00401806 rep stos dword ptr [edi]
17: __asm
18: { //这里VC在传递参数经来的时候已经自动保留了现场;
19: //并开辟一定栈区(ebp-4~ebp-4*N),在本例中N=10h,
//保留供本函数使用
20: //并且将参数放在ebp+8开始的栈区里面;
21: mov eax, dword ptr [ebp+8]
00401808 mov eax,dword ptr [ebp+8]
22: cmp dword ptr [ebp+8], 0
0040180B cmp dword ptr [ebp+8],0
23: jge abs_end
0040180F jge abs_end (00401813)
24: neg eax
00401811 neg eax
25: abs_end:
26: }
27: }
00401813 pop edi
00401814 pop esi
00401815 pop ebx
00401816 add esp,40h
00401819 cmp ebp,esp
0040181B call __chkesp (00407360) //VC 编译器检测esp;
00401820 mov esp,ebp
00401822 pop ebp
00401823 ret //自动退一个双字栈内存;