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!
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)
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
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.
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
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.
#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; }
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
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
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.