Forum: Compiler & IDEs Compiler übersetzt nur Müll


von Giantics (Gast)


Lesenswert?

Selbst bei einfachen Programmen kommt bei mir manchmal nicht das
erwünschte Ergebnis aus dem Compiler (avr-gcc (GCC) 3.4.3; Atmega8).
Selbst einfache For-schleifen bringen ihn manchmal zum Aufhängen (der
verwendete Variablentyp stimmt). Wenn man dann die Optimierung
ausschaltet, dann gehts manchmal plötzlich! Also programmiert man
gemütlich so weiter. Und irgendwann mit einer ganz harmlosen Zeile Code
dreht der Controller wieder durch. Wenn man dann Glück hat, gehts mit
einer anderen Optimierungsstufe wieder. Irgendwann war ich dann an dem
Punkt, an dem keine Optimierungsstufe mehr einwandfrei funkioniert hat.
Aber in jeder ging irgendwas anderes nicht. Absolut nicht
nachvollziehbar. Ich hab jetzt auch gemerkt, dass die "hex"-Datei
nicht mit der "lss"-Datei übereinstimmt (Die Adressen der Funktionen
stimmen nicht). Kann das sein? Ist das ganze eventuell eine
Einstellungssache?
Controller und Frequenz sind in der Makefile eingetragen.

von A.K. (Gast)


Lesenswert?

Wie wär's mit einem Beispiel?

von Giantics (Gast)


Lesenswert?

#include <avr/io.h>
#include <stdint.h>
#include "lcd_atmega8.h"

void main(void)
{
  unsigned int i;
  LCD_Init();
  LCD_Clr();
  DDRB= (1<<PB0) | (1<<PB5);
  PORTB=1;
  for (i=0;i<=30000;i++) ;
  PORTB|= (1<<5);
  LCD_Str("irgendwas");
  while (1);
  return 0;
}

Hin und wieder kann man kurz das Wort auf dem LCD lesen, dann ists
wieder weg und irgenwann wieder da. Im gleichen Takt wechselt der
PortB-5 seinen Zustand. PortB-0 bleibt auf 5V.
Wenn ich die Schleife und die Port-Befehle rausmache, dann filmmert das
LCD (als obs ständig aktualisiert würde).
(Optimierungsstufe 0)

von A.K. (Gast)


Lesenswert?

Trivial, hier ohne Belang und vom Compiler angezeigt: return in einer
void-Funktion.

Welche Schleife rausgemacht? Sind 2 drin. Ohne die zweite tät's mich
nicht wundern. Wenn sich jedoch während der while(1)-Schleife auf dem
LCD oder den Ports etwas tut, dann liegt das Problem in der Hardware,
nicht der Software. Mal vorausgesetzt, dass die LCD-Routinen keine
Interrupts verwenden.

von Fritz G. (fritzg)


Lesenswert?

Bei  while (1); und bei der for-schleife schreib besser

while (1)
 asm volatile ("nop");


weil sonst optimiert er die Schleife weg.

von A.K. (Gast)


Lesenswert?

Der Compiler optimiert nur Dinge weg, die aus seiner keine Wirkung
haben. Die while(1)-Schleife aber darf er nicht wegoptimieren, da sonst
der Code dahinter ausgeführt würde.

Nicht zu verwechseln mit Zählschleifen. Da kann's schon sein, dass aus
for (i=1;i!=1000;++i); am Ende ein einfaches i=1000 wird.

von Giantics (Gast)


Lesenswert?

Konnte es noch weiter eingrenzen:
void main(void)
{
  unsigned int i;
  DDRB= (1<<PB0) | (1<<PB5);
  PORTB=1;
  for (i=0;i<=30000;i++) ;
  PORTB|= (1<<5);
  while (1) ;//asm volatile ("nop")
  return 0;
}
So bleibt PortB auf 1 stehen (d.h. er macht ab der For-Schleife nicht
mehr das, was er soll. Wenn ich jedoch das "asm..." in der while
Schleife eintrage, dann gehts wunderbar. Aber wieso passiert das mit
der Optimierungsstufe 0? In der "lss"-Datei steht der Befehl (rjmp
-2) noch drin. In der Hex stimmt dann gar nix mehr überein!
Außerdem war dies auch nur ein kleines Beispiel meiner Probleme. Bei
größeren Projekten habe ich keine Chance mehr irgendwas zu
kontrollieren. Da optimiert er einfach Sachen weg, obwohl sie nötig
sind. Ich habe keine Ahnung mehr was ich da machen kann. Hat von euch
niemand solche Probleme?

von Giantics (Gast)


Angehängte Dateien:

Lesenswert?

Die Hex liegt bei.
Gibts eine Möglichkeit, dass er alles so wie in der lss-Datei auch in
die Hex übernimmt?

void main(void)
{
  5c:  cd e5         ldi  r28, 0x5D  ; 93
  5e:  d4 e0         ldi  r29, 0x04  ; 4
  60:  de bf         out  0x3e, r29  ; 62
  62:  cd bf         out  0x3d, r28  ; 61
  unsigned int i;
  //LCD_Init();
  //LCD_Clr();
  DDRB= (1<<PB0) | (1<<PB5);
  64:  81 e2         ldi  r24, 0x21  ; 33
  66:  80 93 37 00   sts  0x0037, r24
  PORTB=1;
  6a:  81 e0         ldi  r24, 0x01  ; 1
  6c:  80 93 38 00   sts  0x0038, r24
  for (i=0;i<=30000;i++) ;
  70:  19 82         std  Y+1, r1  ; 0x01
  72:  1a 82         std  Y+2, r1  ; 0x02
  74:  89 81         ldd  r24, Y+1  ; 0x01
  76:  9a 81         ldd  r25, Y+2  ; 0x02
  78:  25 e7         ldi  r18, 0x75  ; 117
  7a:  81 33         cpi  r24, 0x31  ; 49
  7c:  92 07         cpc  r25, r18
  7e:  30 f4         brcc  .+12       ; 0x8c
  80:  89 81         ldd  r24, Y+1  ; 0x01
  82:  9a 81         ldd  r25, Y+2  ; 0x02
  84:  01 96         adiw  r24, 0x01  ; 1
  86:  89 83         std  Y+1, r24  ; 0x01
  88:  9a 83         std  Y+2, r25  ; 0x02
  8a:  f4 cf         rjmp  .-24       ; 0x74
  PORTB|= (1<<5);
  8c:  80 91 38 00   lds  r24, 0x0038
  90:  80 62         ori  r24, 0x20  ; 32
  92:  80 93 38 00   sts  0x0038, r24
  //LCD_Str("irgendwas");
  while (1) ;//asm volatile ("nop")
  96:  ff cf         rjmp  .-2        ; 0x96

von A.K. (Gast)


Lesenswert?

Mir scheint das Hex-File eigentlich ganz gut zum LSS zu passen.

von A.K. (Gast)


Angehängte Dateien:

Lesenswert?

"Da optimiert er einfach Sachen weg, obwohl sie nötig sind."

Da wäre ein konkretes Beispiel recht hilfreich - also der betreffende
C-Code und das falsche Resultat (.lst oder .lss). Im oben gezeigten
Code ist bis hin zum Hex-File alles ok.

"Hat von euch niemand solche Probleme?"

Ich selbst nicht und der allgemeinen Diskussionskultur hier nach zu
schliessen auch sonst niemand.

Anbei Disassembly vom Hex.

von A.K. (Gast)


Lesenswert?

PORTB=1;
  for (i=0;i<=30000;i++) ;
  PORTB|= (1<<5);

"So bleibt PortB auf 1 stehen"

Ich sehe auch keinen Grund, warum der Mega8 das nicht so halten sollte.
Die erste Zeile setzt B5 auf 1, die dritte Zeile ändert B5 von 1 auf 1.
Wenn B5 da auf 0 gehen soll, dann mit
  PORTB &= ~(1<<5);

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Nicht ganz richtig. Nach der ersten Zeile ist PORTB 1, nach der dritten
0x21.

von Giantics (Gast)


Lesenswert?

@A.K. Genau, der PortB müsste 0x21 sein, ist er aber definitiv nicht.
Ich hab mal das Hex mit dem AVR-Studio debugged und siehe da, auch hier
ist nur PB0 gesetzt nicht aber PB5!
Das deutet doch daraufhin, dass hex und lss doch nicht übereinstimmen,
oder bin ich blind? Habt ihr das hex mal ausprobiert? Oder könnte
jemand von euch mal die obigen Zeilen kompilieren und das hex hier
reinstellen, dann könnte ich sehen obs vielleicht doch an meinen
Einstellung liegt.

von churchi (Gast)


Lesenswert?

mit
PORTB=1; und
PORTB|= (1<<5);

ist es glaub ich kein Wunder wenn PB5 nicht gesetzt ist.
mit einem |= wird ein bit gelöscht.
mit &=~ wird es gesetzt

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Das ist falsch.

von churchi (Gast)


Lesenswert?

sry - klar - warum verwechsle ich das nur immer wieder?

von Fritz G. (fritzg)


Lesenswert?

Schau dir mal  Zeit und Datum der .lss und .hex Datei an. Sollte
eigentlich identisch sein.

von Giantics (Gast)


Lesenswert?

Habe die Ursache gefunden. Es liegt am Übertragungsprogramm:

Das wird reingeschickt:
0000: 12 C0 2B C0 2A C0 29 C0 28 C0 27 C0 26 C0 25 C0
0010: 24 C0 23 C0 22 C0 21 C0 20 C0 1F C0 1E C0 1D C0
0020: 1C C0 1B C0 1A C0 11 24 1F BE CF E5 D4 E0 DE BF
0030: CD BF 10 E0 A0 E6 B0 E0 E6 E9 F0 E0 02 C0 05 90
0040: 0D 92 A0 36 B1 07 D9 F7 10 E0 A0 E6 B0 E0 01 C0
0050: 1D 92 A0 36 B1 07 E1 F7 01 C0 D2 CF CD E5 D4 E0
0060: DE BF CD BF 81 E2 80 93 37 00 81 E0 80 93 38 00
0070: 19 82 1A 82 89 81 9A 81 8F 31 91 05 30 F4 89 81
0080: 9A 81 01 96 89 83 9A 83 F5 CF 80 91 38 00 80 62
0090: 80 93 38 00 FF CF

Und beim Auslesen kommt das zurück:
0000: 12 C0 2B C0 2A C0 29 C0 28 C0 27 C0 26 C0 25 C0
0010: 24 C0 23 C0 22 C0 21 C0 20 C0 1F C0 1E C0 1D C0
0020: 1C C0 1B C0 1A C0 11 24 1F BE CF E5 D4 E0 DE BF
0030: CD BF 10 E0 A0 E6 B0 E0 E6 E9 F0 E0 02 C0 05 90
0040: 0D 92 A0 36 B1 07 D9 F7 10 E0 A0 E6 B0 E0 01 C0
0050: 1D 92 A0 36 B1 07 E1 F7 01 C0 D2 CF CD E5 D4 E0
0060: DE BF CD BF 81 E2 80 93 37 00 81 E0 80 93 38 00
0070: 19 82 1A 82 89 81 9A 81 8F 31 91 05 30 F4 89 81
0080: 9A 81 01 96 89 83 9A 83 F5 CF 80 91 38 00 80 62
0090: 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

Da fehlen eindeutig die letzten 2 Befehle. Werde mal schauen wo da der
Fehler liegt.
Danke für eure Hilfe!

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Übrigens, nur nebenbei: das LSS-Listing ist ein Disassemblerlisting,
das von der Ausgabe her rückwärts generiert wird und dann anhand der
Debuginformationen mit den Codeschnipseln ,,annotiert'' wird.  Das
muss ganz zwangsläufig mit der ELF-Date übereinstimmen, und sofern
nicht jemand das Extrahieren der HEX-Datei aus dem ELF verpfuscht hat,
dann auch mit dieser.

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.