2017-12-18 18 views
3

문제점비트 마스킹 문제에 대한 좋은 해결책은 무엇입니까?

  • I 다른 비트에 영향을주지 않고 다른 조합으로 비트의 조합을 변경하고 싶다. 최고의 마스킹 솔루션 무엇 :이 조합에서
  • 는 일부 비트는 해제 또는

질문을 설정해야합니다. 특히 해제 masking.I

예를 들어 변화 비트 [3 : 0] -> 0b1011 (데이터) 목적 비트 [3 : 0] -> 0b0110

날 I 시도 어떻게 공유 할 0b0110 :

  • 마스크를 작성> [1111] 0110 (1로하지 신경 비트를 변경) - 0b1001의 1의 보수 :

    • 설정되지 않은 마스크를 작성

      그리고이 두 개의 마스크를 사용하여 비트 연산을 사용할 수 있습니다.

      int data = 0xB;   /*0b1011 (0xb) -> 0110 (0x6)*/ 
      int umask = 0x9;  /*unset mask 0b1001*/ 
      int smask = 0x6;  /*Set Mask 0b0110*/ 
      
      data &= ~umask;  /*Unset the bits what needs without affecting other*/ 
      data |= smask;   /*Set the bits what needs to be set*/ 
      
  • +1

    일반 솔루션을 요청하십니까? 또는 이러한 설정 값에 대해 제안 된 솔루션 이외의 다른 (더 나은) 솔루션이 있는지 알고 싶습니까? – AntonH

    +1

    당신이 묘사하는 것은 정확히 그것이 일반적으로 행해지는 방식입니다. 컴파일러가 나머지 작업을 수행합니다. –

    +1

    비트 트위 빙시 마이크로 컨트롤러 (예 : AVR)에서 매우 일반적인 패턴.'PORTB | = 1 << 2; '와 같은 라인은 하나의'SBI' set-bit 어셈블리 명령어로 변환 될 것입니다. –

    답변

    2

    간단한 대답은 '예, 당신은 당신이 삭제하려는 비트를 취소 한 마스크를 사용하고, 다른 사용자가 설정하려는 사람을 설정할 수 있습니다. 그러나 때로는 마스크와 데이터가 사용되는 방식과 마스크의 의미에 따라 알아둬야 할 숨겨진 하드웨어 수준의 항목이 있습니다.

    당신은 단지 값에 4 개 비트를 설정하려면

    :

    val &= ~(0xf); // This only clears the low 4 bits, preserving the rest. 
    
    assert((new4BitMaskvalue & ~0xf) == 0); // Make sure new mask only plays with low 4 bits. 
    val |= new4BitMaskvalue; // or new mask 
    

    당신은 기술적으로 약간의 여분의 비트를 클리어하고 있지만 이것은 당신이 청소에 한 일반적인 마스크를 사용할 수 있습니다. 정확한 비트를 지울 수도 있지만, 필요하지 않을 수도 있습니다.

    CPU가 지원하는 메모리 단위 크기로 모든 필드를 한꺼번에 설정하는 경우 전체 값을 할당하고 단계를 생략하는 것이 종종 있습니다. (u8/u16/u32/u64/etc.)

    이제 "재미"부분. 이 비트가 실제 하드웨어 레지스터를 나타내는 경우 흥미로운 동작을 유발할 수 있으므로 이처럼 전체 필드를 설정하지 못할 수도 있습니다. 아마도 이것은 인터럽트 인 에이블 레지스터입니다. 그렇다면 삭제 및 설정이 필요없는 비트를 삭제하고 재설정하면 의도하지 않은 부작용이 발생할 수 있습니다. 또한 레지스터는 읽기 또는 쓰기 만하는 경우가 많습니다. 다시 마스크 할 때 조심해야하며 한 번에 하나씩 개별 비트를 설정하거나 지울 수도 있습니다.

    요컨대, 일반적으로 비트를 지우고 설정하려면 최소한 2 개의 값이 필요합니다. 첫 번째 not and 마스크는 일반적으로 관심있는 모든 비트를 지울 수 있으므로 2 개의 특수 마스크가 필요하지 않습니다.

    +0

    예, 내 주요 질문은 레지스터 비트 조작에 관한 것입니다.하지만 먼저 시도하기 전에이 문제를 이해하고 싶습니다. – Peter

    +0

    당신은 이미 적은 수의 단어로 이것을 말하고 있을지 모르지만 그것은 매우 중요합니다. 포인터 마술을 사용하여 하드웨어 레지스터 myreg에 대한 포인터를 사용하면 실제로 myreg & = ~ 0x7 레지스터를 사용하는 것이 좋습니다. myreg | = 0x2; 그 비트를 변경 한 다음 다시 변경했으면 temp = myreg 복사본을 만들고 싶습니다. 임시 &=~0x7; 임시 | = 0x2; myreg = temp. 따라서 액세스 방법을 이해하십시오. 이 변수가 단순히 변수의 데이터이고 명시된대로 그리고 당신이 알아 낸대로 0과 0 비트가 필요하고 비트를 설정해야합니다. –