C++函数调用原理理解

空程序:<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

int main()

{

00411360 push ebp ;压入ebp

00411361 mov ebp,esp ;ebp = esp,保留esp,待函数调用完再恢复,因为函数调用中肯定会用到esp.

00411363 sub esp,<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" /><chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="0" unitname="c">0C</chmetcnv>0h ;esp-=<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="0" unitname="c">0C</chmetcnv>0h(192);为该函数留出临时存储区

;将其他指针或寄存器中的值入栈,以便在函数中使用这些寄存器。

00411369 push ebx ;压入ebx

<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="41136" unitname="a"><span lang="en-us" style="font-size: 12pt; font-family: 新宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'times new roman'; mso-no-proof: yes">0041136A</span></chmetcnv> push esi ;压入esi

0041136B push edi ;压入edi

<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="41136" unitname="c"><span lang="en-us" style="font-size: 12pt; font-family: 新宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'times new roman'; mso-no-proof: yes">0041136C</span></chmetcnv> lea edi,[ebp<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="true" hasspace="false" sourcevalue="0" unitname="c">-0C</chmetcnv>0h] ;读入[ebp<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="true" hasspace="false" sourcevalue="0" unitname="c">-0C</chmetcnv>0h]有效地址,即原esp<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="true" hasspace="false" sourcevalue="0" unitname="c">-0C</chmetcnv>0h,正好是为该函数留出的临时存储区的最低位

00411372 mov ecx,30h ;ecx = 30h(48),30h*4 = <chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="0" unitname="c">0C</chmetcnv>0h

00411377 mov eax,0CCCCCCCCh ;eax = 0CCCCCCCCh;

<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="41137" unitname="c"><span lang="en-us" style="font-size: 12pt; font-family: 新宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'times new roman'; mso-no-proof: yes">0041137C</span></chmetcnv> rep stos dword ptr es:[edi] ;重复在es:[edi]存入30;0CCCCCCCCh? Debug模式下把Stack上的变量初始化为0xcc,检查未初始化的问题

return 0;

0041137E xor eax,eax ;eax清零,作为返回值

}

;各指针出栈

00411380 pop edi ;弹出edi

00411381 pop esi ;弹出esi

00411382 pop ebx ;弹出ebx

00411383 mov esp,ebp ;esp复原

00411385 pop ebp ;弹出ebp,也复原

00411386 ret ;返回

函数调用:

int _tmain(int argc, _TCHAR* argv[])

{

同上理解, 保存现场

004113D0 push ebp

004113D1 mov ebp,esp

004113D3 sub esp,<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="0" unitname="f">0F</chmetcnv>0h ;一共留了<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="0" unitname="f"><span lang="en-us">0F</span></chmetcnv>0h(240)空间

004113D9 push ebx

004113DA push esi

004113DB push edi

004113DC lea edi,[ebp<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="true" hasspace="false" sourcevalue="0" unitname="f">-0F</chmetcnv>0h]

004113E2 mov ecx,3Ch ; ecx = <chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="3" unitname="c">3C</chmetcnv>(60),<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="3" unitname="c">3C</chmetcnv>*4 = <chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="0" unitname="f">0F</chmetcnv>0h,

004113E7 mov eax,0CCCCCCCCh

004113EC rep stos dword ptr es:[edi]

同上理解.

int a = 1, b = 2, c = 3;

定义a,b,c并存储在为函数留出的临时存储空间中.

004113EE mov dword ptr [a],1

<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="4113" unitname="f"><span lang="en-us" style="font-size: 12pt; font-family: 新宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'times new roman'; mso-no-proof: yes">004113F</span></chmetcnv>5 mov dword ptr [b],2

004113FC mov dword ptr [c],3

int d = Fun1(a, b, c);

参数反向入栈

00411403 mov eax,dword ptr [c]

00411406 push eax

00411407 mov ecx,dword ptr [b]

<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="41140" unitname="a"><span lang="en-us" style="font-size: 12pt; font-family: 新宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'times new roman'; mso-no-proof: yes">0041140A</span></chmetcnv> push ecx

0041140B mov edx,dword ptr [a]

0041140E push edx

调用Fun1

<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="41140" unitname="f"><span lang="en-us" style="font-size: 12pt; font-family: 新宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'times new roman'; mso-no-proof: yes">0041140F</span></chmetcnv> call Fun1 (4111DBh) ;Call调用时将下一行命令的EIP压入堆栈

恢复因为Fun1参数入栈改变的栈指针,因为Fun13个参数,一个整数4个字节,0Ch(12)个字节

00411414 add esp,0Ch

00411417 mov dword ptr [d],eax

将返回值保存在d.

return 0;

返回值为0,eax清零

<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="41141" unitname="a"><span lang="en-us" style="font-size: 12pt; font-family: 新宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'times new roman'; mso-no-proof: yes">0041141A</span></chmetcnv> xor eax,eax

}

恢复现场

<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="41141" unitname="c"><span lang="en-us" style="font-size: 12pt; font-family: 新宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'times new roman'; mso-no-proof: yes">0041141C</span></chmetcnv> pop edi

0041141D pop esi

0041141E pop ebx

以下全为运行时ESP检查:

先恢复因为为main预留空间而改变的栈指针

<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="41141" unitname="f"><span lang="en-us" style="font-size: 12pt; font-family: 新宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'times new roman'; mso-no-proof: yes">0041141F</span></chmetcnv> add esp,<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="0" unitname="f">0F</chmetcnv>0h

00411425 cmp ebp,esp

00411427 call @ILT+320(__RTC_CheckEsp) (411145h)

正常时只需要以下两句就可以正常恢复esp,再出栈,又可以恢复ebp.

<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="41142" unitname="c"><span lang="en-us" style="font-size: 12pt; font-family: 新宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'times new roman'; mso-no-proof: yes">0041142C</span></chmetcnv> mov esp,ebp

0041142E pop ebp

<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="41142" unitname="f"><span lang="en-us" style="font-size: 12pt; font-family: 新宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'times new roman'; mso-no-proof: yes">0041142F</span></chmetcnv> ret ;main返回

int Fun1(int a, int b, int c)

{

同上理解, 保存现场

<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="411" unitname="a"><span lang="en-us" style="font-size: 12pt; font-family: 新宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'times new roman'; mso-no-proof: yes">00411A</span></chmetcnv>70 push ebp

<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="411" unitname="a"><span lang="en-us" style="font-size: 12pt; font-family: 新宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'times new roman'; mso-no-proof: yes">00411A</span></chmetcnv>71 mov ebp,esp

<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="411" unitname="a"><span lang="en-us" style="font-size: 12pt; font-family: 新宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'times new roman'; mso-no-proof: yes">00411A</span></chmetcnv>73 sub esp,0E4h ;留了0E4H(228)空间,

<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="411" unitname="a"><span lang="en-us" style="font-size: 12pt; font-family: 新宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'times new roman'; mso-no-proof: yes">00411A</span></chmetcnv>79 push ebx

<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="411" unitname="a"><span lang="en-us" style="font-size: 12pt; font-family: 新宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'times new roman'; mso-no-proof: yes">00411A</span></chmetcnv><chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="7" unitname="a"><span lang="en-us" style="font-size: 12pt; font-family: 新宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'times new roman'; mso-no-proof: yes">7A</span></chmetcnv> push esi

<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="411" unitname="a"><span lang="en-us" style="font-size: 12pt; font-family: 新宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'times new roman'; mso-no-proof: yes">00411A</span></chmetcnv>7B push edi

<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="411" unitname="a"><span lang="en-us" style="font-size: 12pt; font-family: 新宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'times new roman'; mso-no-proof: yes">00411A</span></chmetcnv><chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="7" unitname="c"><span lang="en-us" style="font-size: 12pt; font-family: 新宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'times new roman'; mso-no-proof: yes">7C</span></chmetcnv> lea edi,[ebp-0E4h]

<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="411" unitname="a"><span lang="en-us" style="font-size: 12pt; font-family: 新宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'times new roman'; mso-no-proof: yes">00411A</span></chmetcnv>82 mov ecx,39h ; 39H(57)*4 = 0E4H(228)

<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="411" unitname="a"><span lang="en-us" style="font-size: 12pt; font-family: 新宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'times new roman'; mso-no-proof: yes">00411A</span></chmetcnv>87 mov eax,0CCCCCCCCh

<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="411" unitname="a"><span lang="en-us" style="font-size: 12pt; font-family: 新宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'times new roman'; mso-no-proof: yes">00411A</span></chmetcnv><chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="8" unitname="c"><span lang="en-us" style="font-size: 12pt; font-family: 新宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'times new roman'; mso-no-proof: yes">8C</span></chmetcnv> rep stos dword ptr es:[edi]

int d = 4, e = 5;

定义变量

<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="411" unitname="a"><span lang="en-us" style="font-size: 12pt; font-family: 新宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'times new roman'; mso-no-proof: yes">00411A</span></chmetcnv>8E mov dword ptr [d],4

<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="411" unitname="a"><span lang="en-us" style="font-size: 12pt; font-family: 新宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'times new roman'; mso-no-proof: yes">00411A</span></chmetcnv>95 mov dword ptr [e],5

int f = Fun2(a, b, c, d, e);

再次参数反向入栈

<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="411" unitname="a"><span lang="en-us" style="font-size: 12pt; font-family: 新宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'times new roman'; mso-no-proof: yes">00411A</span></chmetcnv><chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="9" unitname="c"><span lang="en-us" style="font-size: 12pt; font-family: 新宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'times new roman'; mso-no-proof: yes">9C</span></chmetcnv> mov eax,dword ptr [e]

<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="411" unitname="a"><span lang="en-us" style="font-size: 12pt; font-family: 新宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'times new roman'; mso-no-proof: yes">00411A</span></chmetcnv><chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="9" unitname="f"><span lang="en-us" style="font-size: 12pt; font-family: 新宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'times new roman'; mso-no-proof: yes">9F</span></chmetcnv> push eax

00411AA0 mov ecx,dword ptr [d]

00411AA3 push ecx

00411AA4 mov edx,dword ptr [c]

00411AA7 push edx

00411AA8 mov eax,dword ptr [b]

00411AAB push eax

00411AAC mov ecx,dword ptr [a]

00411AAF push ecx

用Fun2

00411AB0 call Fun2 (4111D6h) ;Call调用时将下一行命令的EIP压入堆栈

00411AB5 add esp,14h ;恢复因为参数入栈改变的栈指针,因为Fun25个参数,一个整数4个字节,14h(20)个字节

Fun2函数的返回值(保存在eax),赋值给f;

00411AB8 mov dword ptr [f],eax

return f;

将保留在f中的Fun1的返回值保存在eax中返回

00411ABB mov eax,dword ptr [f]

}

恢复现场

00411ABE pop edi

00411ABF pop esi

<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="411" unitname="ac"><span lang="en-us" style="font-size: 12pt; font-family: 新宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'times new roman'; mso-no-proof: yes">00411AC</span></chmetcnv>0 pop ebx

以下全为运行时ESP检查:

先恢复因为预留函数存储控件而改变的栈指针,

<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="411" unitname="ac"><span lang="en-us" style="font-size: 12pt; font-family: 新宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'times new roman'; mso-no-proof: yes">00411AC</span></chmetcnv>1 add esp,0E4h

再比较ebp,esp,假如程序运行正确,两个值应该相等.

<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="411" unitname="ac"><span lang="en-us" style="font-size: 12pt; font-family: 新宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'times new roman'; mso-no-proof: yes">00411AC</span></chmetcnv>7 cmp ebp,esp

<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="411" unitname="ac"><span lang="en-us" style="font-size: 12pt; font-family: 新宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'times new roman'; mso-no-proof: yes">00411AC</span></chmetcnv>9 call @ILT+320(__RTC_CheckEsp) (411145h)

正常时只需要以下两句就可以正常恢复esp,再出栈,又可以恢复ebp.

00411ACE mov esp,ebp

00411AD0 pop ebp

返回mainpop堆栈中的EIP开始执行

00411AD1 ret

int Fun2(int a, int b, int c, int d, int e)

{

同上理解, 保存现场

00412050 push ebp

00412051 mov ebp,esp

00412053 sub esp,0E4h ;保留0E4H(228)

00412059 push ebx

<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="41205" unitname="a"><span lang="en-us" style="font-size: 12pt; font-family: 新宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'times new roman'; mso-no-proof: yes">0041205A</span></chmetcnv> push esi

0041205B push edi

<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="41205" unitname="c"><span lang="en-us" style="font-size: 12pt; font-family: 新宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'times new roman'; mso-no-proof: yes">0041205C</span></chmetcnv> lea edi,[ebp-0E4h]

00412062 mov ecx,39h ; 39H(57)*4 = 0E4H(228)

00412067 mov eax,0CCCCCCCCh

<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="41206" unitname="c"><span lang="en-us" style="font-size: 12pt; font-family: 新宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'times new roman'; mso-no-proof: yes">0041206C</span></chmetcnv> rep stos dword ptr es:[edi]

int f = 6, g = 7;

定义变量

0041206E mov dword ptr [f],6

00412075 mov dword ptr [g],7

int h = a + b + c + d + e + f + g;

相加,存入a,再保存在h

<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="41207" unitname="c"><span lang="en-us" style="font-size: 12pt; font-family: 新宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'times new roman'; mso-no-proof: yes">0041207C</span></chmetcnv> mov eax,dword ptr [a]

<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="41207" unitname="f"><span lang="en-us" style="font-size: 12pt; font-family: 新宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'times new roman'; mso-no-proof: yes">0041207F</span></chmetcnv> add eax,dword ptr [b]

00412082 add eax,dword ptr [c]

00412085 add eax,dword ptr [d]

00412088 add eax,dword ptr [e]

0041208B add eax,dword ptr [f]

0041208E add eax,dword ptr [g]

00412091 mov dword ptr [h],eax

return h;

将返回值h的值保存在eax

00412094 mov eax,dword ptr [h]

}

恢复现场

00412097 pop edi

00412098 pop esi

00412099 pop ebx

<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="41209" unitname="a"><span lang="en-us" style="font-size: 12pt; font-family: 新宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'times new roman'; mso-no-proof: yes">0041209A</span></chmetcnv> mov esp,ebp

<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="false" hasspace="false" sourcevalue="41209" unitname="c"><span lang="en-us" style="font-size: 12pt; font-family: 新宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'times new roman'; mso-no-proof: yes">0041209C</span></chmetcnv> pop ebp

0041209D ret ;回fun1 ,pop堆栈中的EIP开始执行
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值