środa, 9 lutego 2011

Zamiana kolejności bitów LSB <-> MSB


Autor: Dondu

Kurs języka C: Tips & Tricks - Spis treści

Czasami potrzebne może być dokonanie zamiany kolejności bitów w zmiennej.

meehowk3
Jak zamienić kolejność bitów? Np.: 00110001 na 10001100


Język C nie posiada instrukcji, która dokonuje takiej zamiany. Poniżej przykład prostej funkcji, która to umożliwia.

Przykład 1 (w kompilatorze)
//Funkcja zamiany kolejności bitów LSB <-> MSB
unsigned char dd_zmien_kolejnosc_bitow(char a){
  
  static unsigned char wynik;           //zmienna wynikowa
  static unsigned char maska_a = 0x01;  //zmienna pomocnicza
  static unsigned char maska_b = 0x80;  //zmienna pomocnicza

  //dla każdego z ośmiu bitów
  static int i;
  for(i = 0; i<8; i=i+1){
    
    //gdy bit jest jedynką dodaj go na odpowiedniej 
    //pozycji przeciwnego mu bitu
    if(a & maska_a) wynik |= maska_b; 
    
    maska_a<<=1;  //przesuń maskę A o jeden w lewo
    maska_b>>=1;  //przesuń maskę B o jeden w prawo
    
  }

  return wynik;

}

Przetestuj przykład w kompilatorze CManiak. W kodzie przykładu znajdziesz linijkę pozwalającą prześledzić poszczególne fazy działania funkcji, by ją łatwiej zrozumieć.


Mikrokontrolery - specyfika

W przypadku mikrokontrolerów i niektórych budowanych na nich urządzeniach, takie rozwiązanie może być zbyt wolne. Wtedy możesz zdefiniować w pamięci programu tablicę, która zawierać będzie przeliczone wartości. Taka tablica będzie umieszczona np. pod adresem X. Wystarczy wtedy odczytać bajt spod adresu: X + liczba do zmiany. Takie rozwiązanie oczywiście oznacza, że wykorzystasz 256 bajtów pamięci programu, więc nie zawsze można sobie na to pozwolić :-)

Innym rozwiązaniem jest wykorzystanie kodu assemblera i dostępnych w nim rozkazów ROL oraz ROR, czyli przesuwania z wykorzystaniem flagi przeniesienia C (ang: carry).


Kurs języka C: Tips & Tricks - Spis treści

37

1 komentarz:

  1. To może zaproponuję bardziej optymalną funkcję, oczywiście można ją jeszcze bardziej zoptymalizować. Ale i tak daje mniejsze narzuty na FLASH i RAM.

    unsigned char zmiana(char a)
    {
    int i, c=0;
    for(i=0; i<8; i++)
    {
    if(a&(1<<i))
    c |= (1<<7-i);
    }
    return c;
    }

    OdpowiedzUsuń