www.mikrocontroller.net

Forum: Compiler & IDEs bitshifting in GCC mit einem Byte


Autor: Gregor (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

Ich hab ein komisches Problem an dem ich schon seit heute Vormittag 
sitze und einfach nicht die Lösung finde.

Ich schreibe eine Bibliothek für ein LCD mit mehreren Grafikfunktionen.

Nun hab ich ein Problem mit einer Bitshifting Operation, wo ich einfach 
nicht den Fehler finde.

Folgender Code (auszugsweise):

uint8_t pattern = 0x66; // 0b 0110 0110

pattern >>=2 ; // um 2 Bit nach rechts schieben


Nun würde ich mir das folgende Ergebnis erwarten:

1001 1001

Ich erhalte jedoch 0001 1001

Es sieht so aus als würde die Operation die 2 Bit nur rechts 
hinausschieben jedoch nicht links wieder einfügen, wie das bei der 
Assember Funktion rol bzw ror ist.

Wie kann ich den GCC dennoch davon überzeugen so ein bitweises Shiften 
durchzuführen?

MfG Gregor

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  Gregor (Gast)

>uint8_t pattern = 0x66; // 0b 0110 0110

>pattern >>=2 ; // um 2 Bit nach rechts schieben

>Nun würde ich mir das folgende Ergebnis erwarten:

>1001 1001

Wieso?

>Ich erhalte jedoch 0001 1001

Was vollkommen korrekt ist. ;-)

MFG
Falk

Autor: Sauger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gregor schrieb:
> Nun hab ich ein Problem mit einer Bitshifting Operation

Falk Brunner schrieb:
> Was vollkommen korrekt ist. ;-)


schieben (shiften) ist nun mal kein rotieren.

MfG

Autor: eklige Tunke (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Operatoren << und >> sind Shift -Operatoren. Deine rol und ror 
sind rotate -Befehle.
Shift  == Schieben
Rotate == Rotieren
Rotieren musst du in C selber bauen oder mal Inline-Assembler testen. 
Bei [1] scheint die richtige Funktion von Inline-Assembler angezweifelt 
zu werden, also probiere es vorher aus, oder baue dir selbst eine 
Funktion in C.

[1] 
http://www.avrfreaks.net/index.php?name=PNphpBB2&f...
[2] http://www.rn-wissen.de/index.php/Inline-Assembler...

Autor: Floh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
void ror(uint8_t &var)
{
  if(var & 0x01)
  {
    var >>=1;
    var |= 0x80;
  }
  else
  {
    var >>=1;
  }
}

Keine Garantie auf Richtigkeit :-)

Autor: Gregor (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für eure Antworten.

Ich hab da wohl zwei Dinge miteinander  vermischt. Ich werde die 
Funktion von Floh ausprobieren

Vielen dank nochmal

Autor: Andreas Ferber (aferber)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Floh schrieb:
> void ror(uint8_t &var)
> {

Erheblich kürzer, auch im generierten Code:
var = (var << 7) | (var >> 1);

Schneller in Punkto Taktzyklen ist es allerdings nicht, braucht nur 
weniger Speicher.

Andreas

PS: das mit den Taktzyklen war natürlich jetzt AVR-zentrisch, der OP 
hatte aber nicht erwähnt, dass er das verwenden würde. Andere 
Architekturen können andere Ergebnisse liefern, der x86-GCC z.B. macht 
bei -O2 aus meiner Zeile oben sogar wirklich ein ROL (um 7 Bits, also 
effektiv ROR), im Gegensatz zu der Variante mit Verzweigung, die mehr 
oder weniger "wörtlich" übersetzt wird.

Autor: eklige Tunke (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Andreas Ferber (aferber)
Oder gleich [1] befolgen, bei mir hat es geklappt.
Die Vermutung aus [1], dass das nur schiebt und nicht rotiert, stimmt 
nicht auf meinem x86_64 zumindest nicht. Bei einem µC sollte man das 
wohl nochmal simulieren oder mit ein paar LEDs testen...

Autor: Markus J. (markusj)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
eklige Tunke schrieb:
> Bei [1] scheint die richtige Funktion von Inline-Assembler angezweifelt
> zu werden

Jein, es wird nur darauf hingewiesen, dass die Instruktionen ROR und ROL 
eben nicht Rotate Right/Left sind, sondern Rotate Right/Left through 
Carry.
Darum reicht eine Instruktion nicht aus, da man sich eben um das 
Carry-Loch kümmern muss.

mfG
Markus

Autor: eklige Tunke (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Markus J. schrieb:
> Darum reicht eine Instruktion nicht aus, da man sich eben um das
> Carry-Loch kümmern muss.
Ah, jetzt verstehe ich. Scheint bei x86 aber anders zu sein.

Autor: Andreas Ferber (aferber)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
eklige Tunke schrieb:
>> Darum reicht eine Instruktion nicht aus, da man sich eben um das
>> Carry-Loch kümmern muss.
> Ah, jetzt verstehe ich. Scheint bei x86 aber anders zu sein.

Yepp. Bei x86 gibt es separate Instruktionen zur Rotation mit Carry, RCR 
und RCL.

Andreas

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.