Binäre Zahl drehen

Gast #179404
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!
Gast #179406
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
Gast #179407
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.
Gast #179408
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
Gast #179409
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.
Gast #179411
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;
}
Gast #179412
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
Gast #179414
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
Gast #179415
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren