Forum: Compiler & IDEs bitshifting in GCC mit einem Byte


von Gregor (Gast)


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

von Falk B. (falk)


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

von Sauger (Gast)


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

von eklige Tunke (Gast)


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&file=viewtopic&p=454612
[2] http://www.rn-wissen.de/index.php/Inline-Assembler_in_avr-gcc

von Floh (Gast)


Lesenswert?

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

Keine Garantie auf Richtigkeit :-)

von Gregor (Gast)


Lesenswert?

Danke für eure Antworten.

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

Vielen dank nochmal

von Andreas F. (aferber)


Lesenswert?

Floh schrieb:
> void ror(uint8_t &var)
> {

Erheblich kürzer, auch im generierten Code:
1
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.

von eklige Tunke (Gast)


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

von Markus J. (markusj)


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

von eklige Tunke (Gast)


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.

von Andreas F. (aferber)


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

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.