Forum: Compiler & IDEs Binäre Zahl drehen


von Dido (Gast)


Lesenswert?

Hallo!

Ich habe eine Frage und werde mich freuen, wenn mir jemand weiter
hilft. Wenn man eine binäre Zahl hat z.B 00101111 (8bit) wie kann man
am einfachsten in C die Rotieren damit man 11110100 am ende kriegt. Das
wäre für hilfreich, wenn man (wie mich) etwas inwertiert an einen Port
von einen AVR anhängt und schon fertiges Software hat und auch vile
ausgerechnete hex-Zahlen.

Danke für ihre hilfe!

von Tobi (Gast)


Lesenswert?

erstmal eine kurze nachfrage: willst du
das ganze um eine bestimmte anzahl rotieren?
invertieren (deinem beispiel nach nicht)?
oder oberes und unteres nibbel tauschen (scheint so)

von Matthias (Gast)


Lesenswert?

Hi

für mich siehts eher nach ner Spiegelung der Bits aus. Also 7->0 6->1
usw.

Am schnellsten geht das mit einer Look-Up-Tabelle. Das kostet
allerdings 256 Byte Flash. Ansonsten hat hier im Forum mal jemand einen
passenden Code gepostet. Einfach mal nach Bit und spiegeln suchen.

Matthias

von Jörg Wunsch (Gast)


Lesenswert?

Das Thema ist schon paarmal diskutiert worden.  Du findest es in den
Annalen dieses Forums.  Für 16-und-mehr-Bit-Zahlen gibt's einen
netten
C-Trick, für 8-Bit-Zahlen lohnt der eigentlich nicht, weil die
einfache Rotationsschleife (zumindest in inline asm) kürzer ist als
der coole Trick.

von Sebastian (Gast)


Lesenswert?

dafür gibt es die assemblerbefehle rol und ror.
die musst du dann 8x auf dein arbeitsregister anwendenund schon hast du
das von dir erwartete ergebniss.
einen schnelleren befehl oder lösung habe ich für dieses problem auch
noch nicht gefunden.

MfG
Sebastian

von Rufus T. Firefly (Gast)


Lesenswert?

Eine bitweise Spiegelung bekommt man mit ROL/ROR alleine nicht hin.

  76543210 -> ROR
= C7654321 (0 im Carry)

  C7654321 -> ROR
= 0C765432 (1 im Carry)

  0C765432 -> ROR
= 10C76543 (2 im Carry)

Gewollt ist aber:

  76543210 -> Operation X
  01234567

Für eine 4-Bit-Zahl sähe das in C so aus:

  Wert = ((Wert & 1) << 3) | (((Wert >> 1) & 1) << 2) | (((Wert >> 2) &
1) << 1) | ((Wert >> 3) & 1);

Das ist aber aufgrund der vielen Schiebeoperationen sehr ineffizient
in Assemblercode umzusetzen, erst recht, wenn man das auf 8 Bit
ausweitet.

von Sebastian Schildt (Gast)


Lesenswert?


von Jörg Wunsch (Gast)


Lesenswert?

#include <avr/io.h>

static _inline_ uint8_t
mirror(uint8_t b)
{
        uint8_t res;

        _asm_ volatile("ldi r25, 8" "\n"
                        "1: ror %1" "\n"
                        "rol %0" "\n"
                        "dec r25" "\n"
                        "brne 1b":
                        "=&r" (res):
                        "r" (b):
                        "r25");
        return res;
}

int
main(void)
{
        uint8_t i;

        i = 0x6f;
        i = mirror(i);

        return i;
}

von Dido (Gast)


Lesenswert?

Ich danke euch alle fuer die super schnellen Antworten! Leider hatte ich
erst jetzt Zeit die zu lesen. Also es ist  nicht trivial so was zu
machen. Habe gehofft auf eine Loesung mit 2-3 assembler befehlen, aber
leider nicht der Fall. Dann werde ich am besten alle Hex zahlen einfach
mit den vorgeschlagenen C beispiele neu umrechnen um uebefluessiges Code
zu sparen.

Gruesse Dido

von Matthias (Gast)


Lesenswert?

Hi

mit einer Look-UP Tabelle ist es trivial. Aber es kostet halt ein
bischen Speicher. Auf einem Mega128 ist das kein Problem. Auf einem
2313 evtl. aber schon.

Matthias

von Rufus T. Firefly (Gast)


Lesenswert?

Einige Prozessoren haben Befehle*, um zwei Nibbles zu vertauschen. Damit
kann man die Größe der Lookup-Table deutlich (auf 16 Bytes) reduzieren.

Also:

7654 3210

Lookuptable auf untere vier Bit anwenden

7654 0123

Nibbles tauschen

0123 7654

Lookup-Table auf untere vier Bit anwenden

0123 4567

Das sollte sich realisieren lassen.

*) MCS51 & AVR: SWAP

von Jörg Wunsch (Gast)


Lesenswert?

Ganz davon abgesehen, die von mir vorgeschlagene Lösung beinhaltet
doch nur zwei Assemblerbefehle für die eigentliche Bitschieberei, drei
weitere werden für die Schleife gebraucht.  OK, es sind paar Takte
mehr als mit der lookup table, genauer: 8 * 5 + 1 Takte.  Wie schnell
musst Du denn sein?

Die von Rufus vorgeschlagene Variante hat natürlich auch was, ist
dafür ein wenig aufwendiger zu codieren.  Mit bisschen Glück kann man
die sogar komplett in C schreiben, irgendwie kann ich mich erinnern,
dass der AVR-GCC den SWAP-Befehl auch hineinoptimieren kann.

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.