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
Das hört sich so an, als wenn die For-Schleife leer ist. Poste doch mal den gesamten Code.
Der Compiler hat gewisse Freiheiten, unsinnigen Code rauszuwerfen. Nennt sich Optimierung. Eine leere for-loop mit einer normalen Variablen ist sowas. Wenn du Wert drauf legst, dass jeder scheinbare Unsinn mit einer Variablen drin bleibt, dann mach sie volatile.
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.
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.