转-从逆向工程的角度来看C++ (六)-热血打工人社区-弘客联盟新手区-弘客联盟

转-从逆向工程的角度来看C++ (六)

链 接:http://bbs.pediy.com/showthread.php?t=87592
进入本次正题:

                           (六)[  C++ 之 命名控制  ]

static int i; 这种静态变量是在.data段中的.

我们来看下在类中使用静态成员.

// Lesson6.cpp : Defines the entry point for the console application.
//

#include “stdafx.h”
#include <iostream.h>
#include <windows.h>

class X
{
int i;
public:
X(int I = 0):i(I){cout << “X::X()”<< endl;} //
~X(){cout << “X::~X()”<< endl;exit(1);cout << “X::~X()”<< endl;}

friend void f();
};

void f()
{
static X x1(47);
cout<<&x1<<“-“<<sizeof(x1)<<“-“<<x1.i<<endl;
}

int main(int argc, char* argv[])
{
// __asm int 3
f();
return 0;
}

函数f中定义了一个静态的对象. 对于静态对象:

1.程序控制第一次转到对象的定义点时, 而且只有在第一次时, 才需要执行构造函数.

2.静态对象的析构函数(包括静态存储的所有对象,不仅仅是上例中的局部静态变量)在程序从main() 块中退出时,或者标准的C库函数e x i t ( )被调用时才被调用, 实验证明析构函数调用发生在exit 栈帧中,_exit栈帧外.

实验说明:

当析构为:~X(){cout << “X::~X()”<< endl;}时: 输出为:

X::X()
0x0042E060-4-47
X::~X()

当析构为~X(){cout << “X::~X()”<< endl;_exit(1);}时,输出为:

X::X()
0x0042E060-4-47
X::~X()

当析构为~X(){cout << “X::~X()”<< endl;exit(1);}时,输出为:
X::X()
0x0042E060-4-47
X::~X()

X::~X()

X::~X()

X::~X()

… …

发生了嵌套调用了.

//再来看看这个CPP:

// Lesson6.cpp : Defines the entry point for the console application.
//

#include “stdafx.h”
#include <iostream.h>

int x = 100;
class X
{
static int i;
static int j;
public:
void X::prt() const
{
   i *=100;
   j *=100;
   cout << “i = ” << i <<endl;
   cout << “j = ” << j <<endl;
}
static void X::f()
{
   cout << “sum = ” << i+j <<endl;
}
};

int X::i = 9;
int X::j = x + 1;

int main(int argc, char* argv[])
{
__asm int 3
X x;
cout << “sizeof X = “<< sizeof(x) <<endl ;
x.prt();
X::f();
return 0;
}

//Dasm:

004010C0 > 55              push ebp
004010C1    8BEC            mov ebp,esp
004010C3    83EC 44         sub esp,44
004010C6    53              push ebx
004010C7    56              push esi
004010C8    57              push edi
004010C9    8D7D BC         lea edi,dword ptr ss:[ebp-44]
004010CC    B9 11000000     mov ecx,11
004010D1    B8 CCCCCCCC     mov eax,CCCCCCCC
004010D6    F3:AB           rep stos dword ptr es:[edi]
004010D8    90              nop
004010D9    68 0F104000     push Lesson6.0040100F                    ; endl
004010DE    6A 01           push 1                                   ; sizeof(X)
004010E0    68 F0904200     push Lesson6.004290F0                    ; ASCII “sizeof X = “
004010E5    B9 68E34200     mov ecx,offset Lesson6.cout
004010EA    E8 11C80000     call Lesson6.ostream:perator<<
004010EF    8BC8            mov ecx,eax
004010F1    E8 EA050100     call Lesson6.ostream:perator<<
004010F6    8BC8            mov ecx,eax
004010F8    E8 08FFFFFF     call Lesson6.00401005
004010FD    8D4D FC         lea ecx,dword ptr ss:[ebp-4]             ; 传this
00401100    E8 0FFFFFFF     call Lesson6.00401014                    ; 非静态方法 X::prt()
00401105    E8 19FFFFFF     call Lesson6.00401023                    ; 静态方法X::f()
0040110A    33C0            xor eax,eax                              ; Lesson6.cout
0040110C    5F              pop edi
0040110D    5E              pop esi
0040110E    5B              pop ebx
0040110F    83C4 44         add esp,44
00401112    3BEC            cmp ebp,esp
00401114    E8 E7010000     call Lesson6._chkesp
00401119    8BE5            mov esp,ebp
0040111B    5D              pop ebp
0040111C    C3              retn

////Release

00401020    90              nop
00401021    6A 01           push 1                                   ; sizeof(x)
00401023    68 70904000     push Lesson6.00409070                    ; ASCII “sizeof X = “
00401028    B9 98BB4000     mov ecx,Lesson6.0040BB98                 ; cout
0040102D    E8 493C0000     call Lesson6.00404C7B                    ; <<
00401032    8BC8            mov ecx,eax
00401034    E8 EE3A0000     call Lesson6.00404B27                    ; <<
00401039    68 30114000     push Lesson6.00401130
0040103E    6A 0A           push 0A
00401040    8BC8            mov ecx,eax
00401042    E8 423A0000     call Lesson6.00404A89
00401047    8BC8            mov ecx,eax
00401049    E8 C2000000     call Lesson6.00401110
0040104E    A1 54904000     mov eax,dword ptr ds:[409054]            ; 成员变量 i 赤裸于此
00401053    8B0D E0B94000   mov ecx,dword ptr ds:[40B9E0]            ; 成员变量 j 赤裸于此
00401059    8D0480          lea eax,dword ptr ds:[eax+eax*4]         ; i *=5
0040105C    8D0C89          lea ecx,dword ptr ds:[ecx+ecx*4]
0040105F    8D0480          lea eax,dword ptr ds:[eax+eax*4]         ; i *= 5
00401062    8D0C89          lea ecx,dword ptr ds:[ecx+ecx*4]
00401065    C1E0 02         shl eax,2                                ; * 4
00401068    C1E1 02         shl ecx,2
0040106B    890D E0B94000   mov dword ptr ds:[40B9E0],ecx            ; 写回 静态的 j
00401071    50              push eax
00401072    68 68904000     push Lesson6.00409068                    ; ASCII “i = “
00401077    B9 98BB4000     mov ecx,Lesson6.0040BB98                 ; cout 地址,ecx传参
0040107C    A3 54904000     mov dword ptr ds:[409054],eax            ; 写回 静态的 i
00401081    E8 F53B0000     call Lesson6.00404C7B                    ; <<
00401086    8BC8            mov ecx,eax
00401088    E8 4B390000     call Lesson6.004049D8                    ; <<
0040108D    68 30114000     push Lesson6.00401130
00401092    6A 0A           push 0A
00401094    8BC8            mov ecx,eax                              ; <<
00401096    E8 EE390000     call Lesson6.00404A89
0040109B    8BC8            mov ecx,eax
0040109D    E8 6E000000     call Lesson6.00401110
004010A2    8B15 E0B94000   mov edx,dword ptr ds:[40B9E0]            ; j
004010A8    B9 98BB4000     mov ecx,Lesson6.0040BB98
004010AD    52              push edx
004010AE    68 60904000     push Lesson6.00409060                    ; ASCII “j = “
004010B3    E8 C33B0000     call Lesson6.00404C7B                    ; <<
004010B8    8BC8            mov ecx,eax
004010BA    E8 19390000     call Lesson6.004049D8                    ; <<
004010BF    68 30114000     push Lesson6.00401130
004010C4    6A 0A           push 0A
004010C6    8BC8            mov ecx,eax
004010C8    E8 BC390000     call Lesson6.00404A89
004010CD    8BC8            mov ecx,eax
004010CF    E8 3C000000     call Lesson6.00401110
004010D4    A1 54904000     mov eax,dword ptr ds:[409054]
004010D9    8B0D E0B94000   mov ecx,dword ptr ds:[40B9E0]
004010DF    03C8            add ecx,eax
004010E1    51              push ecx
004010E2    68 58904000     push Lesson6.00409058                    ; ASCII “sum = “
004010E7    B9 98BB4000     mov ecx,Lesson6.0040BB98                 ; cout
004010EC    E8 8A3B0000     call Lesson6.00404C7B                    ; <<
004010F1    8BC8            mov ecx,eax
004010F3    E8 E0380000     call Lesson6.004049D8
004010F8    68 30114000     push Lesson6.00401130
004010FD    6A 0A           push 0A
004010FF    8BC8            mov ecx,eax
00401101    E8 83390000     call Lesson6.00404A89
00401106    8BC8            mov ecx,eax
00401108    E8 03000000     call Lesson6.00401110
0040110D    33C0            xor eax,eax                              ; Lesson6.0040BB98
0040110F    C3              retn

小结:Release版本的优化了不少, 看的出来, Release合并了一些简单的成员函数.

另: 静态方法直接call全局地址. 跟普通方法没区别;

还有sizeof(X) 的值为1 , 象征性的1. X x 该局部变量也就一个DWORD. 而且还是cccccccc填充, 根本没用这个值.
面向对象始终还是为编译器服务的.静态成员都是赤裸裸的.data段数据调用类静态方法也是不需要传this指针 .

到了这里,静态嵌套类也不用做实验了, 理解了思想, 就理解了一切, 什么东西都是一样的 .

请登录后发表评论

    没有回复内容

随便看看