언어 자료구조 알고리즘/C 언어 문법

12. 증감연산자

언제나휴일 2009. 8. 19. 05:47
반응형
증감연산자

 

 

다루는 내용

    - 증감 연산자와 산술 연산자와의 비교

    - 어셈블리 코드 확인하기(디스어셈블리)

 

증감연산자는 단항 연산자로 ++, -- 연산자가 있다.

 

증감연산자는 기본적으로 자기 자신의 값을 1증가(++),  1감소(--)시키는 연산 행위를 한다.

하지만 연산 결과는 전위에 연산자가 왔을 때는 변경된 자기 자신의 값이고 후위에 왔을 때는 변경되기 전 값이다.

 

이는 증감연산의 결과를 사용을 하려했을 때는 전위 연산 표현인지 후위 연산 표현인지에 따라 영향을 미치게 된다.

 

 

Look & Feel & Think

전위에 연산자가 왔을 때(++i) 

C언어 어셈블리 설명
int i = 0; mov         dword ptr [i],0  변수 i에 0으로 초기화
++i; mov         eax,dword ptr [i]  eax레지스터에 변수 i를 대입
add         eax,1  eax레스트터에 1을 더한다.
mov         dword ptr [i],eax  변수 i에 eax레지스터 대입
  

후위에 연산자가 왔을 때(i++) 

C언어 어셈블리 설명
int i = 0; mov         dword ptr [i],0  변수 i에 0으로 초기화
  mov        ecx,dword ptr [i]  eax레지스터에 변수 i를 대입
i++; add        ecx,1  eax레스트터에 1을 더한다.
  mov        dword ptr [i],ecx  변수 i에 eax레지스터 대입

 

자기 자신에 1을 더하는 코드(i = i +1)

C언어 어셈블리 설명
int i = 0; mov         dword ptr [i],0  변수 i에 0으로 초기화
  mov        ecx,dword ptr [i]  eax레지스터에 변수 i를 대입
i = i+1; add        ecx,1  eax레스트터에 1을 더한다.
  mov        dword ptr [i],ecx  변수 i에 eax레지스터 대입

 

위의 세 개의 표를 보면 C언어 코드는 다르지만 어셈블리 코드는 완벽히 일치함을 알 수 있다.

즉, 증감연산자의 연산행위는 전위에 오거나 후위에 오거나 상관없이 동일함을 알 수 있다. 

 

 

Look & Feel & Think

전위에 증감연산자가 오고 연산 결과를 다른 변수에 대입(re = ++i) 

C언어 어셈블리 설명
int i = 0; mov         dword ptr [i],0  변수 i에 0으로 초기화
int re = 0; mov         dword ptr [re],0  변수 re에 0으로 초기화
re = ++i; mov         eax,dword ptr [i]  eax레지스터에 변수 i를 대입
add         eax,1  eax레스트터에 1을 더한다.
mov         dword ptr [i],eax  변수 i에 eax레지스터 대입
mov         ecx,dword ptr [i]  ecx레지스터에 변수 i대입
mov         dword ptr [re],ecx  re변수에 ecx대입

 

자신을 1 더한 후에 변경된 값을 다른 변수에 대입하는 코드 (i = i+1; re = i;)

C언어 어셈블리 설명
int i = 0; mov         dword ptr [i],0  변수 i에 0으로 초기화
int re = 0; mov         dword ptr [re],0  변수 re에 0으로 초기화
i = i +1;  mov         eax,dword ptr [i]  eax레지스터에 변수 i를 대입
add         eax,1  eax레스트터에 1을 더한다.
mov         dword ptr [i],eax  변수 i에 eax레지스터 대입
re = i; mov         eax,dword ptr [i]  eax레지스터에 변수 i를 대입
mov         dword ptr [re],eax  re변수에 eax대입

위의 두 표를 보면 두 개의 어셈블리가 일치함을 알 수 있다.(사용하는 범용 레지스터가 다르지만 연산의 내용은 동일)

  

후위에 증감연산자가 오고 연산 결과를 다른 변수에 대입(re = i++)  

C언어 어셈블리 설명
int i = 0; mov         dword ptr [i],0  변수 i에 0으로 초기화
int re = 0; mov         dword ptr [re],0  변수 re에 0으로 초기화
re = i++; mov        eax,dword ptr [i]  eax레지스터에 변수 i를 대입
  mov        dword ptr [re],eax  변수 re에 eax레지스터 대입
  mov        ecx,dword ptr [i]  ecx레지스터에 변수 i를 대입
  add        ecx,1  ecx레스트터에 1을 더한다.
  mov        dword ptr [i],ecx  변수 i에 ecx레지스터 대입

 

자신을 다른 변수에 대입한 후 자신을 1 더하는 코드 (re = i;  i = i+1;) 

위의 두 표를 보면 두 개의 어셈블리가 일치함을 알 수 있다.(사용하는 범용 레지스터가 다르지만 연산의 내용은 동일)

  

이를 통해 증감연산자의 경우 연산의 결과는 연산자의 위치에 따라 다름을 알 수 있다.

 

본인은 증감연산자의 결과를 사용하는 구문은 사용하지 않는다.

이는 코드를 다시 볼 때 생각을 좀 더 해야 한다는 것이다.  즉, 가독성을 떨어트리는 요소가 된다.

하지만 다른 연산자와 같이 사용을 하지 않으면 연산 결과를 사용하지 않기 때문에 즐겨 사용한다.

 

증감 연산자는  연산자의 위치에 상관없이 연산 행위는 동일하나 연산 결과는 다르다.

증감연산자는 다른 연산과 같이 사용하지 말자.

 

  

 

어셈블리 코드 확인하기

먼저 고급 언어 코드와 어셈블리 코드, 기계어의 차이에 대해 얘기를 하자.

고급 언어 코드는 자연어 형식에 맞게 만든 언어를 고급 언어라 하며 해당 고급 언어 문법에 맞게 작성된 코드이다.

컴파일러는 이를 기계어로 번역을 하게 된다.

기계어는 실제 컴퓨터에서 수행하는 코드로 0과 1의 집합으로 되어 있는 코드를 얘기를 한다.

우리가 보통 어셈블리를 기계어라 얘기를 하지만 어셈블리 코드는 기계 명령 대신 니모닉을 이용하여 기계어와 1기계어와 1:1 매핑되어 있는 코드를 말한다.  즉, 0과 1로 기계어 코드를 작성하는 것과 1:1 매핑시켜 작성하기 쉽게 만든 언어를 어셈블리어라 한다.

 

그리고 어셈블리어로 만든 코드는 어셈블러에 의해 기계어로 바뀌는데 이러한 과정을 어셈블리라 하고 역으로 기계어 코드를 어셈블리 코드로 변환하는 것을 디스 어셈블리라 한다.

 

여기서는 Visual Studio 2008에서 디스 어셈블리를 이용하여 어셈블리 코드를 확인하는 방법을 얘기할 것이다. 

 

1. 먼저 소스 코드에 BreakPoint를 설정한다. 

    단순히 라인위에 마우스 왼쪽 버튼을 클릭하면 설정 다시 클릭하면 해제된다. 

    설정 후에 F5로 디버깅 시작을 누르면 BreakPoint 앞까지 실행되서 Break포인터에서 멈춘다. 

 

2. BreakPoint에서 멈추면 디버그 메뉴→창→디스어셈블리(단축키:Ctrl+Alt+D)를 선택하자.

3. 다음과 같은 디스어셈블리 창이 뜬다. 

    기계어는 문법이 단순해서 무슨 내용인지 이해하기 어렵지 않다.  다만 단순한 문법을 이용해서 커다란 프로그램을 작성하는 것이 힘들 뿐이다.  용기를 갖고 손가락에 힘을 주고 키보드를 누르고 약간의 Thinking을 하면 뭔가 느낄 수 있을 것이다.

 

 

 

반응형