www.mikrocontroller.net

Forum: Compiler & IDEs Shift-Problem?


Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

ich bin blutiger Anfänger, also bitte um Nachsicht ;-)

In einem Programm möchte ich warten, bis auf PIND die letzten drei Bits 
1 sind. Meine Frage:

Warum tut es so:
while(~PIND & 0b00000111){warte();}

aber nicht so:
while((PIND << 5) != 0b11100000){warte();}

Die obere Bedingung wird false, wenn alle drei Bits 1 sind, wie 
gewünscht. Die untere Bedingung wird aber nie false, also die 
while-Schleife nie verlassen.

Danke schonmal,
Martin

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich würde auf ein Vorzeichenproblem tippen.  Durch die Schiebeoperation
wird der Typ des entsprechenden Ausdrucks nach `int' promoted, und
sobald dann das Bit 7 gesetzt ist, werden die Bits 8...15 auch
gesetzt.

Probiere mal, ob das sich ändert, wenn du explizit mit "5U" schiebst
statt "5".

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
War mir gar nicht klar, dass der uint8 dann zum int wird. Das führt mein 
Shiften natürlich ad absurdum.

5U hat leider den gleichen Effekt.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich würde sagen, dass das ein Compilerfehler ist, der optimiert hier 
etwas zu clever. Der Code sieht nämlich so aus:
+0000002F:   C001        RJMP    PC+0x0002        Relative jump
+00000030:   D006        RCALL   PC+0x0007        Relative call subroutine
+00000031:   B380        IN      R24,0x10         In from I/O location
+00000032:   3087        CPI     R24,0x07         Compare with immediate
+00000033:   F7E1        BRNE    PC-0x03          Branch if not equal

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kann ich so einen Codeabschnitt irgendwie als volatile o.ä. markieren, 
damit er nicht kaputtoptimiert wird?

Autor: Der Albi (der-albi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo.
Es gibt auch noch einen interessanten Unterschied: In der ersten Version 
überprüfst du mit Bitoperatoren, ob die unteren 3 Bit gesetzt sind. Das 
ist ok. Die Anderen Bits von PINx spielen dadurch keine rolle.

Bei der unteren Variante, vergleichst du logisch. Dabei zählen alle 
Bits.
Soweit ich weiß, arbeitet der Compiler bei so einem Vergleich mit ganzen 
ints. Also in dem fall 16bit. Das Shift5 löscht somit die anderen bits 
nicht.
Sie werden einfach ins HighByte verschoben. Dein 8bit Konstanten 
ausdruck ist auch ein int. sein HighByte ist 0.
Somit spielen die anderen Bits von PINx plötzlich eine Rolle.
Ich vermute das alles nur ;-) Bitte nicht lachen ;-)
Bei dem gezeigtes ASM weiß ich leider nicht, welche Version das ist. 
vermutlich die untere.. das all mein gebrabbel widerlegen würde :-D

Ich würde es nochmal mit:

while((unsigned char)(((unsigned char)PIND) << 5) != (unsigned 
char)0b11100000){warte();}
probieren. Das ist Nummer sicher ;-)

oder:

while(((PIND&0x07) << 5) != 0b11100000){warte();}

So.
MFG

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich bin nach etwas Überlegung zur gleichen Erkenntnis gekommen.

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich kann die Erklärung von Der Albi und Jörg (promotet zu was mit 16bit) 
bestätigen. Habe es jetzt (fast) wie von Der Albi vorgeschlagen:
while(( (PIND & 0b00000111) << 5) != 0b11100000){...}

Klappt wunderbar.

Danke Leute!

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Argh, ich konnte diese Integer-Promotions noch nie leiden.

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.