mega 32 compilerfehler

Gast #283213
Lesenswert?

hallo leute

ich hatte im laufe der woche schon eine umfrage gestartet wegen eines
vermuteten compilerfehlers. hier nochmal die eckdaten:

avrgcc3.3, pn2, avrstudio4.11 und jtag-ice
compilereinstellungen: richtiger controller, optimierung s
programmiert wird in c.

folgendes detail:

123:        dac_set_value(URDM_1,-1.5);    // AP für MOSFET UGS=-3V
+00000FC2:   E040        LDI     R20,0x00         Load immediate
+00000FC3:   E050        LDI     R21,0x00         Load immediate
+00000FC4:   EC60        LDI     R22,0xC0         Load immediate
+00000FC5:   EB7F        LDI     R23,0xBF         Load immediate
+00000FC6:   E081        LDI     R24,0x01         Load immediate
123:        dac_set_value(URDM_1,-1.5);    // AP für MOSFET UGS=-3V
+00000FC7:   940E0000    CALL    0x00000000       Call subroutine
127:          dac_set_value(US_1,1.5);    // Startpunkte setzen
+00000FC9:   E040        LDI     R20,0x00         Load immediate
---- No Source
------------------------------------------------------------------------ 
------------
+00000FCA:   E050        LDI     R21,0x00         Load immediate
+00000FCB:   EC60        LDI     R22,0xC0         Load immediate
+00000FCC:   E37F        LDI     R23,0x3F         Load immediate
+00000FCD:   E080        LDI     R24,0x00         Load immediate
+00000FCE:   CFF8        RJMP    PC-0x0007        Relative jump

hinter diesem asm-code verbergen sich folgende zeilen im pn

  dac_set_value(URDM_1,-1.5);

  for(;;)
  {
    dac_set_value(US_1,1.5);

  }
effekt1:

der pc wird vom compiler aus der schleife herausgeschickt
in die zeile vor der schleife!

+00000FCE:   CFF8        RJMP    PC-0x0007        Relative jump

wer hat infos woran das liegen kann?

m. gerlach
Moderator Persönliche Seite #283216
Lesenswert?

Naja, ich wollte etwas compilierfähiges haben, damit ich mir
den Compiler-Output mal angucken kann.

Aber eigentlich hat sich das schon erledigt, mir ist auf dem
Heimweg beim Radeln eingefallen, dass der Compiler eben einfach
nur genial compiliert hat.

Der Code ist komplett korrekt.  Der Compiler hat nur festgestellt,
dass er die beiden Funktionsaufrufe in einen vereinigen kann.
Das ist ein typisches Beispiel, an dem man sieht, dass es eben
einfach nicht immer eine 1:1-Zuordnung vom Objektcode zurück zum
C-Code geben kann: der Funktionsaufruf auf Adresse 0xFC7 gehört
sowohl zu Zeile 123 als auch Zeile 127 im Quelltext.
Gast #283217
Lesenswert?

Wo ist nun dein Problem? Der RJMP spring nach 0FC7 und genau das soll er
doch auch. Nur ist der Compiler ein bischen schlauer als Du angenommen
hast, denn er verwendet den selben CALL-Befehl gleich für beide
Funktionsaufrufe. Nur eben mit verschiedenen Parametern. Genau wie er
soll.
Gast #283220
Lesenswert?

Wieso? Es stimmt doch alles.

Ausserhalb und innerhalb der Schleife wird doch die gleiche Funktion
aufgerufen. Also passiert bei Ablauf des Codes folgendes:

  1.) Werte für den ersten Funktionsausruf laden.
  2.) Funktion aufrufen.
  3.) Werte für den Funktionsaufruf in der Endlosschleife laden.
  4.) Goto zu Schritt 2.

Alternativ könntest Du das natürlich auch so schreiben:

  1.) Werte für den ersten Funktionsausruf laden.
  2.) Funktion aufrufen.
  3.) Werte für den Funktionsaufruf in der Endlosschleife laden.
  4.) Funktion aufrufen.
  5.) Goto zu Schritt 3.

Das nun hat aber einen unnötigen Schritt zuviel. Also kann man den auch
wegoptimieren...

Und noch lustiger wird es beim gcc-4.x mit Tail-Call-Optimierungen,
besonders in rekursiven Funktionen.
Da kann man dann in C fast schon so wie in LISP programmieren, und
trotzdem gibt's kein Stack-Overflow. ;-)
#283221
Lesenswert?

OK das leuchtet mir soweit sogar ein. Aber die funktionen werden auch
sozusagen vertauscht ausgeführt.
ich habe einen haltepunkt in die endlosschleife gesetzt. springt der
debugger da hin und lasse ich den nächsten schritt ausführen springt
der debugger aus der schleife führt dabei aber nicht die funktion in
der schleife aus. erst wenn der debugger wieder über die "aussere"
funktion gelaufen ist passiert hardwaremässig das was passieren soll.

und warum ist das kein fehler wenn ich will, dass die "aussere"
funktion nur einmal ausgeführt wird jedoch die "innere" im anschluss
daran ständig und er faktisch beide immerwieder ausführt? dann genau so
läuft das programm ab. beide funktionen werden immerwieder ausgeführt!
#283222
Lesenswert?

ok jetzt hab ichs tatsächlich verstanden. alles klar. kein fehler! sieht
eben nur so aus. ich finds nutürlich ein wenig bescheurt vom studio,
dass da nicht der sinn des asm-codes verstanden wird und dem benutzter
wenigstens vorgegaukelt wird, dass alles so läuft wie gewünscht.

aber noch was anderes

habt ihr irgendeine idee welche ursachen in frage kommen, wenn
code-teile mal richtig und mal falsch ausgeführt werden
bsp:
variante a: 999938/1000000=0.999938
variante b: 999938/1000000=0.499969
Gast #283223
Lesenswert?

Der Debugger hat keine Chance. Wo technisch nur ein Funktionsaufruf ist,
hat er naturgemäss Probleme, diesen Aufruf mehreren Quellecodezeilen
zuzuordnen. Das ist der wohlbekannte Pferdefuss bei eingeschalteter
Code-Optimierung des Compilers.

Weshalb in solchem Kontext auch immer der Tip gegeben wird, bei Nutzung
des Debuggers die Code-Optimierung durch den Compiler abzuschalten. Was
bei Controllern freilich bisweilen Grenzen hat, wenn dabei das ROM
platzt.

Die Situation ist also nicht ideal, sie kann es nicht sein. Es kann
sogar das Paradox entstehen, dass ein mies optimierender Compiler im
praktischen Betrieb mit Debuggern angenehmer wirkt als ein gut
optimierender.

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