您的位置:首页 > 其它

函数调用时的栈帧结构以及临时变量的深入研究

2011-12-17 17:41 399 查看
C++代码:
#include<iostream>
#include<string>
using namespace std;

class base
{
public:
base():id(0){}
base(int i):id(i){}
base(const base &orig):id(orig.id){cout << "called copy constructor" << endl;}
private:
int id;
};
base func(base a)
{
base tem(a);
return tem;
}
int main()
{
base mb1(7),mb2;
mb2 = func(mb1);
return 0;
}


对应汇编代码:

19:   int main()
20:   {
00401270   push        ebp
00401271   mov         ebp,esp
00401273   sub         esp,50h
00401276   push        ebx
00401277   push        esi
00401278   push        edi
00401279   lea         edi,[ebp-50h]
0040127C   mov         ecx,14h
00401281   mov         eax,0CCCCCCCCh
00401286   rep stos    dword ptr [edi]
21:       base mb1(7),mb2;
00401288   push        7
0040128A   lea         ecx,[ebp-4]  //这里就是指定空间来装mb1,地址是0x0012ff7c,以ebp为基址向下偏移4个字节处
0040128D   call        @ILT+105(base::base) (0040106e)//指定了空间后就调用构造函数来填充
00401292   lea         ecx,[ebp-8]  //这里指定空间来装mb2,地址是0x0012ff78,同样以ebp为基址向下偏移8个字节处
00401295   call        @ILT+85(base::base) (0040105a)//指定了空间后就调用构造函数来填充
22:       mb2 = func(mb1);
0040129A   push        ecx
0040129B   mov         ecx,esp
0040129D   lea         eax,[ebp-4]
004012A0   push        eax
004012A1   call        @ILT+150(base::base) (0040109b)
004012A6   lea         ecx,[ebp-10h]//将ebp-10h得到一个地址,也就是0x0012ff70赋给ecx
004012A9   push        ecx          //在栈上保存这个地址
004012AA   call        @ILT+30(func) (00401023)
004012AF   add         esp,8
004012B2   mov         edx,dword ptr [eax]
004012B4   mov         dword ptr [ebp-8],edx
23:       return 0;
004012B7   xor         eax,eax
24:   }
004012B9   pop         edi
004012BA   pop         esi
004012BB   pop         ebx
004012BC   add         esp,50h
004012BF   cmp         ebp,esp
004012C1   call        __chkesp (00409190)
004012C6   mov         esp,ebp
004012C8   pop         ebp
004012C9   ret

base func(base a)
15:   {
00401190   push        ebp
00401191   mov         ebp,esp
00401193   sub         esp,44h
00401196   push        ebx
00401197   push        esi
00401198   push        edi
00401199   lea         edi,[ebp-44h]
0040119C   mov         ecx,11h
004011A1   mov         eax,0CCCCCCCCh
004011A6   rep stos    dword ptr [edi]
16:       base tem(a);
004011A8   lea         eax,[ebp+0Ch]//这个地方,ebp+0ch后恰好是压入的实参地址
004011AB   push        eax          //这里也是实参进栈为调用构造函数作准备
004011AC   lea         ecx,[ebp-4]  //这里为局部变量tem找一个容纳地址,以ebp为基址向下偏移4个字节处
004011AF   call        @ILT+150(base::base) (0040109b)//调用构造函数进行填充
17:       return tem;
004011B4   lea         ecx,[ebp-4]  //取地址放入ecx
004011B7   push        ecx
004011B8   mov         ecx,dword ptr [ebp+8]//取ebp向上偏移8个字节处的地址里面的地址值赋给ecx,这个地址是0x0012ff70
004011BB   call        @ILT+150(base::base) (0040109b)//调用构造函数进行填充,也就是填充0x0012ff70
004011C0   mov         eax,dword ptr [ebp+8]//将临时变量地址放入到eax
18:   }
004011C3   pop         edi
004011C4   pop         esi
004011C5   pop         ebx
004011C6   add         esp,44h
004011C9   cmp         ebp,esp
004011CB   call        __chkesp (00409190)
004011D0   mov         esp,ebp
004011D2   pop         ebp
004011D3   ret


栈帧结构图:



这里只讨论了main函数和func函数的栈帧结构,构造函数调用时的栈帧结构没有讨论,函数调用完之后都会清栈,所以我们可以单独的研究这两个函数的栈帧,对于其中调用的构造函数可以不予理会。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐