Forum: Mikrocontroller und Digitale Elektronik Bits tauschen?!


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von C - Anfänger (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallöle,

bin gerade etwas überfordert.
Möchte gerne diese ganze "if abfragerei" in einer "for" Schleife 
erledigen..
Muss doch funktionierten oder?
1
static inline uint8_t swapBits(uint8_t byte)
2
{
3
  uint8_t tmp = 0;
4
  if(byte&1<<7) tmp|=1<<0;
5
  if(byte&1<<6) tmp|=1<<1;
6
  if(byte&1<<5) tmp|=1<<2;
7
  if(byte&1<<4) tmp|=1<<3;
8
  if(byte&1<<3) tmp|=1<<4;
9
  if(byte&1<<2) tmp|=1<<5;
10
  if(byte&1<<1) tmp|=1<<6;
11
  if(byte&1<<0) tmp|=1<<7;
12
  return tmp;
13
}

von Sheeva P. (sheevaplug)


Bewertung
-3 lesenswert
nicht lesenswert
C - Anfänger schrieb:
> bin gerade etwas überfordert.
> Möchte gerne diese ganze "if abfragerei" in einer "for" Schleife
> erledigen..

Was ist eigentlich eine Zählschleife? ;-)

von C - Anfänger (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Die Schleife an sich verstehe Ich. Es geht um die Rechnerei.

von Teo D. (teoderix)


Bewertung
0 lesenswert
nicht lesenswert
Beitrag "Re: Bits drehen bzw. spiegeln"
1
for ( i = 0; i < 8; i++ )
2
{
3
   gespiegelt >>= 1;
4
   gespiegelt |= original & 0x80;
5
   original <<= 1;
6
}

von bascom lover (Gast)


Bewertung
-1 lesenswert
nicht lesenswert
Mit den Behinderungen in Bascom könnte man es so machen. If ist nicht 
notwendig.

For I = 0 To 7
  K = 7 - I
  Tmp.i = Half_word.k
Next I

von Hans (Gast)


Bewertung
0 lesenswert
nicht lesenswert

von C - Anfänger (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Teo D. schrieb:
> Beitrag "Re: Bits drehen bzw. spiegeln"
> for ( i = 0; i < 8; i++ )
> {
>    gespiegelt >>= 1;
>    gespiegelt |= original & 0x80;
>    original <<= 1;
> }

Die Lösung ist Prima. Danke!

von Michael R. (fisa)


Bewertung
0 lesenswert
nicht lesenswert
je nach Architektur bietet der GCC dafür "builtins" an, zB für AVR das 
__builtin_avr_insert_bits:
1
// reverse bit order
2
static uint8_t mirror(const uint8_t bits)
3
{
4
    return __builtin_avr_insert_bits(0x01234567, bits, 0);
5
}

von Teo D. (teoderix)


Bewertung
0 lesenswert
nicht lesenswert
C - Anfänger schrieb:
> Die Lösung ist Prima. Danke!

Der Dank geht wohl an ARM-Fan (Gast), Florian (Gast) und Google. 8-)

Aber danke für dir Rückmeldung das es funst. ;)

von Markus F. (mfro)


Bewertung
-2 lesenswert
nicht lesenswert
wer Platz hat, nimmt eine Lookup-Tabelle:
1
static const uint8_t lut = { 0xff, 0xfe, 0xfd, ... }
2
3
uint8_t bitrev(uint8_t bits) {
4
    return lut[bits];
5
}

... und wer keinen hat, der kann das auch in zwei 4-bit Lookups mit 
entsprechenden Shifts (und dem damit verbundenen Performanceverlust) 
aufteilen.

... und wer einen ColdFire hat, nimmt BITREV, die ARM-Fraktion RBIT...


C - Anfänger schrieb:
> Teo D. schrieb:
>> Beitrag "Re: Bits drehen bzw. spiegeln"
>> for ( i = 0; i < 8; i++ )
>> {
>>    gespiegelt >>= 1;
>>    gespiegelt |= original & 0x80;
>>    original <<= 1;
>> }
>
> Die Lösung ist Prima. Danke!

Die Lösung ist m.E. suboptimal. Wenn "orginal" 0 wird, kann man 
'fertigshiften' und aufhören. Macht man dennoch weiter, erzeugt man nur 
noch unnötig Wärme ;)

: Bearbeitet durch User
von Herbert P. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hmm. Vergleicht man die beiden Ansätze:
1
typedef unsigned char uint8_t; // damit er uint8_t kennt
2
3
uint8_t swapBits(uint8_t byte)
4
{
5
  uint8_t tmp = 0;
6
  if(byte&1<<7) tmp|=1<<0;
7
  if(byte&1<<6) tmp|=1<<1;
8
  if(byte&1<<5) tmp|=1<<2;
9
  if(byte&1<<4) tmp|=1<<3;
10
  if(byte&1<<3) tmp|=1<<4;
11
  if(byte&1<<2) tmp|=1<<5;
12
  if(byte&1<<1) tmp|=1<<6;
13
  if(byte&1<<0) tmp|=1<<7;
14
  return tmp;
15
}
16
17
uint8_t swap2(uint8_t original)
18
{
19
    uint8_t gespiegelt = 0;
20
    for (int i = 0; i < 8; i++ )
21
    {
22
        gespiegelt >>= 1;
23
        gespiegelt |= original & 0x80;
24
        original <<= 1;
25
    }
26
    return gespiegelt;
27
}

z.B. im Compiler-Explorer (https://godbolt.org/#) und wählt die Option 
-O3 aus, so zeigt sich sowohl für AVR- als auch ARM-Compiler (die 
anderen habe ich nicht untersucht), dass durch die Optimierung die erste 
Lösung deutlich kürzer wird als die Schleife (Stichwort: 
Loop-Unrolling).

Nur so als Anregung...

Gruß
Herby

von Stefan ⛄ F. (stefanus)


Bewertung
0 lesenswert
nicht lesenswert
Mit der Lookup Tabelle hat man die beste Performance. Kostet aber 256 
Bytes RAM.

von A. S. (achs)


Bewertung
-1 lesenswert
nicht lesenswert
Stefan U. schrieb:
> Kostet aber 256
> Bytes RAM.

oder ensprechend ROM

von Frank M. (ukw) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Ich werfe mal die in den Raum:
1
unsigned char reverse(unsigned char b) {
2
   b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
3
   b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
4
   b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
5
   return b;
6
}

oder auch diese mit lediglich 16 Bytes Lookup-Table.
1
static unsigned char lookup[16] = {
2
0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
3
0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf, };
4
5
uint8_t reverse(uint8_t n) {
6
   return (lookup[n&0b1111] << 4) | lookup[n>>4];
7
}

Quelle: 
https://stackoverflow.com/questions/2602823/in-c-c-whats-the-simplest-way-to-reverse-the-order-of-bits-in-a-byte

von spess53 (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hi

Ich finde die Lösung von PeDa eleganter:

Beitrag "Re: reihenfolge der bits in einem byte umdrehen"

MfG Spess

von spess53 (Gast)


Bewertung
-1 lesenswert
nicht lesenswert
Hi

Mist. Zu spät.

MfG Spess

von Possetitjel (Gast)


Bewertung
1 lesenswert
nicht lesenswert
Frank M. schrieb:

> Ich werfe mal die in den Raum: [...]

Ungünstig, wenn die Zielplattform nur um ein Bit
je Befehl schieben kann.


> oder auch diese mit lediglich 16 Bytes Lookup-Table.

Könnte man pimpen, wenn getrennte Tabellen für
High- und Low-Nibble verwendet werden.

von S. R. (svenska)


Bewertung
1 lesenswert
nicht lesenswert
Possetitjel schrieb:
>> oder auch diese mit lediglich 16 Bytes Lookup-Table.
> Könnte man pimpen, wenn getrennte Tabellen für
> High- und Low-Nibble verwendet werden.

Ist bei einer 16 Byte-Tabelle schon geschehen, sonst bräuchte man ja 256 
Byte.

Vermutlich ist das Compiler-Builtin die sinnvollste Variante. Wenn ein 
Compiler ohne passendes Builtin benutzt werden soll, dann kann man ja 
immernoch gcc's builtin disassemblieren...

von Possetitjel (Gast)


Bewertung
0 lesenswert
nicht lesenswert
S. R. schrieb:

> Possetitjel schrieb:
>>> oder auch diese mit lediglich 16 Bytes Lookup-Table.
>> Könnte man pimpen, wenn getrennte Tabellen für
>> High- und Low-Nibble verwendet werden.
>
> Ist bei einer 16 Byte-Tabelle schon geschehen, [...]

Missverständnis.

Ich sprach davon, eine 16-Byte-Tabelle für das
High-Nibble und zusätzlich eine weitere 16-Byte-Tabelle
für das Low-Nibble zu verwenden. Das spart die Shifts
komplett ein.

von A. S. (achs)


Bewertung
0 lesenswert
nicht lesenswert
Possetitjel schrieb:
> Das spart die Shifts komplett ein.

Ich finde Deine Idee gut. Führt man sie weiter, könnte man auch 2 * 8 
+1*4 Einträge nehmen (2*3Bit, 1*2Bit), 4*4 oder 8*2. Wobei letzteres 
dann wieder der Ursprungslösung entspricht ;-)
1
unsigned char bswap(unsigned char x)
2
{
3
   /* 8 literal tables of 2 values */
4
   return (unsigned char)
5
         ((x&128?  1:0)
6
         |(x& 64?  2:0)
7
         |(x& 32?  4:0)
8
         |(x& 16?  8:0)
9
         |(x&  8? 16:0)
10
         |(x&  4? 32:0)
11
         |(x&  2? 64:0)
12
         |(x&  1?128:0));
13
}

von S. R. (svenska)


Bewertung
0 lesenswert
nicht lesenswert
Possetitjel schrieb:
> Das spart die Shifts komplett ein.

Sind die 4 Bit-Shifts nicht auf den betroffenen 8 Bit-Architekturen 
beinahe kostenlos (wegen SWAP)? Auf größeren Systemen kann man gleich 
die volle Tabelle nehmen.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.