Assemblerbefehle ROL /ROR in C?

Gast #179218
Lesenswert?

Da wirst Du mit Inline-Assembler arbeiten müssen. Rotation ist keine in
C standardmäßig verfügbare Operation.
Ginge es nur ums Schieben, dann sähe das anders (nämlich so: << und >>)
aus.
Sich eine Rotation in C selbstzubasteln ist recht ineffizient.

  char quelle;
  char ziel;

  // Rotation in die eine Richtung
  ziel = (quelle << 1) | ((quelle & 0x80) >> 7);

  // Rotation andersrum
  ziel = (quelle >> 1) | ((quelle & 1) << 7);

Diese selbstgebaute Rotation rotiert nicht durch das Carry-Flag und
wird auf Prozessoren ohne "barrel-shifter" je nach Compiler recht
langsam. Das ließe sich allerdings umgehen, vorausgesetzt, daß der
Prozessor multiplizieren kann:

  // Rotation in die eine Richtung
  ziel = (quelle * 2) | ((quelle & 0x80) / 0x80);

  // Rotation andersrum
  ziel = (quelle / 2) | ((quelle & 1) * 0x80);

Ein brauchbar optimierender Compiler sollte das aber auch von selbst
auf die Reihe bekommen.
Gast #179219
Lesenswert?

Hallo Rufus,

Danke erstmal für diese Möglichkeit - die Schiebebefehle waren mir
schon bekannt - nutze ich im Moment auch. Kannst Du mir evtl. auch
sagen wie das das Rollen mit Inline-Assembler funktioniert?
Viele Grüße

Christian
Gast #179220
Lesenswert?

Das ist vom verwendeten Compiler und Prozessor abhängig ...

Mangels eigener Nutzung selbigens kann ich Dir da nicht weiterhelfen,
das wird aber sicherlich jemand anderes aus diesem Forum hier
hinbekommen.
#179221
Lesenswert?

"Sich eine Rotation in C selbstzubasteln ist recht ineffizient."

Das halte ich aber für ein Gerücht.

Eine echte Rotation gibt es beim AVR-Asssembler außerdem nicht, es wird
immer über C rotiert. Du mußt also immer noch von C nach Bit 0 (oder 7)
kopieren.

Die Frage ist eigentlich, wozu braucht man die Rotation ???

Meistens reicht das << bzw. >> völlig.


Peter
Gast #179222
Lesenswert?

Recht ineffizient ist sie, weil statt eines ROR/ROL-Befehles eben 'ne
ganze Latte Befehle erforderlich sind - die von mir geposteten
Codefragmente werden vom Compiler sicherlich nicht in ein, zwei Befehle
übersetzt.

Selbst wennn es nur ROR/ROL durchs Carry-Flag geben sollte, dürfte das
nachträgliche Übertragen des Carry-Flags nach Bit0/7 kaum mehr als
eines Befehles bedürfen, so daß so etwas in Assembler sicherlich
effizienter ist, als die Übersetzung des C-Konstruktes.

Rotationsoperatoren kommen IMHO in Verschlüsselungsalgorithmen des
öfteren vor.
#179223
Lesenswert?

Also unter "'ne ganze Latte Befehle" würde ich das doppelte und mehr
verstehen.

In Assembler braucht man 3 Befehle:

 lsr   r25
 brcc  label
 ori   r25, 0x80
label:


Und in C sähe das gleiche so aus:

 u8 temp = val;
 val >>= 1;
 if( temp & 0x01 )
   val |= 0x80;

Das sind dann 4 Assembler-Befehle, d.h. der Assemblercode ist gerade
mal nur 25% kleiner:

 66:   98 2f           mov     r25, r24
 u8 temp = val;
 val >>= 1;
 68:   96 95           lsr     r25
 if( temp & 0x01 )
 6a:   80 fd           sbrc    r24, 0
   val |= 0x80;
 6c:   90 68           ori     r25, 0x80


Peter
Gast #179225
Lesenswert?

Was soll der Compiler anderes als LSR aus einer Zeile mit >> machen?

Ob die "peephole"-Optimierung ein ROR aus dem ganzen Konstrukt
bastelt, kann ich nicht beurteilen*. Kann man das (als
Normalsterblicher) beim GCC in irgendeiner Weise beeinflussen?
Nach dem Motto Code-Fragment wird von Hand optimiertem Code-Fragment
gegenüber gestellt und der Compiler ersetzt dann entsprechend?

@Peter: Mit Deinem so formulierten C-Code gibst Du dem Compiler ja
schon den einen oder anderen Hinweis, auch verwendest Du eine
Hilfsvariable.
Wie sieht denn das Übersetzungsresultat* des von mir geposteten Codes
aus?


*) (beide) Habe hier keinen AVR-GCC verfügbar, kann daher nur "im
Trockenen" spekulieren.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren