For-Loop wird nicht richtig ausgeführt

Gast #1920249
Lesenswert?
• ▲
▼
Hallo
Habe ein Problem,wenn ich eine einfaches C-Programm im AVR Studio 4.12 
neustes update mit GCC Unterstützung simulieren will. (Habe schon in 
Assembler programmiert jedoch wenig in anderen C-Compiler)

Umgebung: windows xp, Atmel stk 500, Atiny 13

Beispiel: For loop

int an;
....
 for(an=0;an<=10;an=an+1)
.....

da sollte doch "an" um eins hochgezählt werden bis 10.
 Aber im Debugger ist die Variable beim ersten For-Schritt schon bei 11 
(elf!) (auch Im Watch Fenster) angelangt und die Schleife wird natürlich 
sofort verlassen!
Habe andere Variablen probiert wie auch z.B. andere Start und Endwerte 
verwendet.
Kann mir das nicht vorstellen

Danke für einen Hinweis
Viele Grüsse
Gast #1920266
Lesenswert?
• ▲
▼
Kommt drauf an, was in der Schleife steht. GCC kann da auch eine ganze 
Schleife wegoptimieren wenn es den Schleifeninhalt auch ohne Schleife in 
einem Rutsch ausführen kann.

Mal als Beispiel:
1
unsigned int test(unsigned int n)
2
{
3
  unsigned int x;
4

5
  for (x = n; x < n + 20; x++)
6
    ;
7

8
  return x;
9
}

Mit eingeschalteter Optimierung (-O2) wird das auf x86 zu:
1
0000000000000000 <test>:
2
   0:  89 f8                  mov    %edi,%eax
3
   2:  83 c0 14               add    $0x14,%eax
4
   5:  0f 42 c7               cmovb  %edi,%eax
5
   8:  c3                     retq

Man sieht, da wird anstatt 20 mal zu inkrementieren direkt 20 addiert.


Wenn du alles wie im Quellcode ausgeführt sehen willst, musst du die 
Optimierungen ausschalten. Mit Optimierungen wird es auch auf andere 
Weise unübersichtlich im Debugger, z.B. kann die Reihenfolge der 
Anweisungen umgestellt werden.
Persönliche Seite #1921097
Lesenswert?
• ▲
▼
Hier mal ein kleines Beispielprogramm:
1
int fac (int x)
2
{
3
    if (x == 0)
4
        return 1;
5

6
    return x * fac (x-1);
7
}
8

9
int main()
10
{
11
    return fac (7);
12
}

avr-gcc 4.5.1 bzw. 4.6.0 mit -O2 macht aus main:
1
main:
2
  ldi r24,lo8(5040)
3
  ldi r25,hi8(5040)
4
  ret

d.h. der (end-)rekursive Aufruf ist komplett verschwunden. Es wird nur 
7! ins return-reg geladen. Da die Fakultätsfunktion hier nicht-statisch 
ist, muss sie ausimplementiert werden. Das sieht für einen ATmega8 und 
auf Größe optimiert so aus:
1
fac:
2
  ldi r18,lo8(1)
3
  ldi r19,hi8(1)
4
.L3:
5
  sbiw r24,0
6
  breq .L2
7
  movw r20,r18
8
  mul r20,r24
9
  movw r18,r0
10
  mul r20,r25
11
  add r19,r0
12
  mul r21,r24
13
  add r19,r0
14
  clr r1
15
  sbiw r24,1
16
  rjmp .L3
17
.L2:
18
  movw r24,r18
19
  ret

Nix mehr mit Rekursion. gcc erzeugt eine normale Schleife.

Ergo: Der Compiler transformiert den Code so, daß er die gleiche Wirkung 
hat, aber kann das auf ganz anderen Wegen erreichen, als man anhand der 
Quelle zu glauben geneigt ist. Entsprechend verwirrend kann das Debuggen 
solchen Codes ausfallen.

Antwort schreiben

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.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.