Forum: Mikrocontroller und Digitale Elektronik c binärvariable drehen


von Sonke A. (soeni)


Lesenswert?

Wie kann man in c eine Binärzahl drehen also von

0b01010101
zu
0b10101010

danke im Voraus

von Sven P. (Gast)


Lesenswert?

Invertieren mit ~

von Rufus Τ. F. (rufus) Benutzerseite


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?

von sönke (soeni) (Gast)


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.

von Roland P. (pram)


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
1
data[0b0000]=0b0000;
2
data[0b0001]=0b1000;
3
data[0b0010]=0b0100;
4
...
5
data[0b1111]=0b1111;
6
7
unsigned char reverse(unsigned char inp ) {
8
  return (data[inp &0x0F] << 4) | data[inp  >> 4];
9
}

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

von spess53 (Gast)


Lesenswert?

Hi

Wenn du Assembler kannst:

8x    shr rxy
      rol ryx

geht am schnellsten.

MfG Spess

von Matthias L. (Gast)


Lesenswert?

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


>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...

von Sebastian (Gast)


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

von Sven P. (Gast)


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!

von Tim R. (vref)


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... ? ;-)

von spess53 (Gast)


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

von Tim R. (vref)


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

von Sven P. (Gast)


Lesenswert?

Datenblatt lesen...

von spess53 (Gast)


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

von Matthias L. (Gast)


Lesenswert?

>schiebt denn "SHR" das unterste bit

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

AUs
1
unsigned char mirror( unsigned char n )
2
{
3
  n = ((n >> 1) & 0x55) | ((n << 1) & 0xaa);
4
  n = ((n >> 2) & 0x33) | ((n << 2) & 0xcc);
5
  n = ((n >> 4) & 0x0f) | ((n << 4) & 0xf0);
6
  return n;
7
}
macht der Compiler
1
; R24 ist in
2
MOV     R25,R24          ;Copy register
3
LSR     R25              ;Logical shift right
4
ANDI    R25,0x55         ;Logical AND with immediate
5
LSL     R24              ;Logical Shift Left
6
ANDI    R24,0xAA         ;Logical AND with immediate
7
OR      R25,R24          ;Logical OR
8
MOV     R24,R25          ;Copy register
9
LSR     R24              ;Logical shift right
10
LSR     R24              ;Logical shift right
11
ANDI    R24,0x33         ;Logical AND with immediate
12
LSL     R25              ;Logical Shift Left
13
LSL     R25              ;Logical Shift Left
14
ANDI    R25,0xCC         ;Logical AND with immediate
15
OR      R24,R25          ;Logical OR
16
MOV     R25,R24          ;Copy register
17
SWAP    R25              ;Swap nibbles
18
ANDI    R25,0xF0         ;Logical AND with immediate
19
SWAP    R24              ;Swap nibbles
20
ANDI    R24,0x0F         ;Logical AND with immediate
21
OR      R24,R25          ;Logical OR
22
CLR     R25              ;Clear Register
23
RET                      ;Subroutine return
24
; (R25:)R24 ist out
22 Befehle.

von Stefan E. (sternst)


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.

von Jochen M. (taschenbuch)


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

von Sonke A. (soeni)


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.

von Sebastian M. (izaseba)


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 ?

von Jörg X. (Gast)


Lesenswert?

Das ganze mit inline Asm für AVR-GCC - nach dem Hinweis von Spess53:
1
uint8_t reverse_bits(uint8_t data)
2
{
3
  uint8_t result;
4
  // Ohne bzw. mit Schleife:
5
  // 35 Bytes  vs. 16Bytes
6
  // 20 Takte  vs. ~50 Takte
7
  // 2      vs. 3 Register
8
#ifdef UNROLL
9
  asm volatile("lsr %1 \n\t"
10
    "rol %0 \n\t"
11
    "lsr %1 \n\t"
12
    "rol %0 \n\t"
13
    "lsr %1 \n\t"
14
    "rol %0 \n\t"
15
    "lsr %1 \n\t"
16
    "rol %0 \n\t"
17
    "lsr %1 \n\t"
18
    "rol %0 \n\t"
19
    "lsr %1 \n\t"
20
    "rol %0 \n\t"
21
    "lsr %1 \n\t"
22
    "rol %0 \n\t"
23
    "lsr %1 \n\t"
24
    "rol %0 \n\t"
25
    :"&=r" (result)
26
    :"r"(data)
27
    );
28
#else
29
  int8_t i=8;
30
  do
31
  {
32
    asm volatile("lsr %1 \n\t"
33
      "rol %0 \n\t"
34
      :"&=r" (result)
35
      :"r"(data)
36
      );
37
38
  } while (--i);
39
#endif
40
  return result;
41
}
hth. Jörg

von Matthias L. (Gast)


Angehängte Dateien:

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.

von Tim R. (vref)


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!".

von Jörg X. (Gast)


Lesenswert?

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

von Sebastian (Gast)


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

von Klugscheisser (Gast)


Lesenswert?

Bemerkenswert finde ich den Assemblercode dern "der Compiler" (welcher 
war das?) erzeugt.
Insbesondere der Code welcher für die letzte Zeile:
1
n = ((n >> 4) & 0x0f) | ((n << 4) & 0xf0);
erzeugt wird ist, wenn ich das richtig sehe, eigentlich unnötig lang.
1
MOV     R25,R24          ;Copy register
2
SWAP    R25              ;Swap nibbles
3
ANDI    R25,0xF0         ;Logical AND with immediate
4
SWAP    R24              ;Swap nibbles
5
ANDI    R24,0x0F         ;Logical AND with immediate
6
OR      R24,R25          ;Logical OR
7
CLR     R25              ;Clear Register
8
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
1
SWAP    R24              ;Swap nibbles
2
CLR     R25              ;Clear Register
3
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.

von Sven L. (friemler)


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.

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

Also ist es doch das Gleiche wie:

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

Nur kürzer, oder?

von Klugscheisser (Gast)


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.
1
unsigned char mirror( unsigned char n )
2
{
3
  n = ((n >> 1) & 0x55) | ((n << 1) & 0xaa);
4
  n = ((n >> 2) & 0x33) | ((n << 2) & 0xcc);
5
  n = (n >> 4)| (n << 4);
6
  return n;
7
}

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

von Matthias L. (Gast)


Lesenswert?

>Kann das mal einer durchjagen?

(Rechts daneben hab ich die Befehle von oben eingefügt)
1
;mirror
2
MOV     R18,R24          Copy register                MOV     R25,R24   
3
LSR     R18              Logical shift right          LSR     R25
4
ANDI    R18,0x55         Logical AND with immediate   ANDI    R25,0x55
5
LSL     R24              Logical Shift Left           LSL     R24
6
ANDI    R24,0xAA         Logical AND with immediate   ANDI    R24,0xAA
7
OR      R18,R24          Logical OR                   OR      R25,R24
8
MOV     R25,R18          Copy register                MOV     R24,R25
9
LSR     R25              Logical shift right          LSR     R24
10
LSR     R25              Logical shift right          LSR     R24
11
ANDI    R25,0x33         Logical AND with immediate   ANDI    R24,0x33
12
LSL     R18              Logical Shift Left           LSL     R25
13
LSL     R18              Logical Shift Left           LSL     R25
14
ANDI    R18,0xCC         Logical AND with immediate   ANDI    R25,0xCC
15
OR      R25,R18          Logical OR                   OR      R24,R25
16
MOV     R24,R25          Copy register                MOV     R25,R24
17
SWAP    R24              Swap nibbles                 SWAP    R25
18
ANDI    R24,0xF0         Logical AND with immediate   ANDI    R25,0xF0
19
SWAP    R25              Swap nibbles                 SWAP    R24
20
ANDI    R25,0x0F         Logical AND with immediate   ANDI    R24,0x0F
21
OR      R24,R25          Logical OR                   OR      R24,R25
22
CLR     R25              Clear Register               CLR     R25
23
RET                      Subroutine return            RET

22Befehle ;-)

PS: WinAVR 4.13 Build 522

von Jörg X. (Gast)


Lesenswert?

0K, hier ein "best of both Worlds ;)
1
unsigned char mirror( unsigned char n )
2
{
3
  n = ((n >> 1) & 0x55) | ((n << 1) & 0xaa);
4
  n = ((n >> 2) & 0x33) | ((n << 2) & 0xcc);
5
  asm volatile ("swap %0\t\n":"=r"(n):"0"(n));
6
  return n;
7
}
also:
1
  mov r25, r24
2
  lsl r25
3
  andi r25, 0xAA
4
  lsr r24
5
  andi r24, 0x55
6
  or r25, r24
7
  mov r24, r25
8
  lsl r24
9
  lsl r24
10
  andi r24, 0xCC
11
  lsr r25
12
  lsr r25
13
  andi r25, 0x33
14
  or r24,r25
15
  swap r24  
16
  clr r25
17
  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

von ralf (Gast)


Lesenswert?

wozu ist eigentlich 'clr r25' nötig?

von Jörg X. (Gast)


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.html#faq_reg_usage )
und das Highbyte ist eben 0.

rtfm ;) Jörg

von Klugscheisser (Gast)


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.

von spess53 (Gast)


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

von Klugscheisser (Gast)


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).

von Andreas K. (a-k)


Lesenswert?

Klugscheisser wrote:

> Nur bei signed ist das nachgeschobene Bit nicht definiert

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

von spess53 (Gast)


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.

von Klugscheisser (Gast)


Lesenswert?

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

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.