www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik c binärvariable drehen


Autor: Sonke A. (soeni)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie kann man in c eine Binärzahl drehen also von

0b01010101
zu
0b10101010

danke im Voraus

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Invertieren mit ~

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das Beispiel ist schlecht gewählt.

Ist mit "Drehen" ein Vertauschen von MSB und LSB gemeint?

Soll aus 10100000
         00000101

werden?

Oder --und dann hätte Sven die Lösung bereits genannt--
soll daraus
         01011111

werden?

Autor: sönke (soeni) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
nein aus 10100000 soll 00000101 werden.

ich habe ein display in einer Schlatung falschrum an einen Port 
angeschlossen und möchte dies nun im Programm korigieren, indem ich das 
Datenwort einfach drehe, wenn das möglich ist.

Autor: Roland Praml (pram)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
also aus

abcdefgh -> hgfedcba

das machst vermutlich am schnellsten über eine Lookuptable. Diese muss 
im Idealfall die Größe von 256 Bytes haben und da steht schon der fertig 
berechnete Wert drin.
Alternativ kannst das auch in 2 Schritten machen, zuerst das Nibble 
"abcd" in der Tabelle nachschlagen, dann "efgh" und die entsprechenden 
Werte dann eben mit Shifts etc. verodern

also
data[0b0000]=0b0000;
data[0b0001]=0b1000;
data[0b0010]=0b0100;
...
data[0b1111]=0b1111;

unsigned char reverse(unsigned char inp ) {
  return (data[inp &0x0F] << 4) | data[inp  >> 4];
}

Beim AVR data ggf im PROGMEM ablegen und mit enntsprechenden Makrros 
zugreifen.

evtl gibt es aber auch noch eine elegantere Lösung, auf die Schnelle bin 
ich aber auf keine gkommen die nicht x-tausend shifts benötigt.

Gruß
Roland

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

Wenn du Assembler kannst:

8x    shr rxy
      rol ryx

geht am schnellsten.

MfG Spess

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
nach peda:
unsigned char mirror( unsigned char n )
{
  n = ((n >> 1) & 0x55) | ((n << 1) & 0xaa);
  n = ((n >> 2) & 0x33) | ((n << 2) & 0xcc);
  n = ((n >> 4) & 0x0f) | ((n << 4) & 0xf0);
  return n;
}


>indem ich das Datenwort einfach drehe, wenn das möglich ist.

Aber warum lässt du das nicht einfach weg. die Kommandos kannst du 
verher umrechnen. Dann heißen die halt anders und fertig. Bei den 
Bitmaps spielt das eh keine Rolle.. Es sei denn, es ist kein 
Grafikdisplay...

Autor: Sebastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab das mal so gelöst:

  for (i=0; i<8; i++){
    temp3 |= (((temp2>>i) & 1) << (7-i));
  }
temp3 ist dann das gespiegelte von temp2.

Aber denks nochmal durch. Das hat nie jemand richtig getestet.

Aber ich glaub, das von peda ist eh schneller.

Sebastian

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sebastian wrote:
> Hab das mal so gelöst:
>
>   for (i=0; i<8; i++){
>     temp3 |= (((temp2>>i) & 1) << (7-i));
>   }

um ehrlich zu sein, das ist so ziemlich das Ineffizienteste, was du 
hinlegen kannst :-) Der AVR mag Schiebereien um mehr als ein Bit 
(tem2>>i) aber soooowas von ungern... und das gleich noch zweimal, ne, 
Fingers wech!

Autor: Tim R. (vref)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wenn lookuptable zu groß, dann schon lieber so:

out = 0;
for(i=0; i<8; i++)
{
    out >>= 1;
    out |= in & 0x80;
    in  <<= 1;
}

ich denke, das meinte spess53 auch mit seinem etwas kryptischen "8x 
shr rxy
      rol ryx"


Vielleicht doch lieber die 8 Leitungen drehen... ? ;-)

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>auch mit seinem etwas kryptischen "8x

sollte eigentlich nur bedeuten: Acht mal ausführen. Werde in Zukunft das 
Roman-Format benutzen.

MfG Spess

Autor: Tim R. (vref)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
naja, der zeichensatz war ja nicht so das problem... ;-)

interessehalber: schiebt denn "SHR" das unterste bit in irgend ein 
"carry" register, das mit "ROL" wieder von unten reingeschoben wird?
wenn ja, dann wäre das ja wesentlich effektiver als jegliche c-lösungen 
und wäre nen klarer fall für
#asm
#endasm

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Datenblatt lesen...

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>interessehalber: schiebt denn "SHR" das unterste bit in irgend ein
>"carry" register, das mit "ROL" wieder von unten reingeschoben wird?
>wenn ja, dann wäre das ja wesentlich effektiver als jegliche c-lösungen
>und wäre nen klarer fall für

Genau so ist es!

MfG Spess

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>schiebt denn "SHR" das unterste bit

Wenn du LSL/LSR meinst, dann nein.
Das machen nur die ROL/ROR.

AUs
unsigned char mirror( unsigned char n )
{
  n = ((n >> 1) & 0x55) | ((n << 1) & 0xaa);
  n = ((n >> 2) & 0x33) | ((n << 2) & 0xcc);
  n = ((n >> 4) & 0x0f) | ((n << 4) & 0xf0);
  return n;
}
macht der Compiler
; R24 ist in
MOV     R25,R24          ;Copy register
LSR     R25              ;Logical shift right
ANDI    R25,0x55         ;Logical AND with immediate
LSL     R24              ;Logical Shift Left
ANDI    R24,0xAA         ;Logical AND with immediate
OR      R25,R24          ;Logical OR
MOV     R24,R25          ;Copy register
LSR     R24              ;Logical shift right
LSR     R24              ;Logical shift right
ANDI    R24,0x33         ;Logical AND with immediate
LSL     R25              ;Logical Shift Left
LSL     R25              ;Logical Shift Left
ANDI    R25,0xCC         ;Logical AND with immediate
OR      R24,R25          ;Logical OR
MOV     R25,R24          ;Copy register
SWAP    R25              ;Swap nibbles
ANDI    R25,0xF0         ;Logical AND with immediate
SWAP    R24              ;Swap nibbles
ANDI    R24,0x0F         ;Logical AND with immediate
OR      R24,R25          ;Logical OR
CLR     R25              ;Clear Register
RET                      ;Subroutine return
; (R25:)R24 ist out
22 Befehle.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Matthias Lipinsky wrote:
>>schiebt denn "SHR" das unterste bit
>
> Wenn du LSL/LSR meinst, dann nein.
> Das machen nur die ROL/ROR.

Bitte? Auch bei LSx kommt das "rausfallende" Bit ins Carry. Der einzige 
Unterschied zwischen LSx und ROx besteht darin, was nachgeschoben wird.

Autor: Jochen Müller (taschenbuch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Och watt süüüssss,
Wird jetzt wieder lang-und-breit über etwas debattiert, was...

-JEDER asm-programmierer wissen MUSS?
-EIN BLICK ins Datenblatt klärt?
-VÖLLIG indiskutabel ist?

@lippy,
Wenn Dir ASM nicht so geläufig ist, dann ist das ja keine Schande.
Schändlich wird es, wenn man dann lauthals Falschinformationen 
verbreitet.

@sternst,
Genau das was Du schreibst stimmt natürlich. Das ist auch weder 
verhandlungsfähig noch diskutabel. Es ist so und fertig. Jede 
Gegenmeinung ist schlichtweg dummer Unsinn, der niemandem etwas nützt.

@vref,
das Bit wird nicht in IRGENDEIN CARRY geschoben, sondern in DAS 
(einzige) CARRY. Diese Präzisierung sollte auch ein C'ler kennen und 
beachten!

Jochen Müller

Autor: Sonke A. (soeni)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
danke, da es sich ja nur um einen Prototyp für mich handelt, denke ich 
werde ich einfach einen Adapter bauen, der die Belegung umdreht. Das 
macht das Ganze wesentlich einfacher.

Danke trozdem. ich dachte, dass es vielleicht eine Funktion wie 
reverse(); gibt. Naja egal. danke nochmal.

Autor: Sebastian Mazur (izaseba)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Danke trozdem. ich dachte, dass es vielleicht eine Funktion wie
> reverse(); gibt. Naja egal. danke nochmal.

Hmm,
Du hast doch eine mirror Funktion bekommen, wo liegt jetzt das Problem ?

Autor: Jörg X. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ganze mit inline Asm für AVR-GCC - nach dem Hinweis von Spess53:
uint8_t reverse_bits(uint8_t data)
{
  uint8_t result;
  // Ohne bzw. mit Schleife:
  // 35 Bytes  vs. 16Bytes
  // 20 Takte  vs. ~50 Takte
  // 2      vs. 3 Register
#ifdef UNROLL
  asm volatile("lsr %1 \n\t"
    "rol %0 \n\t"
    "lsr %1 \n\t"
    "rol %0 \n\t"
    "lsr %1 \n\t"
    "rol %0 \n\t"
    "lsr %1 \n\t"
    "rol %0 \n\t"
    "lsr %1 \n\t"
    "rol %0 \n\t"
    "lsr %1 \n\t"
    "rol %0 \n\t"
    "lsr %1 \n\t"
    "rol %0 \n\t"
    "lsr %1 \n\t"
    "rol %0 \n\t"
    :"&=r" (result)
    :"r"(data)
    );
#else
  int8_t i=8;
  do
  {
    asm volatile("lsr %1 \n\t"
      "rol %0 \n\t"
      :"&=r" (result)
      :"r"(data)
      );

  } while (--i);
#endif
  return result;
}
hth. Jörg

Autor: Matthias Lipinsky (lippy)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
>Bitte? Auch bei LSx kommt das "rausfallende" Bit ins Carry. Der einzige
>Unterschied zwischen LSx und ROx besteht darin, was nachgeschoben wird.

>Schändlich wird es, wenn man dann lauthals Falschinformationen
>verbreitet.


Da ich, zugegebenermaßen, das nicht wusste, habe ich im Datenblatt eines 
mega8 nachgeschaut: siehe Anhang.

Dort ist eindeutig zu erkennen, dass ROx durch das Carry schiebt, aber 
in der Funtkionsbeschreibung von LSx taucht das C nicht auf.

Da das offenbar eine falsche Information meinerseits war, ziehe ich 
diese zurück.
Aber, bitte einen anderen Ton.

Autor: Tim R. (vref)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Auch ich habe mich kurz gefragt, ob Assemblerprogrammieren irgendwie 
aggresiv macht... ;-)

DANKE Jörg!
Ich finde fundierte Codebeispiele und deine Taktzyklenberechnung 
wesentlich hilfreicher als Hinweise wie "Datenblatt lesen!".

Autor: Jörg X. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Codebeispiele und die Taktzyklen-Zahlen sind das direkte Ergebnis 
vom "Datenblatt lesen!" :-P

Autor: Sebastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nur der Vollständigkeit halber:
Aus der Hilfe im AVR Studio:

"LSL - Logical Shift Left

Description:

Shifts all bits in Rd one place to the left. Bit 0 is cleared. Bit 7 is 
loaded into the C flag of the SREG."


Damit wär dann alles geklärt hoffe ich.

Sebastian

Autor: Klugscheisser (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bemerkenswert finde ich den Assemblercode dern "der Compiler" (welcher 
war das?) erzeugt.
Insbesondere der Code welcher für die letzte Zeile:
n = ((n >> 4) & 0x0f) | ((n << 4) & 0xf0);
erzeugt wird ist, wenn ich das richtig sehe, eigentlich unnötig lang.
MOV     R25,R24          ;Copy register
SWAP    R25              ;Swap nibbles
ANDI    R25,0xF0         ;Logical AND with immediate
SWAP    R24              ;Swap nibbles
ANDI    R24,0x0F         ;Logical AND with immediate
OR      R24,R25          ;Logical OR
CLR     R25              ;Clear Register
RET                      ;Subroutine return
In der Wirkung vertauscht dieser Code ja die beiden Nibbles.
Tatsächlich aber ist das 1:1 übersetzen der C-Zeile hier unnötig,
da bereits das SWAP auch die Nibbles vertauscht.
Es könnte also
SWAP    R24              ;Swap nibbles
CLR     R25              ;Clear Register
RET                      ;Subroutine return
heissen.
Ich wollte nämlich selbst mal nachschauen ob WinAVR das merkt. Leider 
habe ich es allerdings nicht installiert.
Daher bitte nochmal die Frage an Matthias Lipinsky welchen Compiler er 
verwendet hat.

Autor: Sven L. (friemler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab da mal 'ne Verständnisfrage und zwar kann doch das &0x0f und das 
&0xf0 weggelassen werden, weil, wie mir bekannt, doch ursprünglich nicht 
vorhandene Bits eh als 0 angenommen werden.

>
> n = ((n >> 4) & 0x0f) | ((n << 4) & 0xf0);
> 

Also ist es doch das Gleiche wie:

>
> n = (n >> 4)|(n << 4);
> 

Nur kürzer, oder?

Autor: Klugscheisser (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Sven

Ja, ich denke Du hast Recht. In K&R, Hanser, 1983, S. 50 steht das beim 
schieben nach links Nullen nachgeschoben werden und beim schieben nach 
rechts eines unsigned auch. (Nur bei signed ist das nachgeschobene Bit 
nicht definiert).

Also könnte der Code von Peter Danneger tatsächlich so verbessert 
werden.
unsigned char mirror( unsigned char n )
{
  n = ((n >> 1) & 0x55) | ((n << 1) & 0xaa);
  n = ((n >> 2) & 0x33) | ((n << 2) & 0xcc);
  n = (n >> 4)| (n << 4);
  return n;
}

Würde mich mal interessieren was da an Asssemblercode rauskommt. Kann 
das mal einer durchjagen? (Vor allem wegen dem SWAP interessiert mich 
das).

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Kann das mal einer durchjagen?

(Rechts daneben hab ich die Befehle von oben eingefügt)
;mirror
MOV     R18,R24          Copy register                MOV     R25,R24   
LSR     R18              Logical shift right          LSR     R25
ANDI    R18,0x55         Logical AND with immediate   ANDI    R25,0x55
LSL     R24              Logical Shift Left           LSL     R24
ANDI    R24,0xAA         Logical AND with immediate   ANDI    R24,0xAA
OR      R18,R24          Logical OR                   OR      R25,R24
MOV     R25,R18          Copy register                MOV     R24,R25
LSR     R25              Logical shift right          LSR     R24
LSR     R25              Logical shift right          LSR     R24
ANDI    R25,0x33         Logical AND with immediate   ANDI    R24,0x33
LSL     R18              Logical Shift Left           LSL     R25
LSL     R18              Logical Shift Left           LSL     R25
ANDI    R18,0xCC         Logical AND with immediate   ANDI    R25,0xCC
OR      R25,R18          Logical OR                   OR      R24,R25
MOV     R24,R25          Copy register                MOV     R25,R24
SWAP    R24              Swap nibbles                 SWAP    R25
ANDI    R24,0xF0         Logical AND with immediate   ANDI    R25,0xF0
SWAP    R25              Swap nibbles                 SWAP    R24
ANDI    R25,0x0F         Logical AND with immediate   ANDI    R24,0x0F
OR      R24,R25          Logical OR                   OR      R24,R25
CLR     R25              Clear Register               CLR     R25
RET                      Subroutine return            RET

22Befehle ;-)

PS: WinAVR 4.13 Build 522

Autor: Jörg X. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
0K, hier ein "best of both Worlds ;)
unsigned char mirror( unsigned char n )
{
  n = ((n >> 1) & 0x55) | ((n << 1) & 0xaa);
  n = ((n >> 2) & 0x33) | ((n << 2) & 0xcc);
  asm volatile ("swap %0\t\n":"=r"(n):"0"(n));
  return n;
}
also:
  mov r25, r24
  lsl r25
  andi r25, 0xAA
  lsr r24
  andi r24, 0x55
  or r25, r24
  mov r24, r25
  lsl r24
  lsl r24
  andi r24, 0xCC
  lsr r25
  lsr r25
  andi r25, 0x33
  or r24,r25
  swap r24  
  clr r25
  ret
17 Befehle (34 Bytes), 18 Takte -- Ich wusste doch, dass da was geniales 
dran war (leider ist der Compiler da weniger genial)

hth. Jörg

Autor: ralf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wozu ist eigentlich 'clr r25' nötig?

Autor: Jörg X. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> wozu ist eigentlich 'clr r25' nötig?

Der AVR-GCC behandelt alle Funktionsparameter und -Rückgabewerte als 
(min.) 16 Bit breit 
(http://www.nongnu.org/avr-libc/user-manual/FAQ.htm... )
und das Highbyte ist eben 0.

rtfm ;) Jörg

Autor: Klugscheisser (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke Matthias und Jörg

Witzig finde ich ja, das er aus dem auf C-Ebene "optimierten" Code einen 
ASM-Code macht, der drei Register braucht, anstelle von zweien und dann 
in der Variante von Jörg mit dem händischem SWAP wieder nur zwei.

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>Nur bei signed ist das nachgeschobene Bit nicht definiert

Für Rechtsschieben von Signed existiert ein eigener Assemblerbefehl: 
'asr'.
Dabei wird bei jedem Schieben Bit7 wieder nach Bit7 kopiert. Damit 
bleibt das Vorzeichen erhalten.

MfG Spess

Autor: Klugscheisser (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Spess53

>>Nur bei signed ist das nachgeschobene Bit nicht definiert
>Für Rechtsschieben von Signed existiert ein eigener Assemblerbefehl:
>'asr'.

Vollständiges Zitat:
>Ja, ich denke Du hast Recht. In K&R, Hanser, 1983, S. 50 steht das beim
>schieben nach links Nullen nachgeschoben werden und beim schieben nach
>rechts eines unsigned auch. (Nur bei signed ist das nachgeschobene Bit
>nicht definiert).

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klugscheisser wrote:

> Nur bei signed ist das nachgeschobene Bit nicht definiert

In K&R noch nicht, aber ab C89 sehr wohl.

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>In K&R, Hanser, 1983...
Vielleicht nicht mehr 100%-ig Up-To-Date. Bist du sicher, das das auch 
für GCC gilt. Das würde mich schwer enttäuschen und wäre ein weitere 
Grund nicht auf C umzusteigen.

MfG Spess

P.S. Ich halte den Hanser-Verlag für relativ seriös, aber ich habe auch 
gelernt (manchmal schmerzhaft), das man nicht alles glauben soll, was 
geschrieben steht.

Autor: Klugscheisser (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Andreas
>In K&R noch nicht, aber ab C89 sehr wohl.
Danke für den Hinweis.

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]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [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.