Forum: Mikrocontroller und Digitale Elektronik Bitweise Verschiebung


von Georg M. (g_m)


Lesenswert?

Die einzige "1" in einem Byte (uint8_t) kann ich sehr einfach nach links 
(<<) und nach rechts (>>) verschieben:

00000010
00010000  (<<3)
00000100  (>>2)

Es werden zwar alle Bits verschoben, sichtbar wandert aber nur die "1".

Nun soll aber die einzige "0" verschoben werden:

11110111
11101111
11011111
10111111
01111111
10111111
11011111

Ist nicht mehr so einfach?

von sokannsgehen (Gast)


Lesenswert?

invertieren, verschieben, invertieren

von Oliver S. (oliverso)


Lesenswert?

Schieben, und die neue hinzugekommenen Nullen mit 1 überschreiben.

Oliver

von FOp (Gast)


Lesenswert?

Doch ist genauso einfach. Du meinst vermutlich die Werte der Bits, die 
hineingeschoben werden.

Da fallen mir 4 Taktiken ein :

a) schiebe den Wert 0 hinein

b) schiebe den Wert 1 hinein

c) schiebe den Wert der am anderen Ende herauspurzelt hinein

d) schiebe den Wert des Carry-Flags hinein und lade das Carry-Flag mit 
dem Wert, der am anderen Ende herausfällt

Wobei C an und für sich erstmal nur a) beherrscht. Aber mit ein wenig 
Bit hin und her gewurschtel kommt man auf b) oder c)
1
a) x <<= 3;
2
b) x = (x << 3) | 7;
3
c) x = (x << 3) | (x >> 5);

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Georg M. schrieb:
> Es werden zwar alle Bits verschoben, sichtbar wandert aber nur die "1".
> Nun soll aber die einzige "0" verschoben werden
Das, was du da willst, nennt sich im Grunde "rotieren": das was links 
oder rechts rausfällt, soll auf der jeweils anderen Seite wieder 
hineingeschoben werden.

Der Assembler kann das ganz einfach, da gibt es entsprechende 
Rotationsbefehle ror und rol. In C ist das wie schon dargestellt 
aufwändiger und leider kapiert mit annehmbarer Wahrscheinlichkeit der 
Compiler nicht, dass er ror und rol verwenden könnte:
https://www.google.com/search?q=rotate+in+c

: Bearbeitet durch Moderator
von zyxwv (Gast)


Lesenswert?

Du meinst vermutlich einfach invertiert:
~(1<<4) ergibt 11101111

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

zyxwv schrieb:
> Du meinst vermutlich
Bei den Beispielen oben wird nicht von Konstanten ausgegangen. Oder 
anders:
was ergibt "11011111 ror 2"? Was ergibt "11110111 ror 2"?

Georg M. schrieb:
> Ist nicht mehr so einfach?
Manchmal wäre es echt nicht schlecht, das eigentliche Problem zu kennen 
und nicht nur den geplanten Lösungsansatz dafür...

von A. S. (Gast)


Lesenswert?

Nach rechts geht es "einfach", wenn die 0 nicht an Bit 7 (ganz links) 
steht und int8_t statt uint8_t verwendet wird.

Wenn es aber nur eine 0 enthält, reicht auch eine Tabelle von 8 
einträgen, über die man itteriert (mit %8)

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

A. S. schrieb:
> Wenn es aber nur eine 0 enthält, reicht auch eine Tabelle von 8
> einträgen, über die man itteriert (mit %8)
Ja, aber in dieser Tabell muss man erst mal den aktuellen Wert finden, 
wenn dieses Bitmuster von aussen kommt.

Und wenn das Bitmuster es quasi als "Index" im eigenen Programm 
verwaltet wird (z.B. Spalte/Zeile eines LED-Multiplexers), dann wäre es 
sinnvoller, den Index abzuspeichern und daraus jeweils das Bitmuster zu 
berechnen.

Wie gesagt: was ist das Problem, das hier gelöst werden soll?

von Georg M. (g_m)


Lesenswert?

Lothar M. schrieb:
> Manchmal wäre es echt nicht schlecht, das eigentliche Problem zu kennen

Beim EEPROM gilt 0xFF als gelöscht, und da dachte ich: ok, dann mache 
ich auch meinen ganzen Code invers.
Aber offensichtlich gibt es keine Gleichberechtigung/Gleichbehandlung 
bei den Nullen und Einsen.

von Nils (Gast)


Lesenswert?

Lothar M. schrieb:
> In C ist das wie schon dargestellt
> aufwändiger und leider kapiert mit annehmbarer Wahrscheinlichkeit der
> Compiler nicht, dass er ror und rol verwenden könnte:

Meeep. Das können so gut wie alle Compiler seit über einem Jahrzeht. Ist 
eine der einfachsten Optimierungsstufen. Und da es häufig in Hash 
funktionen vorkommt macht es auch praktisch Sinn:

Beispiel:

https://godbolt.org/z/qza33Ys55
1
uint8_t f(uint8_t a) 
2
{
3
    return (a<<1) | (a >>7);
4
}
1
        mov     eax, edi
2
        rol     al
3
        ret

von mIstA (Gast)


Lesenswert?

Georg M. schrieb:
> Aber offensichtlich gibt es keine
> Gleichberechtigung/Gleichbehandlung
> bei den Nullen und Einsen.

Natürlich nicht - vor allem wenn (E)EPROMs mitspielen wollen.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Nils schrieb:
> Das können so gut wie alle Compiler seit über einem Jahrzeht.
Ist ja nett, dann machen wir das künftig genau so...  ;-)

Georg M. schrieb:
> Beim EEPROM gilt 0xFF als gelöscht, und da dachte ich: ok, dann mache
> ich auch meinen ganzen Code invers.
> Aber offensichtlich gibt es keine Gleichberechtigung/Gleichbehandlung
> bei den Nullen und Einsen.
Gleichberechtigung war im Grunde auch nie ein Ziel... ;-)

Georg M. schrieb:
> Beim EEPROM gilt 0xFF als gelöscht, und da dachte ich: ok, dann mache
> ich auch meinen ganzen Code invers.
Beim EEPROM ist es schnurz, weil du da das Schreiben vom Löschen 
meistens sowieso nicht entkoppeln kannst. Sprich: wenn schon irgendwas 
im EPROM steht und du willst eine 0x00 reinschreiben, dann wird die 
Speicherzelle erst auf 0xff gelöscht, und dann alle Bits auf 0 
geschrieben. Du gewinnst im Grunde also nichts.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.