1.1 标准调用(__stdcall函数)
1.1.1 代码
#include
<stdio.h>
int
__stdcall Callee(int param1,int param2)
{
int
iVar = param1
;
return 10;
}
int
main()
{
Callee(1,2);
return 0;
}
1.1.2 函数int main()
int main()
{
00411460 push ebp
00411461 mov ebp,esp
00411463 sub esp,0C0h
00411469 push ebx
0041146A push esi
0041146B push edi
0041146C lea edi,[ebp-0C0h]
00411472 mov ecx,30h
00411477 mov eax,0CCCCCCCCh
0041147C rep stos dword ptr es:[edi]
Callee(1,2);
0041147E push 2
00411480 push 1
00411482 call CrackFun (4111EAh)
【Jeffrey: 在函数调用前先将参数从左到右入栈,然哈欧调用参数。】
return 0;
00411487 xor eax,eax
}
00411489 pop edi
0041148A pop esi
0041148B pop ebx
0041148C add esp,0C0h
00411492 cmp ebp,esp
00411494 call @ILT+300(__RTC_CheckEsp) (411131h)
00411499 mov esp,ebp
0041149B pop ebp
0041149C ret
--- No source file -------------------------------------------------------------
......
004111E5 jmp Callee (411410h)
004111EA jmp Callee (411410h)
【Jeffrey:此时已经将函数的返回值地址压入栈中。】
004111EF int 3
004111F0 int 3
......
1.1.3 函数int __stdcall Callee(int param1,int param2)
int __stdcall Callee(int param1,int param2)
{
00411410 push ebp
00411411 mov ebp,esp
00411413 sub esp,0CCh
00411419 push ebx
0041141A push esi
0041141B push edi
【Jeffrey:在子函数入口处,依次将以上4个寄存器的值入栈。】
0041141C lea edi,[ebp-0CCh]
00411422 mov ecx,33h
00411427 mov eax,0CCCCCCCCh
0041142C rep stos dword ptr es:[edi]
int iVar = param1;
0041142E mov eax,dword ptr [param1]
00411431 mov dword ptr [iVar],eax
return 10;
00411434 mov eax,0Ah
【Jeffrey:函数返回值放在寄存器EAX中。】
}
00411439 pop edi
0041143A pop esi
0041143B pop ebx
0041143C mov esp,ebp
0041143E pop ebp
【Jeffrey:在函数返回前,将入口处入栈的寄存器逆次出栈。】
0041143F ret 8
【Jeffrey:标准调用中,函数返回前负责恢复堆栈信息,“8”为传入参数的大小。】
--- No source file -------------------------------------------------------------
1.2 C调用(__cdecl函数)
1.2.1 代码
#include
<stdio.h>
int
__cdecl Callee(int param1,int param2)
{
int iVar = param1;
return 10;
}
int
main()
{
Callee(1,2);
return 0;
}
1.2.2 函数int main()
int main()
{
004113D0 push ebp
004113D1 mov ebp,esp
004113D3 sub esp,0C0h
004113D9 push ebx
004113DA push esi
004113DB push edi
004113DC lea edi,[ebp-0C0h]
004113E2 mov ecx,30h
004113E7 mov eax,0CCCCCCCCh
004113EC rep stos dword ptr es:[edi]
Callee(1,2);
004113EE push 2
004113F0 push 1
004113F2 call Callee (411136h)
004113F7 add esp,8
【Jeffrey:函数返回后主调函数负责恢复堆栈信息。】
return 0;
004113FA xor eax,eax
}
004113FC pop edi
004113FD pop esi
004113FE pop ebx
004113FF add esp,0C0h
00411405 cmp ebp,esp
00411407 call @ILT+300(__RTC_CheckEsp) (411131h)
0041140C mov esp,ebp
0041140E pop ebp
0041140F ret
--- No source file -------------------------------------------------------------
1.2.3 函数int __cedcl Callee(int param1,int param2)
int __cdecl Callee(int param1,int param2)
{
00411390 push ebp
00411391 mov ebp,esp
00411393 sub esp,0CCh
00411399 push ebx
0041139A push esi
0041139B push edi
0041139C lea edi,[ebp-0CCh]
004113A2 mov ecx,33h
004113A7 mov eax,0CCCCCCCCh
004113AC rep stos dword ptr es:[edi]
int iVar = param1;
004113AE mov eax,dword ptr [param1]
004113B1 mov dword ptr [iVar],eax
return 10;
004113B4 mov eax,0Ah
}
004113B9 pop edi
004113BA pop esi
004113BB pop ebx
004113BC mov esp,ebp
004113BE pop ebp
004113BF ret
【Jeffrey:C调用中,子函数不负责堆栈信息。】
--- No source file -------------------------------------------------------------
1.3 函数调用过程中栈数据的变化