IT공부/IT서적

[윤성우 열혈 C++프로그래밍] 어셈블리 코드 - Chapter5, Chapter6

shine94 2025. 4. 2. 23:28

* 복사 생성자를 정의하지 않으면,

   멤버 대 멤버의 복사를 진행하는 디폴트 복사 생성자가 자동으로 삽입

 

* 복사 생성자가 호출되는 시점

   (1) 기존에 생성된 객체를 이용해서 새로운 객체를 초기화하는 경우

   (2) Call-by-value 방식의 함수호출 과정에서 객체를 인자로 전달하는 경우

   (3) 객체를 반환하되, 참조형으로 반환하지 않는 경우(즉, 값으로 반환하는 경우)

 

int main(void)
{
008B10C0  push        ebp  
008B10C1  mov         ebp,esp  
008B10C3  sub         esp,0Ch  
008B10C6  mov         eax,dword ptr [__security_cookie (08B5000h)]  
008B10CB  xor         eax,ebp  
008B10CD  mov         dword ptr [ebp-4],eax  
	SoSimple obj(7, 3);
008B10D0  push        3  
008B10D2  push        7  
008B10D4  lea         ecx,[obj]  
008B10D7  call        SoSimple::SoSimple (08B1000h)  
	cout << "함수 호출 전" << endl;
008B10DC  push        offset std::endl<char,std::char_traits<char> > (08B14C0h)  
008B10E1  push        8B3178h  
008B10E6  mov         eax,dword ptr [__imp_std::cout (08B3074h)]  
008B10EB  push        eax  
008B10EC  call        std::operator<<<std::char_traits<char> > (08B11D0h)  
008B10F1  add         esp,8  
008B10F4  mov         ecx,eax  
008B10F6  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (08B3040h)]  
008B10FC  nop  

	SimpleFuncObj(obj);
008B10FD  sub         esp,8  
008B1100  mov         ecx,esp  
008B1102  lea         edx,[obj]  
008B1105  push        edx  
008B1106  call        SoSimple::SoSimple (08B1030h)  
008B110B  call        SimpleFuncObj (08B10B0h)  
008B1110  add         esp,8  
	cout << "함수 호출 후" << endl;
008B1113  push        offset std::endl<char,std::char_traits<char> > (08B14C0h)  
008B1118  push        8B3188h  
008B111D  mov         eax,dword ptr [__imp_std::cout (08B3074h)]  
008B1122  push        eax  
008B1123  call        std::operator<<<std::char_traits<char> > (08B11D0h)  
008B1128  add         esp,8  
008B112B  mov         ecx,eax  
008B112D  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (08B3040h)]  

	return 0;
008B1133  xor         eax,eax  
}
008B1135  mov         ecx,dword ptr [ebp-4]  
008B1138  xor         ecx,ebp  
008B113A  call        __security_check_cookie (08B16FAh)  
008B113F  mov         esp,ebp  
008B1141  pop         ebp  
008B1142  ret

 

* 매개변수 객체 값 복사를 위해 복사 생성자를 먼저 호출해서 스택에 복사 후 SimpleFuncObj 함수 호출
   008B10FD  sub         esp,8
   008B1100  mov         ecx,esp
   008B1102  lea         edx,[obj]  
   008B1105  push        edx  
   008B1106  call        SoSimple::SoSimple (08B1030h)
   008B110B  call        SimpleFuncObj (08B10B0h)

 

int main(void)
{
009311A0  push        ebp  
009311A1  mov         ebp,esp  
009311A3  sub         esp,14h  
009311A6  mov         eax,dword ptr [__security_cookie (0935000h)]  
009311AB  xor         eax,ebp  
009311AD  mov         dword ptr [ebp-4],eax  
	SoSimple obj(7);
009311B0  push        7  
009311B2  lea         ecx,[obj]  
009311B5  call        SoSimple::SoSimple (0931080h)  
009311BA  nop  
	SimpleFunObj(obj).AddNum(30).ShowData();
009311BB  push        1Eh  
009311BD  sub         esp,8  
009311C0  mov         ecx,esp  
009311C2  lea         eax,[obj]  
009311C5  push        eax  
009311C6  call        SoSimple::SoSimple (09310B0h)  
009311CB  lea         ecx,[ebp-14h]  
009311CE  push        ecx  
009311CF  call        SimpleFunObj (0931160h)  
009311D4  add         esp,0Ch  
009311D7  mov         ecx,eax  
009311D9  call        SoSimple::AddNum (0931100h)  
009311DE  mov         ecx,eax  
009311E0  call        SoSimple::ShowData (0931120h)  
009311E5  nop  

	printf("==================================\n");
009311E6  push        933184h  
009311EB  call        printf (0931040h)  
009311F0  add         esp,4  

	obj.ShowData();
009311F3  lea         ecx,[obj]  
009311F6  call        SoSimple::ShowData (0931120h)  
	return 0;
009311FB  xor         eax,eax  
}
009311FD  mov         ecx,dword ptr [ebp-4]  
00931200  xor         ecx,ebp  
00931202  call        __security_check_cookie (09317B3h)  
00931207  mov         esp,ebp  
00931209  pop         ebp  
0093120A  ret

///////////////////////////////////////////////////////////

SoSimple SimpleFunObj(SoSimple ob)
{
00931160  push        ebp  
00931161  mov         ebp,esp  
	cout << "return 이전" << endl;
00931163  push        offset std::endl<char,std::char_traits<char> > (0931780h)  
00931168  push        933178h  
0093116D  mov         eax,dword ptr [__imp_std::cout (0933078h)]  
00931172  push        eax  
00931173  call        std::operator<<<std::char_traits<char> > (0931490h)  
00931178  add         esp,8  
0093117B  mov         ecx,eax  
0093117D  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (0933044h)]  
	return ob;
00931183  lea         ecx,[ob]  
00931186  push        ecx  
00931187  mov         ecx,dword ptr [ebp+8]  
0093118A  call        SoSimple::SoSimple (09310B0h)  
0093118F  mov         eax,dword ptr [ebp+8]  
}
00931192  pop         ebp  
00931193  ret

 

* 매개변수 객체 값 복사를 위해 복사 생성자를 먼저 호출해서 스택에 복사 후 SimpleFuncObj 함수 호출

   009311BB  push        1Eh  
   009311BD  sub         esp,8  
   009311C0  mov         ecx,esp  
   009311C2  lea         eax,[obj]  
   009311C5  push        eax  
   009311C6  call        SoSimple::SoSimple (09310B0h)
   009311CB  lea         ecx,[ebp-14h]       // 객체를 리턴하기 위한 임시공간

                                                                  // SimpleFunObj 함수 안에서 객체 리턴을 위한 복사 생성자를 호출
   009311CE  push        ecx  
   009311CF  call        SimpleFunObj (0931160h)  
   009311D4  add         esp,0Ch  
   009311D7  mov         ecx,eax  
   009311D9  call        SoSimple::AddNum (0931100h)  
   009311DE  mov         ecx,eax  
   009311E0  call        SoSimple::ShowData (0931120h)  
   009311E5  nop 

 

* SimpleFunObj 함수 안에서 객체 리턴을 위한 복사 생성자를 호출

   00931183  lea         ecx,[ob]  
   00931186  push        ecx  
   00931187  mov         ecx,dword ptr [ebp+8]      // 이전 함수프레임에서 저장, 객체를 리턴을 위한 임시공간 주소

   0093118A  call        SoSimple::SoSimple (09310B0h)
   0093118F  mov         eax,dword ptr [ebp+8]  

 

* 임시 객체는 다음 행으로 넘어가면 바로 소멸된다

 

* 참조자에 참조되는 임시객체는 바로 소멸되지 않는다

 

int main(void)
{
005A1100  push        ebp  
005A1101  mov         ebp,esp  
005A1103  push        0FFFFFFFFh  
005A1105  push        5A2635h  
005A110A  mov         eax,dword ptr fs:[00000000h]  
005A1110  push        eax  
005A1111  sub         esp,20h  
005A1114  mov         eax,dword ptr [__security_cookie (05A5000h)]  
005A1119  xor         eax,ebp  
005A111B  mov         dword ptr [ebp-10h],eax  
005A111E  push        eax  
005A111F  lea         eax,[ebp-0Ch]  
005A1122  mov         dword ptr fs:[00000000h],eax  
	Temporary(100);
005A1128  push        64h  
005A112A  lea         ecx,[ebp-18h]  
005A112D  call        Temporary::Temporary (05A1000h)  
005A1132  lea         ecx,[ebp-18h]  
005A1135  call        Temporary::~Temporary (05A1050h)  
005A113A  nop  
	cout << sizeof(Temporary(100)) << endl;
005A113B  push        offset std::endl<char,std::char_traits<char> > (05A17E0h)  
005A1140  push        4  
005A1142  mov         ecx,dword ptr [__imp_std::cout (05A307Ch)]  
005A1148  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (05A303Ch)]  
005A114E  mov         ecx,eax  
005A1150  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (05A3048h)]  
	cout << "================================" << endl << endl;
005A1156  push        offset std::endl<char,std::char_traits<char> > (05A17E0h)  
005A115B  push        offset std::endl<char,std::char_traits<char> > (05A17E0h)  
005A1160  push        5A317Ch  
005A1165  mov         eax,dword ptr [__imp_std::cout (05A307Ch)]  
005A116A  push        eax  
005A116B  call        std::operator<<<std::char_traits<char> > (05A14F0h)  
005A1170  add         esp,8  
005A1173  mov         ecx,eax  
005A1175  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (05A3048h)]  
005A117B  mov         ecx,eax  
005A117D  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (05A3048h)]  
005A1183  nop  

	Temporary(100).ShowTempInfo();
005A1184  push        64h  
005A1186  lea         ecx,[ebp-24h]  
005A1189  call        Temporary::Temporary (05A1000h)  
005A118E  mov         dword ptr [ebp-1Ch],eax  
005A1191  mov         ecx,dword ptr [ebp-1Ch]  
005A1194  mov         dword ptr [ebp-20h],ecx  
005A1197  mov         dword ptr [ebp-4],0  
005A119E  mov         ecx,dword ptr [ebp-20h]  
005A11A1  call        Temporary::ShowTempInfo (05A10C0h)  
005A11A6  mov         dword ptr [ebp-4],0FFFFFFFFh  
005A11AD  lea         ecx,[ebp-24h]  
005A11B0  call        Temporary::~Temporary (05A1050h)  
005A11B5  nop  
	cout << "================================" << endl << endl;
005A11B6  push        offset std::endl<char,std::char_traits<char> > (05A17E0h)  
005A11BB  push        offset std::endl<char,std::char_traits<char> > (05A17E0h)  
005A11C0  push        5A31A0h  
005A11C5  mov         edx,dword ptr [__imp_std::cout (05A307Ch)]  
005A11CB  push        edx  
005A11CC  call        std::operator<<<std::char_traits<char> > (05A14F0h)  
005A11D1  add         esp,8  
005A11D4  mov         ecx,eax  
005A11D6  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (05A3048h)]  
005A11DC  mov         ecx,eax  
005A11DE  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (05A3048h)]  

	const Temporary& ref = Temporary(100);
005A11E4  push        64h  
005A11E6  lea         ecx,[ebp-14h]  
005A11E9  call        Temporary::Temporary (05A1000h)  
005A11EE  mov         dword ptr [ebp-4],1  
005A11F5  lea         eax,[ebp-14h]  
005A11F8  mov         dword ptr [ref],eax  
	cout << sizeof(ref) << " end main" << endl << endl;
005A11FB  push        offset std::endl<char,std::char_traits<char> > (05A17E0h)  
005A1200  push        offset std::endl<char,std::char_traits<char> > (05A17E0h)  
005A1205  push        5A31C4h  
005A120A  push        4  
005A120C  mov         ecx,dword ptr [__imp_std::cout (05A307Ch)]  
005A1212  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (05A303Ch)]  
005A1218  push        eax  
005A1219  call        std::operator<<<std::char_traits<char> > (05A14F0h)  
005A121E  add         esp,8  
005A1221  mov         ecx,eax  
005A1223  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (05A3048h)]  
005A1229  mov         ecx,eax  
005A122B  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (05A3048h)]  
005A1231  nop  

	return 0;
005A1232  mov         dword ptr [ebp-28h],0  
005A1239  mov         dword ptr [ebp-4],0FFFFFFFFh  
005A1240  lea         ecx,[ebp-14h]  
005A1243  call        Temporary::~Temporary (05A1050h)  
005A1248  mov         eax,dword ptr [ebp-28h]  
}
005A124B  mov         ecx,dword ptr [ebp-0Ch]  
005A124E  mov         dword ptr fs:[0],ecx  
005A1255  pop         ecx  
005A1256  mov         ecx,dword ptr [ebp-10h]  
005A1259  xor         ecx,ebp  
005A125B  call        __security_check_cookie (05A1813h)  
005A1260  mov         esp,ebp  
005A1262  pop         ebp  
005A1263  ret

 

* cout << sizeof(Temporary(100)) << endl;

   sizeof는 컴파일 타임에 크기를 계산하는 연산자이고,

   컴파일러는 해당 타입의 크기만 알면 되기 때문에 생성자 호출 없이 타입 정보를 이용해 크기를 계산한다

 

int main(void)
{
003B11B0  push        ebp  
003B11B1  mov         ebp,esp  
003B11B3  push        0FFFFFFFFh  
003B11B5  push        3B2695h  
003B11BA  mov         eax,dword ptr fs:[00000000h]  
003B11C0  push        eax  
003B11C1  sub         esp,1Ch  
003B11C4  mov         eax,dword ptr [__security_cookie (03B5000h)]  
003B11C9  xor         eax,ebp  
003B11CB  mov         dword ptr [ebp-10h],eax  
003B11CE  push        eax  
003B11CF  lea         eax,[ebp-0Ch]  
003B11D2  mov         dword ptr fs:[00000000h],eax  
	SoSimple obj(7);
003B11D8  push        7  
003B11DA  lea         ecx,[obj]  
003B11DD  call        SoSimple::SoSimple (03B1000h)  
003B11E2  mov         dword ptr [ebp-4],0  
	SimpleFuncObj(obj);
003B11E9  push        ecx  
003B11EA  mov         ecx,esp  
003B11EC  mov         dword ptr [ebp-24h],esp  
003B11EF  lea         eax,[obj]  
003B11F2  push        eax  
003B11F3  call        SoSimple::SoSimple (03B1050h)  
003B11F8  lea         ecx,[ebp-1Ch]  
003B11FB  push        ecx  
003B11FC  call        SimpleFuncObj (03B1110h)  
003B1201  add         esp,8  
003B1204  mov         dword ptr [ebp-28h],eax  
003B1207  lea         ecx,[ebp-1Ch]  
003B120A  call        SoSimple::~SoSimple (03B10A0h)  
003B120F  nop  

	cout << endl;
003B1210  push        offset std::endl<char,std::char_traits<char> > (03B1810h)  
003B1215  mov         ecx,dword ptr [__imp_std::cout (03B3078h)]  
003B121B  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (03B3044h)]  
	SoSimple temRef = SoSimple(obj);
003B1221  lea         edx,[obj]  
003B1224  push        edx  
003B1225  lea         ecx,[temRef]  
003B1228  call        SoSimple::SoSimple (03B1050h)  
003B122D  mov         byte ptr [ebp-4],1  
	cout << "Return Obj " << &temRef << endl;
003B1231  push        offset std::endl<char,std::char_traits<char> > (03B1810h)  
003B1236  lea         eax,[temRef]  
003B1239  push        eax  
003B123A  push        3B3188h  
003B123F  mov         ecx,dword ptr [__imp_std::cout (03B3078h)]  
003B1245  push        ecx  
003B1246  call        std::operator<<<std::char_traits<char> > (03B1520h)  
003B124B  add         esp,8  
003B124E  mov         ecx,eax  
003B1250  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (03B3038h)]  
003B1256  mov         ecx,eax  
003B1258  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (03B3044h)]  
003B125E  nop  

	return 0;
003B125F  mov         dword ptr [ebp-20h],0  
003B1266  mov         byte ptr [ebp-4],0  
003B126A  lea         ecx,[temRef]  
003B126D  call        SoSimple::~SoSimple (03B10A0h)  
003B1272  mov         dword ptr [ebp-4],0FFFFFFFFh  
003B1279  lea         ecx,[obj]  
003B127C  call        SoSimple::~SoSimple (03B10A0h)  
003B1281  mov         eax,dword ptr [ebp-20h]  
}
003B1284  mov         ecx,dword ptr [ebp-0Ch]  
003B1287  mov         dword ptr fs:[0],ecx  
003B128E  pop         ecx  
003B128F  mov         ecx,dword ptr [ebp-10h]  
003B1292  xor         ecx,ebp  
003B1294  call        __security_check_cookie (03B1843h)  
003B1299  mov         esp,ebp  
003B129B  pop         ebp  
003B129C  ret 

/////////////////////////////////////////////////////////////////////////////////////////

SoSimple SimpleFuncObj(SoSimple ob)
003B113A  mov         dword ptr [ebp-4],0  
	cout << "param ADR : " << &ob << endl;
003B1141  push        offset std::endl<char,std::char_traits<char> > (03B1810h)  
003B1146  lea         eax,[ob]  
003B1149  push        eax  
003B114A  push        3B3178h  
003B114F  mov         ecx,dword ptr [__imp_std::cout (03B3078h)]  
003B1155  push        ecx  
003B1156  call        std::operator<<<std::char_traits<char> > (03B1520h)  
003B115B  add         esp,8  
003B115E  mov         ecx,eax  
003B1160  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (03B3038h)]  
003B1166  mov         ecx,eax  
003B1168  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (03B3044h)]  
	return ob;
003B116E  lea         edx,[ob]  
003B1171  push        edx  
003B1172  mov         ecx,dword ptr [ebp+8]  
003B1175  call        SoSimple::SoSimple (03B1050h)  
003B117A  mov         eax,dword ptr [ebp-10h]  
003B117D  or          eax,1  
003B1180  mov         dword ptr [ebp-10h],eax  
003B1183  mov         dword ptr [ebp-4],0FFFFFFFFh  
003B118A  lea         ecx,[ob]  
003B118D  call        SoSimple::~SoSimple (03B10A0h)  
003B1192  mov         eax,dword ptr [ebp+8]  
}
003B1195  mov         ecx,dword ptr [ebp-0Ch]  
003B1198  mov         dword ptr fs:[0],ecx  
003B119F  pop         ecx  
003B11A0  mov         esp,ebp  
003B11A2  pop         ebp  
003B11A3  ret

 

* 객체에 const 선언이 붙게 되면,

   이 객체를 대상으로 const 멤버함수만 호출이 가능하다

 

* const 선언 유무도 함수 오버로딩에 조건이 된다

 

int main(void)
{
002610B0  push        ebp  
002610B1  mov         ebp,esp  
002610B3  sub         esp,0Ch  
002610B6  mov         eax,dword ptr [__security_cookie (0265000h)]  
002610BB  xor         eax,ebp  
002610BD  mov         dword ptr [ebp-4],eax  
	SoSimple obj1(2);
002610C0  push        2  
002610C2  lea         ecx,[obj1]  
002610C5  call        SoSimple::SoSimple (0261000h)  
	const SoSimple obj2(7);
002610CA  push        7  
002610CC  lea         ecx,[obj2]  
002610CF  call        SoSimple::SoSimple (0261000h)  

	obj1.SimpleFunc();
002610D4  lea         ecx,[obj1]  
002610D7  call        SoSimple::SimpleFunc (0261020h)  
	obj2.SimpleFunc();
002610DC  lea         ecx,[obj2]  
002610DF  call        SoSimple::SimpleFunc (0261060h)  

	YourFunc(obj1);
002610E4  lea         eax,[obj1]  
002610E7  push        eax  
002610E8  call        YourFunc (02610A0h)  
002610ED  add         esp,4  
	YourFunc(obj2);
002610F0  lea         ecx,[obj2]  
002610F3  push        ecx  
002610F4  call        YourFunc (02610A0h)  
002610F9  add         esp,4  

	return 0;
002610FC  xor         eax,eax  
}
002610FE  mov         ecx,dword ptr [ebp-4]  
00261101  xor         ecx,ebp  
00261103  call        __security_check_cookie (02616B3h)  
00261108  mov         esp,ebp  
0026110A  pop         ebp  
0026110B  ret

///////////////////////////////////////////////////////////////////////

void YourFunc(const SoSimple& obj)
{
002610A0  push        ebp  
002610A1  mov         ebp,esp  
	obj.SimpleFunc();
002610A3  mov         ecx,dword ptr [obj]  
002610A6  call        SoSimple::SimpleFunc (0261060h)  
002610AB  nop  
}
002610AC  pop         ebp  
002610AD  ret

 

* friend 선언은 클래스 내에 어디든 위치할 수 있다

 

int main(void)
{
000610D0  push        ebp  
000610D1  mov         ebp,esp  
000610D3  sub         esp,1Ch  
000610D6  mov         eax,dword ptr [__security_cookie (065000h)]  
000610DB  xor         eax,ebp  
000610DD  mov         dword ptr [ebp-4],eax  
	Boy boy(170);
000610E0  push        0AAh  
000610E5  lea         ecx,[boy]  
000610E8  call        Boy::Boy (061000h)  
	Girl girl((char*)"010-1234-5678");
000610ED  push        63174h  
000610F2  lea         ecx,[girl]  
000610F5  call        Girl::Girl (061020h)  

	boy.ShowYourFriendInfo(girl);
000610FA  lea         eax,[girl]  
000610FD  push        eax  
000610FE  lea         ecx,[boy]  
00061101  call        Boy::ShowYourFriendInfo (061050h)  
	girl.ShowYourFriendInfo(boy);
00061106  lea         ecx,[boy]  
00061109  push        ecx  
0006110A  lea         ecx,[girl]  
0006110D  call        Girl::ShowYourFriendInfo (061090h)  

	return 0;
00061112  xor         eax,eax  
}
00061114  mov         ecx,dword ptr [ebp-4]  
00061117  xor         ecx,ebp  
00061119  call        __security_check_cookie (0616D3h)  
0006111E  mov         esp,ebp  
00061120  pop         ebp  
00061121  ret

 

 

* static 변수의 메모리 할당 위치

   데이터 영역에 할당된다

   프로그램이 시작될 때 메모리에 올라가고 프로그램이 종료될 때까지 유지된다

   명시적으로 초기화하지 않으면 0 으로 초기화된다 → 이건 전역변수, static 변수, static 클래스 멤버 변수 모두 해당

 

#include <iostream>
using namespace std;

void Counter()
{
00041002  in          al,dx  
	static int cnt;
	cnt++;
00041003  mov         eax,dword ptr [cnt (0453C8h)]  
00041008  add         eax,1  
0004100B  mov         dword ptr [cnt (0453C8h)],eax  
	cout << "Current cnt: " << cnt << endl;
00041010  push        offset std::endl<char,std::char_traits<char> > (0415F0h)  
00041015  mov         ecx,dword ptr [cnt (0453C8h)]  
0004101B  push        ecx  
0004101C  push        43148h  
00041021  mov         edx,dword ptr [__imp_std::cout (043078h)]  
00041027  push        edx  
00041028  call        std::operator<<<std::char_traits<char> > (041300h)  
0004102D  add         esp,8  
00041030  mov         ecx,eax  
00041032  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (043038h)]  
00041038  mov         ecx,eax  
0004103A  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (043044h)]  
00041040  nop  
}
00041041  pop         ebp  
00041042  ret  

/////////////////////////////////////////////////////////////////////////

int main(void)
{
00041050  push        ebp  
00041051  mov         ebp,esp  
00041053  push        ecx  
	for (int i = 0; i < 10; i++)
00041054  mov         dword ptr [ebp-4],0  
0004105B  jmp         main+16h (041066h)  
0004105D  mov         eax,dword ptr [ebp-4]  
00041060  add         eax,1  
00041063  mov         dword ptr [ebp-4],eax  
00041066  cmp         dword ptr [ebp-4],0Ah  
0004106A  jge         main+24h (041074h)  
	{
		Counter();
0004106C  call        Counter (041000h)  
00041071  nop  
	}
00041072  jmp         main+0Dh (04105Dh)  

	return 0;
00041074  xor         eax,eax  
}
00041076  mov         esp,ebp  
00041078  pop         ebp  
00041079  ret

 

 

* static 전역변수, static 멤버변수( = 클래스 변수), static 지역변수, static 멤버함수( = 클래스 함수)

   (1) static 전역변수

      - 파일 단위 접근 제한(링크 범위 제한)

      - 데이터 영역

      - 초기화 안하면 0으로 자동 초기화

      - 주로 전역변수의 외부 노출을 막기 위해 사용

 

   (2) static 멤버변수( = 클래스 변수)

      - 클래스 전체에서 공유

      - 객체 없이도 접근 가능(ClassName::memberField)

      - 데이터 영역

      - 초기화 안하면 0으로 자동 초기화

      - 클래스 외부에서 명시적 정의 필요

 

   (3) static 지역변수

      - 해당 함수 안에서만 사용 가능(📝 [오해 금지] 함수가 끝나도 값 유지됨)

 

      - 데이터 영역

      - 초기화는 딱 1번만 수행(함수 여러 번 호출해도 재초기화 안 함)

      - 초기화 안하면 0으로 자동 초기화

 

   (4) static 멤버함수( = 클래스 함수)

      - 클래스 전체에서 공통적으로 사용되는 함수 정의

      - 객체 없이도 접근 가능(ClassName::memberFunc)

      - 코드 영역

      - this 포인터 없음

      - 접근 가능한 대상

        ① static 멤버변수( = 클래스 변수)

        ② 함수에 전달된 인자 (일반 인자, 참조, 포인터 등 자유롭게 사용 가능)

      - non-static 멤버 변수, 멤버 함수에는 접근할 수 없음

      - 일반 함수처럼 컴파일되어 코드 영역에 배치되며, 객체 없이 독립적으로 동작한다

 

* 최적화: 사용 안 함 (/Od), 인라인 함수 확장: __inline만 확장으로 설정

   컴파일러는 inline 또는 __inline이 지정된 생성자, 소멸자, 짧은 함수는 인라인할 수 있다

   하지만 이건 컴파일러 재량이며, 기본값이나 /Ob0일 경우에는 인라인이 되지 않는다

 

int main(void)
{
007F10A0  push        ebp  
007F10A1  mov         ebp,esp  
007F10A3  sub         esp,0Ch  
007F10A6  mov         eax,dword ptr [__security_cookie (07F5000h)]  
007F10AB  xor         eax,ebp  
007F10AD  mov         dword ptr [ebp-4],eax  
	SoSimple sim1;
007F10B0  lea         ecx,[sim1]  
007F10B3  call        SoSimple::SoSimple (07F1000h)  
	SoSimple sim2;
007F10B8  lea         ecx,[sim2]  
007F10BB  call        SoSimple::SoSimple (07F1000h)  

	SoSimplex cmx1;
007F10C0  lea         ecx,[cmx1]  
007F10C3  call        SoSimplex::SoSimplex (07F1050h)  
	SoSimplex cmx2 = cmx1;
007F10C8  mov         eax,dword ptr [SoSimplex::cmxObjectCnt (07F53CCh)]  
007F10CD  add         eax,1  
007F10D0  mov         dword ptr [SoSimplex::cmxObjectCnt (07F53CCh)],eax  
007F10D5  push        offset std::endl<char,std::char_traits<char> > (07F17C0h)  
007F10DA  push        offset string "\xb9\xf8\xc2\xb0 SoSimplex \xb0\xb4\xc3\xbc - \xba\xb9\xbb\xe7 \xbb\xfd\xbc\xba@"... (07F3168h)  
007F10DF  mov         ecx,dword ptr [SoSimplex::cmxObjectCnt (07F53CCh)]  
007F10E5  push        ecx  
007F10E6  mov         ecx,dword ptr [__imp_std::cout (07F3064h)]  
007F10EC  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (07F3038h)]  
007F10F2  push        eax  
007F10F3  call        std::operator<<<std::char_traits<char> > (07F1340h)  
007F10F8  add         esp,8  
007F10FB  mov         ecx,eax  
007F10FD  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (07F3040h)]  
007F1103  nop  
	SoSimplex();
007F1104  lea         ecx,[ebp-9]  
007F1107  call        SoSimplex::SoSimplex (07F1050h)  
007F110C  nop  

	cout << &cmx2 << endl;
007F110D  push        offset std::endl<char,std::char_traits<char> > (07F17C0h)  
007F1112  lea         edx,[cmx2]  
007F1115  push        edx  
007F1116  mov         ecx,dword ptr [__imp_std::cout (07F3064h)]  
007F111C  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (07F3034h)]  
007F1122  mov         ecx,eax  
007F1124  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (07F3040h)]  

	return 0;
007F112A  xor         eax,eax  
}
007F112C  mov         ecx,dword ptr [ebp-4]  
007F112F  xor         ecx,ebp  
007F1131  call        __security_check_cookie (07F17F3h)  
007F1136  mov         esp,ebp  
007F1138  pop         ebp  
007F1139  ret

 

int main(void)
{
00131000  push        ebp  
00131001  mov         ebp,esp  
	cout << SoSimple::simObjectCnt << "번째 SoSimple 객체" << endl;
00131003  push        offset std::endl<char,std::char_traits<char> > (0131780h)  
00131008  push        133130h  
0013100D  mov         eax,dword ptr [SoSimple::simObjectCnt (01343C8h)]  
00131012  push        eax  
00131013  mov         ecx,dword ptr [__imp_std::cout (0133060h)]  
00131019  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (0133034h)]  
0013101F  push        eax  
00131020  call        std::operator<<<std::char_traits<char> > (0131300h)  
00131025  add         esp,8  
00131028  mov         ecx,eax  
0013102A  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (013303Ch)]  
	SoSimple sim1;
00131030  mov         ecx,dword ptr [SoSimple::simObjectCnt (01343C8h)]  
00131036  add         ecx,1  
00131039  mov         dword ptr [SoSimple::simObjectCnt (01343C8h)],ecx  
	SoSimple sim2;
0013103F  mov         edx,dword ptr [SoSimple::simObjectCnt (01343C8h)]  
00131045  add         edx,1  
00131048  mov         dword ptr [SoSimple::simObjectCnt (01343C8h)],edx  

	cout << endl << endl << SoSimple::simObjectCnt << "번째 SoSimple 객체" << endl;
0013104E  push        offset std::endl<char,std::char_traits<char> > (0131780h)  
00131053  push        133144h  
00131058  mov         eax,dword ptr [SoSimple::simObjectCnt (01343C8h)]  
0013105D  push        eax  
0013105E  push        offset std::endl<char,std::char_traits<char> > (0131780h)  
00131063  push        offset std::endl<char,std::char_traits<char> > (0131780h)  
00131068  mov         ecx,dword ptr [__imp_std::cout (0133060h)]  
0013106E  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (013303Ch)]  
00131074  mov         ecx,eax  
00131076  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (013303Ch)]  
0013107C  mov         ecx,eax  
0013107E  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (0133034h)]  
00131084  push        eax  
00131085  call        std::operator<<<std::char_traits<char> > (0131300h)  
0013108A  add         esp,8  
0013108D  mov         ecx,eax  
0013108F  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (013303Ch)]  
	cout << sim1.simObjectCnt << "번째 SoSimple 객체" << endl;
00131095  push        offset std::endl<char,std::char_traits<char> > (0131780h)  
0013109A  push        133158h  
0013109F  mov         ecx,dword ptr [SoSimple::simObjectCnt (01343C8h)]  
001310A5  push        ecx  
001310A6  mov         ecx,dword ptr [__imp_std::cout (0133060h)]  
001310AC  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (0133034h)]  
001310B2  push        eax  
001310B3  call        std::operator<<<std::char_traits<char> > (0131300h)  
001310B8  add         esp,8  
001310BB  mov         ecx,eax  
001310BD  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (013303Ch)]  
	cout << sim2.simObjectCnt << "번째 SoSimple 객체" << endl;
001310C3  push        offset std::endl<char,std::char_traits<char> > (0131780h)  
001310C8  push        13316Ch  
001310CD  mov         edx,dword ptr [SoSimple::simObjectCnt (01343C8h)]  
001310D3  push        edx  
001310D4  mov         ecx,dword ptr [__imp_std::cout (0133060h)]  
001310DA  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (0133034h)]  
001310E0  push        eax  
001310E1  call        std::operator<<<std::char_traits<char> > (0131300h)  
001310E6  add         esp,8  
001310E9  mov         ecx,eax  
001310EB  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (013303Ch)]  
001310F1  nop  
}
001310F2  xor         eax,eax  
001310F4  pop         ebp  
001310F5  ret