Forum: Mikrocontroller und Digitale Elektronik Bit schieben oder vergleichen


von Jens (Gast)


Lesenswert?

Hallo,
ich habe mal eine Interessensfrage. Da ich nichts habe, womit ich das 
messen könnte, wollte ich mal nachfragen, ob das hier jemand weiß.
Ich möchte z.B. die oberen 4 Bits von einem Byte wissen. Dazu habe ich 
nun zwei möglichkeiten:
1
x = Byte >> 4;
2
x = Byte & 0x0F;

Welche Berechnung wäre bei sowas schneller? Und welche Schreibweise wird 
bevorzugt?

von Jens (Gast)


Lesenswert?

Ahh,
es muss natürlich heißen
1
x = Byte >> 4;
2
x = Byte & 0xF0;

von Alram L. (alram)


Lesenswert?

dir ist aber schon klar, dass x in den beiden fällen nacher nicht den 
gleichen inhalt hat? also wird es wohl auch darauf ankommen, wie x 
weiter verarbeitet werden soll.
und letztlich wird/kann es wohl auch von der verwendeten CPU architektur 
abhängig sein ...

vG Alram

von Stefan F. (Gast)


Lesenswert?

Um solche Fragen zu klären schreibe ich ein kleines Testprogramm und 
lasse mir vom Compiler das Listing des erzeugten Assembler Codes 
ausgeben. Dann schaue ich in der Doku 
(http://ww1.microchip.com/downloads/en/devicedoc/atmel-0856-avr-instruction-set-manual.pdf) 
nach, wie viele Takte die verwendeten Assembler-Befehle benötigen.

Falls du eine Vorlage für das Makefile brauchst: 
http://stefanfrings.de/avr_hello_world/index.html

von Jens (Gast)


Lesenswert?

Alram L. schrieb:
> und letztlich wird/kann es wohl auch von der verwendeten CPU architektur
> abhängig sein ...

Ok, dass kann ich verstehen

Alram L. schrieb:
> dir ist aber schon klar, dass x in den beiden fällen nacher nicht den
> gleichen inhalt hat? also wird es wohl auch darauf ankommen, wie x
> weiter verarbeitet werden soll.

Warum ist x unterschiedlich? Und warum kommt es auf der 
weiterverarbeitung drauf an?

Stefanus F. schrieb:
> Um solche Fragen zu klären schreibe ich ein kleines Testprogramm und
> lasse mir vom Compiler das Listing des erzeugten Assembler Codes
> ausgeben.

Danke, werde ich auch mal versuchen.

von A. S. (Gast)


Lesenswert?

Also Zusammengefasst:
- Es sind zwei unterschiedliche Funktionalitäten
- Es hängt davon ab, welchen Controller Du hast, welchen Compiler und 
welche (Optimierungs-)Einstellungen
- Es hängt davon ab, was davor und danach mit Byte oder X geschieht 
(also ob und welche Zwischenergebnisse sowieso noch gebraucht werden)
- Es hängt auch davon ab, ob BYTE signed ist (beim >>, falls der µC 
Nibbles swappen kann) und welche größe X hat.

In den meisten Fällen sollte die Bitmaske besser oder gleich gut sein. 
Oder anders: Es ist unwahrscheinlich, dass die Schiebeoperation weniger 
Takte braucht.

Wenn es voraussichtlich weniger als 1000 Mal Pro Sekunde pro MHz 
aufgerufen wird, ist das Ergebnis für reale Software wohl kaum relevant.

Wenn es mehr Aufrufe werden, geht auch Messen zur Laufzeit mit µs-Ticker 
(1000 Aufrufe, sicherstellen, dass sie nicht wegoptimiert werden, vorher 
und nacher einen Counter mit ~µs-Auflösung auslesen und Differenz 
bilden.) Mal die eine Version, dann die andere, jeweils in ihrem 
"natürlichen" Kontext.

von Stefan F. (Gast)


Lesenswert?

Jens schrieb:
> Warum ist x unterschiedlich?

Weil es zwei völlig unterschiedliche Operationen sind - sagt meine 
Blitzbirne.

> x = Byte >> 4;

x wird um 4 Bits nach rechts verschoben.
Aus 11001000 wird 00001100.

> x = Byte & 0xF0;
Aus 11001000 wird 11000000.

von Alram L. (alram)


Lesenswert?

Jens schrieb:
> Warum ist x unterschiedlich? Und warum kommt es auf der
> weiterverarbeitung drauf an?

du willst wissen, welche von zwei varianten schneller ist. das geht 
erstmal nur, wenn die beiden letztlich auch das gleiche ergebnis 
liefern.

und deine beiden codezeilen liefern nicht das gleiche ergebnis. damit 
sind sie nicht vergleichbar.

nimm mal an Byte hat den wert 0b11000011:

x = Byte >> 4;
dann hat x nacher den wert 0b00001100

x = Byte & 0xF0;
dann hat x nacher den wert 0b11000000

jetzt hast zwei unterschiedliche ergebnisse und bis daher macht ein 
vergleich keinen sinn.

du wirst aber x vermutlich für weitere berechnungen oder tests 
benötigen. und diese müssen sich in den beiden varianten ebenfalls 
unterscheiden. in summe kann sich ein performanceunterschied ergeben. 
Wenn du x nicht weiter verwendest wird dir jeder vernünftige compiler 
den code komplett löschen ... und damit wäre er gleich schnell. :)

von c-hater (Gast)


Lesenswert?

Jens schrieb:

> Warum ist x unterschiedlich?

Weil in einem Fall z.B. aus 0x38 0x30 wird und im anderen 0x03, was 
ziemlich verscheiden voneinander ist.

Du solltest die Sprache lernen, mit der du hantierst!

> Und warum kommt es auf der
> weiterverarbeitung drauf an?

Weil es manchmal halt nützlicher ist, 0x30 zu haben und manchmal 
nützlicher, 0x03 zu haben. Aber davon, das zu verstehen, bist du mindest 
so weit entfernt, wie Alpha Centauri von Sol. Lichtjahre...

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

c-hater schrieb:
> Aber davon, das zu verstehen, bist du mindest so weit entfernt, wie
> Alpha Centauri von Sol. Lichtjahre...
Und deine "Erklärung" trägt nicht dazu bei, die beiden näher zusammen zu 
bringen.

BTW: wie weit bist du mit deinem Knigge schon gekommen? Ein Tipp: man 
kann da umblättern, der hat mehrere Seiten...

von W.S. (Gast)


Lesenswert?

Jens schrieb:
> Ich möchte z.B. die oberen 4 Bits von einem Byte wissen. Dazu habe ich
> nun zwei möglichkeiten:x = Byte >> 4;
> x = Byte & 0x0F;
>
> Welche Berechnung wäre bei sowas schneller? Und welche Schreibweise wird
> bevorzugt?

Ja, WAS möchtest du denn nun genau von den oberen 4 Bit wissen?
1. ob eines davon nicht null ist?
2. ob sie gleich einem gewünschten Bitmuster sind?
3. ob du sie als Nibble weiterverarbeiten willst?

Für 1. geht es eigentlich immer so am einfachsten:
if(x % 0xF0) ..dann...

Für 2. geht es im Prinzip so:
if((x & 0xF0)==MeinMuster) ..dann...

für 3. geht es so:
nib = (x >> 4) & 0xF;

wobei man das Maskieren meistens auch weglassen kann, aber sowas kann 
architekturabhängig sein. Mit dem & 0xF ist man jedoch immer auf der 
sicheren Seite.

Und wie sich das alles in Maschinenbefehlen darstellt, ist nun wirklich 
aus dem C-Quelltext nicht zu entnehmen. Ich hab z.B. beim Keil schon 
Konstrukte für den ARM-Mode gesehen, wo ähnlich zum Fall 1. das etwa so 
ging, daß x zunächst um einige Bit rechtsverschoben und dann 
linksverschoben wurde, was in dem speziellen Falle innerhalb eines 
einzigen Maschinenbefehls ging.

Du kannst also erwarten, daß du aus dem erzeugten Maschinencode oftmals 
nicht mehr ohne längeres Grübeln herausfinden kannst, was da als 
Quellcode gewesen ist. Manchmal geht es auch garnicht mehr.

Und als Schreibweise rate ich dir an, deine Quelle möglichst einfach zu 
schreiben, auch wenn das oftmals mehrere Zeilen ergibt anstelle einer 
schwer zu lesenden Zeile.

Es ist heutzutage auch völlig OK, kompliziertere Zuweisungen in einzelne 
Zuweisungen aufzuteilen - der Compiler optimiert das schon.

W.S.

von W.S. (Gast)


Lesenswert?

W.S. schrieb:
> x % 0xF0

falsche taste erwischt..

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.