2012년 8월 6일 월요일

비트 마스크(bit mask)

주의사항 : 수업 중에 배운 내용을 정리해서 올려둡니다 수작업이라 내용이 이상하거나 오탈자가 있을 수 있으므로 댓글로 남겨주시면 바로 수정하겠습니다.

현재 이미지의 링크가 깨져있어 보이지 않고 있습니다. 조만간 수정해서 업로드 하겠습니다.


History...

2012. 8. 6. 네이버 블로그에서 이전
=================================================================================

bit mask
마이크로프로세서 수업시간에 비트 마스크에 대해서 설명이 나와서 정리해 봅니다.
나름대로 bitmask가 무엇인지 정의를 내려보자면
>>특정 비트의 값을 바꾸기 위해서 하는 연산
음... 빈약하군요... 보시는 분이 있다면 댓글로 보충 부탁드립니다.
AND & OR 연산
AND(&) 연산은 두 비트가 모두 '1'일 경우 결과가 '1'이고  그렇지 않으면 결과가 '0'이 되는 연산.
OR (|) 연산은 두 비트중 하나만 '1'일 경우 결과가 '1'이고 그렇지 않으면 결과가 '0'이 되는 연산.
* 논리 연산자(&&, ||, !)와 비슷하지만 비트를 연산 대상으로 한다는 점이 다름



AND 연산 예시
OR 연산 예시

mask off
특정 비트를 강제로 '0'으로 만드는(또는 특정 비트를 원래 비트값을 그대로 유지하는) 연산.
AND 연산에서 '0'과 &연산하는 비트는 그 값에 상관없이 무조건 '0'이 되고 '1'과 &연산하는 비트는 원래 비트값을 그대로 유지하는 특성이 있다.
예)
비트열 A가 (0b01010101 = 0x55)라고 하고 상위 2비트와 하위 2비트(0b11000011)를 유지하고 다른 비트들은 다 '0'으로 바꾸고 싶은 경우.
비트열 A와 마스크를 AND 연산한 결과의 상위 2비트와 하위 2비트가 비트가 비트열 A의 그것과 같음을 볼수 있음.
mask on
특정 비트를 강제로 '1'로 만들고 나머지는 유지하는 연산
OR 연산에서 '0'과 연산하는 비트는 원래 값을 유지하고 '1'과 연산하는 비트는 무조건 1이 되는 특성이 있다.
예)
비트열 A가 (0b01010101 = 0x55)라고 하고 상위 2비트와 하위 2비트(0b11000011)를 '1'로 만들고 다른 비트들은 유지하고 싶은 경우. 
비트열 A와 마스크를 OR 연산한 결과의 상위 2비트와 하위 2비트의 비트가 '1'로 바뀌고 나머지 비트는 비트열 A와 같음.
배타적 논리합 (XOR(^):eXclusive OR)의 활용
^은 ~(NOT)연산자와 마찬가지로 비트를 반전시키는 기능을 하는데 ~연산자가 전체 비트를 반전시키는 반면에 ^은 지정한 비트만을 반전시킨다. ^연산은 비트가 서로 다를 때만 '1'이 되고 같으면 '0'이된다. 따라서 '1'과 ^연산하는 비트는 반전하고 '0'과 ^연산하는 비트는 원래 값을 유지한다.
<오타수정 12.3.13>
예)
비트열 A가 (0b01010101 = 0x55)라고 하고 상위 2비트와 하위 2비트(0b11000011)를 반전하고 다른 비트들은 유지하고 싶은 경우.
비트열 A와 마스크를 XOR 연산한 결과  상위 2비트와 하위 2비트의 비트가 반전되고 나머지 비트는 비트열 A와 같음.
활용(수업시간에 한 내용)
#include<avr/io.h>
#include<avr/interrupt.h>
...
TIMSK |= 1<< TOIE0;
TIFR |= 1 << TOV0; 
...
return 0;
}
타이머 예시코드에서  TIMSK(타이머 인터럽트 마스크 래지스터)의 첫 비트의 값을 '1' 넣으러고 하는 코드 설명 중 교수님이 아래 세줄의 차이점을 설명
TIMSK(타이머 인터럽트 마스크 래지스터)의 첫 비트(Timer/counter Overflow Interrupt Enable)가 '1'이 되면 overflow interrupt를 활성화한다. 
TIMSK = 0x01; ---------->(1)
TIMSK |= 0x01; --------->(2)
TIMSK |= 1 << TOIE0; ---->(3)
우선 (1)에서는 TIMSK에 0x01(=0b00000001)값을 넣는 코드인데 이렇게 넣으면 의도대로 첫 비트의 값이 '1'이 들어 가지만 나머지 비트의 값이 다 '0'으로 되어버리므로 에러의 소지가 있다.
(2)에서는 TIMSK와 0x01을 |연산하여 첫번째 비트만 mask on한다. 나머지 비트는 그대로 유지하고 첫번째 비트만 바뀌었다.


(3)을 보면
TIMSK |= 1 << TOIE0; //#define TOIE0 0 (기능에 매칭되는 비트열을 매크로상수로 정의했다.)
|= 연산자 보다 << 연산자가 우선순위가 높기 때문에 '1 << TOIE0 ' 이 먼저 실행한다.
(2)와 (3)은  결과에는 큰 차이가 없지만 (2)에서는 자신이 바꾸어야 할 비트의 위치와 그 비트를 바꾸었을때의 기능을 알아야 하는 반면에 (3)은 TOIE0(Timer/counter Overflow Interrupt Enable)이라는 기능만 알고 있으면 레지스터의 값을 편리하게 바꿀수 있는 장점이 있다.
[참고 및 출처] 마이크로프로세서및실습 수업, www.winapi.co.kr

댓글 없음:

댓글 쓰기