Nisy 发表于 2010-2-2 12:17:33

一些隐藏的临时对象

I 当类对象传参时

//////////////////////////////////////////////////////////////////////////
//源码
//////////////////////////////////////////////////////////////////////////

class Test
{
public:
        int m_nData;
        int m_test;
public:
        Test(int nData):m_nData(nData){}
        ~Test(){;}
public:
        void SetData(Test ttp)
        {
                m_nData = ttp.m_nData;
        }
};

void SetData(Test ttp)
{
        ;
}

int main(int argc, char* argv[])
{
        // printf("Hello World!\n");
        Test tt(10);
        tt.SetData(20);
        return 0;
}

//////////////////////////////////////////////////////////////////////////
//简单分析
//////////////////////////////////////////////////////////////////////////

29:       Test tt(10);
004010DD   push      0Ah
004010DF   lea         ecx,
004010E2   call      @ILT+0(Test::Test) (00401005)
004010E7   mov         dword ptr ,0
30:       tt.SetData(20);
004010EE   sub         esp,8        // 申请空间
004010F1   mov         ecx,esp
004010F3   mov         dword ptr ,esp
004010F6   push      14h
004010F8   call      @ILT+0(Test::Test) (00401005)        // 在这里 retn 4 只是弹出 push 14
004010FD   mov         dword ptr ,eax
00401100   lea         ecx,
00401103   call      @ILT+5(Test::SetData) (0040100a)   // 所以该函数中 ebp+8 就是tempobj的this指针
31:       return 0;
00401108   mov         dword ptr ,0
0040110F   mov         dword ptr ,0FFFFFFFFh
00401116   lea         ecx,
00401119   call      @ILT+10(Test::~Test) (0040100f)
0040111E   mov         eax,dword ptr
32:   }


15:       void SetData(Test ttp)
16:       {
004011BA   mov         dword ptr ,ecx
17:         m_nData = ttp.m_nData;
004011BD   mov         eax,dword ptr
004011C0   mov         ecx,dword ptr         // 临时对象地址
004011C3   mov         dword ptr ,ecx
18:       }
004011C5   lea         ecx,
004011C8   call      @ILT+10(Test::~Test) (0040100f)// 给与析构
}


当参数为对象时,先 sub esp,sizeof(obj) 申请出空间,然后进行构造再调用函数。
构造退出时,ESP既是对象的this指针,函数内ESP+8即可对临时变量进行寻址。
临时对象出函数作用域时进行析构。

Nisy 发表于 2010-2-2 13:08:08

38:       tt = GetData(30);
0040E9E8   push      1Eh
0040E9EA   lea         eax,                        // 把返回对象的地址压入堆栈
0040E9ED   push      eax
0040E9EE   call      @ILT+30(GetData) (00401023)   //
0040E9F3   add         esp,8
0040E9F6   mov         dword ptr ,eax        // 返回的临时对象
0040E9F9   mov         ecx,dword ptr                 // 开始按位COPY
0040E9FC   mov         edx,dword ptr
0040E9FE   mov         eax,dword ptr          
0040EA01   mov         dword ptr ,edx
0040EA04   mov         dword ptr ,eax                // Copy 函数结束
0040EA07   lea         ecx,
0040EA0A   call      @ILT+10(Test::~Test) (0040100f)

// 编译器的编译原则(申请空间)
// 把函数当返回值来看待 以决定该变量所需要的空间
// 若返回值为对象 则压入的参数个数 + 1


call      @ILT+30(GetData) (00401023)
{
29:       Test temp(nData);
004010E4   mov         eax,dword ptr
004010E7   push      eax
004010E8   lea         ecx,                        // 局部变量的空间
004010EB   call      @ILT+0(Test::Test) (00401005)
30:       return temp;
004010F0   mov         ecx,dword ptr                 // 参数
004010F3   mov         edx,dword ptr                 // 赋值(续表)
004010F6   mov         dword ptr ,edx                // 赋值(m_nData)
004010F8   mov         eax,dword ptr
004010FB   mov         dword ptr ,eax
004010FE   mov         ecx,dword ptr
00401101   or          ecx,1
00401104   mov         dword ptr ,ecx
00401107   lea         ecx,
0040110A   call      @ILT+10(Test::~Test) (0040100f) // 赋值OVER后 析构掉函数内部的局部对象)
0040110F   mov         eax,dword ptr
31:   }
页: [1]
查看完整版本: 一些隐藏的临时对象