Forum: Compiler & IDEs seltsamer Assemblercode


von Jogibär (Gast)


Lesenswert?

Hallo,

ich habe da ein Problem, wo ich nicht weiter komme.

Folgender Programmauszug:

case 0:
          {
          sbi (PORTC,1);
          sbi (PORTC,2);
          cbi (PORTC,0);
          PORTD = a |= ( PIND &= 0x80);
          zaehler = 1;
          break;
          }

PortD als Ausgänge definiert.
Ich will den aktuellen Zustand der Ausgänge einlesen, ein Bit, das ich
nicht
verändern möchte , herausfiltern ( PORTD.7) und mit den Bits der
Variable a
logisch ODER verknüpfen.
Dabei soll das 7.Bit des Ausgangs seinen Zustand behalten.

Nur irgendwie habe ich einen Denkfehler.Somit habe ich mir den
Assemblercode
angeschaut, und etwas seltsames entdeckt.

Assembler Code ( Auschnitt);

27e:   02 97           sbiw    r24, 0x02       ; 2
 280:   c9 f0           breq    .+50            ; 0x2b4
 282:   08 95           ret
 284:   a9 9a           sbi     0x15, 1 ; 21
 286:   aa 9a           sbi     0x15, 2 ; 21
 288:   a8 98           cbi     0x15, 0 ; 21
 28a:   80 b3           in      r24, 0x10       ; 16
 28c:   80 78           andi    r24, 0x80       ; 128
 28e:   80 bb           out     0x10, r24       ; 16
 290:   80 b3           in      r24, 0x10       ; 16
 292:   82 2b           or      r24, r18
 294:   82 bb           out     0x12, r24       ; 18
 296:   81 e0           ldi     r24, 0x01       ; 1
 298:   0a c0           rjmp    .+20            ; 0x2ae

In Zeile 28a ließt er den Port ein,in 28c wird mit 0x80 UND verknüpft
und in
Zeile 28e auf PIND !!! ausgegeben, sowie in Zeile 290 von PIND wieder
eingelesen.

Doch laut Datenblatt ist PIND nur lesbar !?!
Darum müßte er in Zeile 290 den alten PIND Wert wieder einlesen.

Ehrlich gesagt, ich verstehe das nicht ganz.
Kann mir jemand mal das erklären ?

mit freundlichen Grüßen

Jogibär

von Peter D. (peda)


Lesenswert?

Sowas kommt davon, wenn man 3 Zuweisungen zugleich macht.
Schreibs besser hintereinander.

Den Compiler interessiert nicht, welche Bedeutung eine IO-Adresse hat.

Er führt brav alles aus, was Du hinschreibst, auch wenn es unsinnig
ist.


Peter

von Jogibär (Gast)


Lesenswert?

Hallo,

danke für deinen Hinweis.

Der Fehler lag in   < PIND &= 0x80 >

Der Compiler verknüpft beide Bytes logisch UND , und
speichert dann das Ergebnis in dem ersten Parameter ( in diesem Fall
PIND).
Deshalb der Schreibzugriff auf PIND.

Bin noch nicht solange dabei, ein paar Fehler seien mir gestattet.

Jogibär

von Peter D. (peda)


Lesenswert?

"Bin noch nicht solange dabei, ein paar Fehler seien mir gestattet."

Deshalb ja mein Tip "immer nur eine Zuweisung je Zeile".

Mehrfachzuweisungen ergeben selten kürzeren Code, höchstens den Sieg im
Unleserlichkeitswettbewerb.


Peter

von Rolf F. (Gast)


Lesenswert?

Dazu kommt noch, dass = und |= die gleiche Priorität haben; da kommt je
nach Commpiler etwas anderes heraus, aus der Zeile.

von Fritz Ganter (Gast)


Lesenswert?

Wegen Mehrfachzuweisungen:

Auch wenn man es gerne macht, tut es nicht, da dabei schlechterer Code
rauskommt.

also statt:

a=b=c;

besser

a=c;
b=a;

schreiben, im ersten Fall liest er den Inhalt von c 2 mal, im zweiten
Fall verwendet er das Register wieder.

Ist im normalen Code vielleicht egal, aber in Interruptroutinen bringts
schon was.

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.