Forum: Compiler & IDEs Fehler in AVR-GCC 3.4.6


von Daniel S. (Gast)


Lesenswert?

Hallo Forum, ich habe verwende den AVR-GCC in der Version 3.4.6 
(Optimierungsgrad "S"). Das Programm wird für ein Atmega AT90CAN128 
compiliert. Ja, ich weiss, dass dies nicht mehr der aktuellste ist, er 
hat sich bei uns aber bewährt und wird daher weiterhin eingesetzt. Bis 
heute konnte ich alle Fehler noch auf irgendwelche "Schweinerein" im 
Quelltext zurückführen. Ab heute bin ich mir aber fast sicher, dass es 
sich hierbei um einen Fehler im Compiler handeln muss.

Problem:
Springt das Programm in die Unterfunktion "Handle_Device" und soll dann 
wieder zu seinem ursprünglichen Aufruf zurückkehren, ist die 
Rücksprungadresse beschädigt und der Prozessor startet quasi neu.
Nun liegt es nahe, dass durch ein Speicherüberlauf dieser innerhalb der 
Funktion beschädigt wurde. Aber so ist es definitiv nicht!

Funktion (stark vereinfacht):
1
unsigned int CRCcheck(TBuffer * aBuffer)
2
{
3
  unsigned char stream[PAYLOAD_LEN + 7];
4
  unsigned char i=0;
5
  unsigned int crc;
6
  stream[0] = 0x02;          // STX
7
  stream[1] = (unsigned char)(aBuffer->Cmd >> 8);   // CMD HIGH
8
  stream[2] = (unsigned char)(aBuffer->Cmd);     // CMD LOW
9
  stream[3] = aBuffer->Len;       // Length of payload
10
      
11
  for(i = 0; ((i < stream[3]) && (i < PAYLOAD_LEN)); i++)
12
  {
13
    stream[4+i] = aBuffer->Payload[i];  // payload
14
  }
15
  
16
  
17
  stream[4+i] = aBuffer->Seq;      // sequence number
18
  stream[5+i] = (unsigned char)(aBuffer->CRC >> 8);   // CRC HIGH
19
  stream[6+i] = (unsigned char)(aBuffer->CRC);     // CRC LOW
20
21
  crc = 0; // < zum test, gleicher fehler wie: CRC16(stream, i+7);
22
23
  return crc;
24
25
}
26
27
unsigned int Handle_Device(TDevice * aDevice)
28
{
29
   unsigned int retval = 0x0000;
30
   // ...
31
   id = 0;
32
   retval = CRCcheck(&aDevice->Buffer[id]);
33
   // ...
34
   return retval;
35
}

Problembehebung ("work around")
- Anderen Optimierungsgrad
- Statt "return retval;" > "return 0;"
- Die Funktion CRCcheck kürzen (egal wie)
Wenn ich einen dieser Punkte ausführe, funktioniert alles wie gewollt.

Um nun dem Fehler zu finden, habe ich mir den Assembler-Quelltext 
angeschaut. Und es gibt einen entscheidenden Unterschied zwischen den 
Fällen, dass es funktioniert und dass es nicht funktioniert. Ich habe 
die entscheidenden Stellen mal rauskopiert:

Assembler FUNKTIONIERT NICHT!!! (Register sichern):
1
+0000115F:   922F        PUSH    R2               Push register on stack
2
+00001160:   923F        PUSH    R3               Push register on stack
3
+00001161:   924F        PUSH    R4               Push register on stack
4
+00001162:   925F        PUSH    R5               Push register on stack
5
+00001163:   926F        PUSH    R6               Push register on stack
6
+00001164:   927F        PUSH    R7               Push register on stack
7
+00001165:   929F        PUSH    R9               Push register on stack
8
+00001166:   92AF        PUSH    R10              Push register on stack
9
+00001167:   92BF        PUSH    R11              Push register on stack
10
+00001168:   92CF        PUSH    R12              Push register on stack
11
+00001169:   92DF        PUSH    R13              Push register on stack
12
+0000116A:   92EF        PUSH    R14              Push register on stack
13
+0000116B:   92FF        PUSH    R15              Push register on stack
14
+0000116C:   930F        PUSH    R16              Push register on stack
15
+0000116D:   931F        PUSH    R17              Push register on stack
16
+0000116E:   93CF        PUSH    R28              Push register on stack
17
+0000116F:   93DF        PUSH    R29              Push register on stack
18
+00001170:   B7CD        IN      R28,0x3D         In from I/O location
19
+00001171:   B7DE        IN      R29,0x3E         In from I/O location
20
+00001172:   9724        SBIW    R28,0x04         Subtract immediate from word
21
+00001173:   B60F        IN      R0,0x3F          In from I/O location
22
+00001174:   94F8        CLI                      Global Interrupt Disable
23
+00001175:   BFDE        OUT     0x3E,R29         Out to I/O location
24
+00001176:   BE0F        OUT     0x3F,R0          Out to I/O location
25
+00001177:   BFCD        OUT     0x3D,R28         Out to I/O location
26
+00001178:   018C        MOVW    R16,R24          Copy register pair
27
+00001179:   012A        MOVW    R4,R20           Copy register pair
28
+0000117A:   013B        MOVW    R6,R22           Copy register pair

Assembler FUNKTIONIERT NICHT!!! (Register wieder aus dem Stack holen):
1
+0000127F:   01C5        MOVW    R24,R10          Copy register pair
2
+00001280:   9624        ADIW    R28,0x04         Add immediate to word
3
+00001281:   B60F        IN      R0,0x3F          In from I/O location
4
+00001282:   94F8        CLI                      Global Interrupt Disable
5
+00001283:   BFDE        OUT     0x3E,R29         Out to I/O location
6
+00001284:   BE0F        OUT     0x3F,R0          Out to I/O location
7
+00001285:   BFCD        OUT     0x3D,R28         Out to I/O location
8
+00001286:   91DF        POP     R29              Pop register from stack
9
+00001287:   91CF        POP     R28              Pop register from stack
10
+00001288:   911F        POP     R17              Pop register from stack
11
+00001289:   910F        POP     R16              Pop register from stack
12
+0000128A:   90FF        POP     R15              Pop register from stack
13
+0000128B:   90EF        POP     R14              Pop register from stack
14
+0000128C:   90DF        POP     R13              Pop register from stack
15
+0000128D:   90CF        POP     R12              Pop register from stack
16
+0000128E:   90BF        POP     R11              Pop register from stack
17
+0000128F:   90AF        POP     R10              Pop register from stack
18
+00001290:   909F        POP     R9               Pop register from stack
19
+00001291:   907F        POP     R7               Pop register from stack
20
+00001292:   906F        POP     R6               Pop register from stack
21
+00001293:   905F        POP     R5               Pop register from stack
22
+00001294:   904F        POP     R4               Pop register from stack
23
+00001295:   903F        POP     R3               Pop register from stack
24
+00001296:   902F        POP     R2               Pop register from stack
25
+00001297:   9508        RET                      Subroutine return

Man beachte, 00001170 bis 00001172 und 00001281 bis 00001285. Hier wird 
der Stack "manipuliert" und genau dieser Part ist im Assembler Quelltext 
nicht vorhanden, wenn ich eines der "Work-Around" nutze.
Außerdem passiert folgendes: Nach meiner Meinung nutzt der Compiler die 
Register R28 und R29 zum sichern des Stackpointers. Soweit so gut, 
jedoch verwendet er diese Register auch noch für andere Dinge innerhalb 
der Funktion.

Und genau hier liegt das Problem! Nachdem die Funktion beendet werden 
soll, wird das Registerpaar genommen und zurück auf den Stackpointer 
geschrieben. Da sich diese Werte aber verändert haben, funktioniert das 
ganze nicht mehr.
Work-Arounds habe ich viele gefunden (ganz unterschiedlicher Art). 
Selbst ein paar zusätzliche Debug-Ausgaben führten dazu, dass das 
genannte Registerpaar innerhalb der Funktion nicht mehr angefasst wird.

ABER WARUM MACHT DER COMPILER SOWAS?!?!

Vielen Dank für eure Hilfe!

Daniel

von (prx) A. K. (prx)


Lesenswert?

Zunächst einmal ist das der seit jeher übliche Prolog/Epilog vom 
avr-gcc. R28/R29 bilden den Framepointer, den GCC aber nur verwendet 
wenn er ihn benötigt oder man die Optimierung abschaltet. Er benötigt 
ihn genau dann, wenn er lokale Daten in den Speicher und nicht in 
Register legt, wegen Anzahl, Adressierung oder weil wie hier ein Array.

Mehr lässt sich schlecht sagen, da du genau den Teil, der dir angeblich 
diesen Framepointer zerlegt, weggelassen hast.

Jedenfalls ist der präsentierte Code völlig ok.

von Peter D. (peda)


Lesenswert?

Die von Dir beklagten Zeilen sind o.k., sie legen 4 Byte Variablen auf 
dem Stack an.

Dein Problem ist, daß Du im Interrupt eine Unterfunktion aufrufst.
Der AVR-GCC macht aber keine Registeranalyse, d.h. er geht immer davon 
aus, daß jede Funktion alle Scratchpadregister zerstört.
Also sicher er unnötig nen Haufen Register und legt zusätzlich eigene 
Variablen auf dem Stack an.
Warscheinlich läuft dadurch Dein Stack über und zerschießt Dir 
Variablen.

Unterfunktionen in Interrupts sind als ober-BÄH.


Peter

von Daniel S. (Gast)


Lesenswert?

Die vermutung von A.K. ist naheliegend, weshalb ich die erweiterte 
Bedingung in die For-Schleife mit aufenommen habe.

Das Auskommentieren dieser Zeile bringt aber auch keinen Erfolg!

Hier die Stelle, an der mir das Register R28 versaut wird:
1
598:        if (aDevice->State == DEVICESTATE_Error)
2
+0000117D:   01EC        MOVW    R28,R24          Copy register pair
3
+0000117E:   8188        LDD     R24,Y+0          Load indirect with displacement
4
+0000117F:   8199        LDD     R25,Y+1          Load indirect with displacement
5
+00001180:   308A        CPI     R24,0x0A         Compare with immediate
6
+00001181:   0591        CPC     R25,R1           Compare with carry
7
+00001182:   F461        BRNE    PC+0x0D          Branch if not equal
8
601:          retval = DEVICEMERROR_GENERALDEVICEERROR;
9
+00001183:   2CA1        MOV     R10,R1           Copy register
10
+00001184:   E8E0        LDI     R30,0x80         Load immediate
11
+00001185:   2EBE        MOV     R11,R30          Copy register
12
+00001186:   C0F8        RJMP    PC+0x00F9        Relative jump

von Daniel S. (Gast)


Lesenswert?

@Peter:
Diese Funktionen werde nicht in einem Interrupt aufgerufen. Zum Test 
habe ich gänzlich alle Interrupts deaktivert.

von (prx) A. K. (prx)


Lesenswert?

Bist du eigentlich sicher, dass dieser Prolog zum der richtige ist? In 
einem Punkt muss ich mich nämlich korrigieren: er ist zwar in sich 
korrekt, passt aber nicht zum gezeigten Quellcode. PAYLOAD_LEN+7 wird 
kaum 4 sein, es sei denn PAYLOAD_LEN ist -3. Denn die 4 Bytes auf dem 
Stack sind klar zu wenig für stream[].

Bring mal ein compilierfähiges Beispiel.

von Peter D. (peda)


Lesenswert?

Daniel S. schrieb:
> @Peter:
> Diese Funktionen werde nicht in einem Interrupt aufgerufen.

Stimmt, die PUSH/POP Orgie hat mich zu der Annahme verleitet, es wäre 
ein Interrupt.

Deine Funktion benutzt aber nen ziemlichen Haufen Variablen, die der 
Compiler nicht optimieren kann. Das bewirkt dann die PUSH/POP Orgie und 
Stackvariablen.

Irgendwas scheint darin zu sein, was den Compiler total die Kontrolle 
verlieren läßt. Vielleicht kannst Du die Funktion etwas übersichtlicher 
schreiben, damit er besser optimieren kann.
Ich glaube eigentlich nicht, daß wirklich soviel Variablen gleichzeitg 
benötigt werden.

Notfalls machen Variablen statisch. Sie belegen dann zwar ständig SRAM, 
ist aber allemal besser als Stackvariablen. Der Compiler kann sie dann 
direkt zugreifen, statt einen Pointer zu belegen.


Peter

von Peter D. (peda)


Lesenswert?

A. K. schrieb:
> Bist du eigentlich sicher, dass dieser Prolog zum der richtige ist? In
> einem Punkt muss ich mich nämlich korrigieren: er ist zwar in sich
> korrekt, passt aber nicht zum gezeigten Quellcode. PAYLOAD_LEN+7 wird
> kaum 4 sein, es sei denn PAYLOAD_LEN ist -3. Denn die 4 Bytes auf dem
> Stack sind klar zu wenig für stream[].


Doch, das ist dem AVR-GCC zuzutrauen.
Er sieht, daß nur stream[3] gelesen wird und optimiert die anderen 
einfach weg.

Aber wofür die vielen Register benötigt werden, das fehlt in dem 
Quelltext.


Peter

von (prx) A. K. (prx)


Lesenswert?

Die Nummer mit R28:R29 steckt in Code, der oben im präsentierten Code 
garnicht drinsteht. Drum frage ich ja nach was compilierbarem, dieses 
Fragment reicht nicht.

von Daniel S. (Gast)


Lesenswert?

Der gezeigte Assembler-Text ist für die Funktion
1
unsigned int Handle_Device(TDevice * aDevice)
. Diese Funktion ist schon recht umfangreich, weshalb das sichern aller 
Register etc. schon nachvollziehbar ist.

Was ebenfalls abhilfe schafft:
1
unsigned int retval = 0x0000;

mit einem volatile versehen:
1
volatile unsigned int retval = 0x0000;

von Daniel S. (Gast)


Lesenswert?

Ok, leider darf ich die Funktion so komplett nicht posten, da es sich 
dabei teilweise um "Firmeneigentum" handelt.

Ich werde die Funktion jetzt mal umschreiben, so dass der Fehler noch 
immer auftritt, diese aber überschaubar und compilierbar wird.

von Peter D. (peda)


Lesenswert?

Daniel S. schrieb:
> Hier die Stelle, an der mir das Register R28 versaut wird:
>
>
1
> 598:        if (aDevice->State == DEVICESTATE_Error)
2
> +0000117D:   01EC        MOVW    R28,R24          Copy register pair
3
>

Wenn irgendwo früher ein "MOVW R24,R28", ist das aber korrekt.


Peter

von Daniel S. (Gast)


Lesenswert?

Hier mal der komplette ASM Bereich zwischen Anfang des Funktionsaufrufs 
und dem "zerschiessen":
1
+0000128D:   922F        PUSH    R2               Push register on stack
2
+0000128E:   923F        PUSH    R3               Push register on stack
3
+0000128F:   924F        PUSH    R4               Push register on stack
4
+00001290:   925F        PUSH    R5               Push register on stack
5
+00001291:   926F        PUSH    R6               Push register on stack
6
+00001292:   927F        PUSH    R7               Push register on stack
7
+00001293:   928F        PUSH    R8               Push register on stack
8
+00001294:   929F        PUSH    R9               Push register on stack
9
+00001295:   92BF        PUSH    R11              Push register on stack
10
+00001296:   92CF        PUSH    R12              Push register on stack
11
+00001297:   92DF        PUSH    R13              Push register on stack
12
+00001298:   92EF        PUSH    R14              Push register on stack
13
+00001299:   92FF        PUSH    R15              Push register on stack
14
+0000129A:   930F        PUSH    R16              Push register on stack
15
+0000129B:   931F        PUSH    R17              Push register on stack
16
+0000129C:   93CF        PUSH    R28              Push register on stack
17
+0000129D:   93DF        PUSH    R29              Push register on stack
18
+0000129E:   B7CD        IN      R28,0x3D         In from I/O location
19
+0000129F:   B7DE        IN      R29,0x3E         In from I/O location
20
+000012A0:   9724        SBIW    R28,0x04         Subtract immediate from word
21
+000012A1:   B60F        IN      R0,0x3F          In from I/O location
22
+000012A2:   94F8        CLI                      Global Interrupt Disable
23
+000012A3:   BFDE        OUT     0x3E,R29         Out to I/O location
24
+000012A4:   BE0F        OUT     0x3F,R0          Out to I/O location
25
+000012A5:   BFCD        OUT     0x3D,R28         Out to I/O location
26
+000012A6:   018C        MOVW    R16,R24          Copy register pair
27
+000012A7:   013A        MOVW    R6,R20           Copy register pair
28
+000012A8:   014B        MOVW    R8,R22           Copy register pair
29
727:        unsigned int result = ERROR_NO;
30
+000012A9:   2422        CLR     R2               Clear Register
31
+000012AA:   2433        CLR     R3               Clear Register
32
729:        if (aDevice->State > STATE_Uninitialized)
33
+000012AB:   01EC        MOVW    R28,R24          Copy register pair
34
+000012AC:   8188        LDD     R24,Y+0          Load indirect with displacement
35
+000012AD:   8199        LDD     R25,Y+1          Load indirect with displacement
36
+000012AE:   2B89        OR      R24,R25          Logical OR
37
+000012AF:   F409        BRNE    PC+0x02          Branch if not equal
38
+000012B0:   C099        RJMP    PC+0x009A        Relative jump
39
+000012B1:   E022        LDI     R18,0x02         Load immediate
40
+000012B2:   2EE2        MOV     R14,R18          Copy register
41
+000012B3:   2CF1        MOV     R15,R1           Copy register
42
+000012B4:   0EE0        ADD     R14,R16          Add without carry
43
+000012B5:   1EF1        ADC     R15,R17          Add with carry
44
+000012B6:   0167        MOVW    R12,R14          Copy register pair
45
+000012B7:   831A        STD     Y+2,R17          Store indirect with displacement
46
+000012B8:   8309        STD     Y+1,R16          Store indirect with displacement
47
+000012B9:   E095        LDI     R25,0x05         Load immediate
48
+000012BA:   2EB9        MOV     R11,R25          Copy register

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


Lesenswert?

Kann natürlich gut sein, dass du hier wirklich über einen Bug
gestolpert bist.  Das könnte man nur sagen, wenn du uns den
Quelltext zum Selbstcompilieren gibst (kannst ihn ja anonymisieren).

Aber wenn dem so wäre: Pech gehabt, diese alte Compilerversion pflegt
halt auch niemand mehr.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Daniel S. schrieb:
> Ok, leider darf ich die Funktion so komplett nicht posten, da es sich
> dabei teilweise um "Firmeneigentum" handelt.
>
> Ich werde die Funktion jetzt mal umschreiben, so dass der Fehler noch
> immer auftritt, diese aber überschaubar und compilierbar wird.

Am besten erstellst du ein Precompilat mit -save-temps (und ohne -pipe). 
Da sind schon mal alle include-Abhängigkeiten, Defines und -DXXX 
aufgelöst. Dann wirfst du unbeteiligte Funktionen raus, d.h. solche, die 
nicht im Call-Graph des Problems auftauchen. Ebenso wirfst du ungenutzte 
Typedefs etc. raus. Schliesslich, wenn du willst, kannst noch nen 
C-Obfuscator drüberlaufen lassen (funktionieren aber nicht alle mit 
Inline-Assembler).

Das ganze muss nicht linkfähig sein; es genügt, wenn der fehlerhafte 
Code mit -S (assemble only) erzeugt wird.

Das Ganze sieht wirklich so aus, als ob da ISR-Prolog und Epiloge 
erzeugt werden für ne normale Funktion.

Veränderst du das ABI indem du Register fixierst? Verwendest du globale 
oder lokale Registervariablen?

Johann

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Daniel S. schrieb:

> Funktion (stark vereinfacht):
> [...]
>
> ABER WARUM MACHT DER COMPILER SOWAS?!?!
>
> Vielen Dank für eure Hilfe!

Der Compiler macht was komplett anderes. Ich hab mir mal die Mühe 
gemacht dein Code in was übersetzbares zu wandeln.
1
#include <stdint.h>
2
3
#define PAYLOAD_LEN 16
4
5
typedef struct
6
{
7
    uint8_t Cmd;
8
    uint8_t Len;
9
    uint16_t CRC;
10
    uint8_t Seq;
11
    uint8_t Payload[PAYLOAD_LEN];
12
} TBuffer;
13
14
typedef struct
15
{
16
    TBuffer Buffer[10];
17
} TDevice;
18
19
unsigned int CRCcheck(TBuffer * aBuffer)
20
{
21
  unsigned char stream[PAYLOAD_LEN + 7];
22
  unsigned char i=0;
23
  unsigned int crc;
24
  stream[0] = 0x02;          // STX
25
  stream[1] = (unsigned char)(aBuffer->Cmd >> 8);   // CMD HIGH
26
  stream[2] = (unsigned char)(aBuffer->Cmd);     // CMD LOW
27
  stream[3] = aBuffer->Len;       // Length of payload
28
      
29
  for(i = 0; ((i < stream[3]) && (i < PAYLOAD_LEN)); i++)
30
  {
31
    stream[4+i] = aBuffer->Payload[i];  // payload
32
  }
33
  
34
  
35
  stream[4+i] = aBuffer->Seq;      // sequence number
36
  stream[5+i] = (unsigned char)(aBuffer->CRC >> 8);   // CRC HIGH
37
  stream[6+i] = (unsigned char)(aBuffer->CRC);     // CRC LOW
38
39
  crc = 0; // < zum test, gleicher fehler wie: CRC16(stream, i+7);
40
41
  return crc;
42
43
}
44
45
unsigned int Handle_Device (TDevice * aDevice, uint8_t id)
46
{
47
   unsigned int retval = 0x0000;
48
49
   retval = CRCcheck (&aDevice->Buffer[id]);
50
51
   return retval;
52
}

Der erzeugt Code ist:
1
  .file  "foo.c"
2
  .arch at90can128
3
__SREG__ = 0x3f
4
__SP_H__ = 0x3e
5
__SP_L__ = 0x3d
6
__tmp_reg__ = 0
7
__zero_reg__ = 1
8
  .global __do_copy_data
9
  .global __do_clear_bss
10
 ;  GNU C version 3.4.6 (avr)
11
 ;   compiled by GNU C version 3.4.2 (mingw-special).
12
 ;  GGC heuristics: --param ggc-min-expand=47 --param ggc-min-heapsize=32702
13
 ;  options passed:  -iprefix -mmcu=at90can128 -auxbase -Os -W -Wall
14
 ;  -fverbose-asm
15
 ;  options enabled:  -feliminate-unused-debug-types -fdefer-pop
16
 ;  -fomit-frame-pointer -foptimize-sibling-calls -funit-at-a-time
17
 ;  -fcse-follow-jumps -fcse-skip-blocks -fexpensive-optimizations
18
 ;  -fthread-jumps -fstrength-reduce -fpeephole -fforce-mem -ffunction-cse
19
 ;  -fkeep-static-consts -fcaller-saves -freg-struct-return -fgcse
20
 ;  -fgcse-lm -fgcse-sm -fgcse-las -floop-optimize -fcrossjumping
21
 ;  -fif-conversion -fif-conversion2 -frerun-cse-after-loop
22
 ;  -frerun-loop-opt -fdelete-null-pointer-checks -fsched-interblock
23
 ;  -fsched-spec -fsched-stalled-insns -fsched-stalled-insns-dep
24
 ;  -fbranch-count-reg -freorder-functions -fcprop-registers -fcommon
25
 ;  -fverbose-asm -fregmove -foptimize-register-move -fargument-alias
26
 ;  -fstrict-aliasing -fmerge-constants -fzero-initialized-in-bss -fident
27
 ;  -fpeephole2 -fguess-branch-probability -fmath-errno -ftrapping-math
28
 ;  -minit-stack=__stack -mmcu=at90can128
29
30
  .text
31
.global  CRCcheck
32
  .type  CRCcheck, @function
33
CRCcheck:
34
/* prologue: frame size=23 */
35
  push r28
36
  push r29
37
  in r28,__SP_L__
38
  in r29,__SP_H__
39
  sbiw r28,23
40
  in __tmp_reg__,__SREG__
41
  cli
42
  out __SP_H__,r29
43
  out __SREG__,__tmp_reg__
44
  out __SP_L__,r28
45
/* prologue end (size=10) */
46
  movw r18,r24   ;  aBuffer, aBuffer
47
  ldi r25,lo8(0)   ;  i,
48
  ldi r24,lo8(2)   ;  tmp45,
49
  std Y+1,r24   ;  stream, tmp45
50
  movw r26,r18   ; , aBuffer
51
  ld r24,X   ;  <variable>.Cmd, <variable>.Cmd
52
  std Y+2,r25   ;  stream,
53
  std Y+3,r24   ;  stream, <variable>.Cmd
54
  movw r30,r18   ; , aBuffer
55
  ldd r24,Z+1   ;  <variable>.Len, <variable>.Len
56
  std Y+4,r24   ;  stream, <variable>.Len
57
  cp r25,r24   ;  i, <variable>.Len
58
  brsh .L3   ; ,
59
  movw r20,r28   ;  tmp75,
60
  subi r20,lo8(-(5))   ;  tmp75,
61
  sbci r21,hi8(-(5))   ;  tmp75,
62
  adiw r26,5   ;  tmp76,
63
.L5:
64
  ld r24,X+   ;  tmp58, <variable>.Payload
65
  movw r30,r20   ; , tmp75
66
  st Z+,r24   ;  stream, tmp58
67
  movw r20,r30   ;  tmp75,
68
  subi r25,lo8(-(1))   ;  i,
69
  ldd r24,Y+4   ;  stream, stream
70
  cp r25,r24   ;  i, stream
71
  brsh .L3   ; ,
72
  cpi r25,lo8(16)   ;  i,
73
  brlo .L5   ; ,
74
.L3:
75
  mov r20,r25   ;  i, i
76
  clr r21   ;  i
77
  movw r26,r28   ;  tmp61,
78
  add r26,r20   ;  tmp61, i
79
  adc r27,r21   ;  tmp61, i
80
  movw r30,r18   ; , aBuffer
81
  ldd r24,Z+4   ;  <variable>.Seq, <variable>.Seq
82
  movw r30,r26   ; , tmp61
83
  std Z+5,r24   ;  stream, <variable>.Seq
84
  movw r30,r18   ; , aBuffer
85
  ldd r24,Z+2   ;  <variable>.CRC, <variable>.CRC
86
  ldd r25,Z+3   ;  <variable>.CRC, <variable>.CRC
87
  mov r24,r25   ;  tmp67, <variable>.CRC
88
  clr r25   ;  tmp67
89
  movw r30,r26   ; , tmp65
90
  std Z+6,r24   ;  stream, tmp67
91
  add r20,r28   ;  i,
92
  adc r21,r29   ;  i,
93
  movw r30,r18   ; , aBuffer
94
  ldd r24,Z+2   ;  <variable>.CRC, <variable>.CRC
95
  movw r30,r20   ; , i
96
  std Z+7,r24   ;  stream, <variable>.CRC
97
  ldi r24,lo8(0)   ;  <result>,
98
  ldi r25,hi8(0)   ;  <result>,
99
/* epilogue: frame size=23 */
100
  adiw r28,23
101
  in __tmp_reg__,__SREG__
102
  cli
103
  out __SP_H__,r29
104
  out __SREG__,__tmp_reg__
105
  out __SP_L__,r28
106
  pop r29
107
  pop r28
108
  ret
109
/* epilogue end (size=9) */
110
/* function CRCcheck size 70 (51) */
111
  .size  CRCcheck, .-CRCcheck
112
.global  Handle_Device
113
  .type  Handle_Device, @function
114
Handle_Device:
115
/* prologue: frame size=0 */
116
/* prologue end (size=0) */
117
  ldi r18,lo8(21)   ;  tmp46,
118
  mul r22,r18   ;  id, tmp46
119
  movw r18,r0   ;  tmp45
120
  clr r1
121
  add r24,r18   ; , tmp45
122
  adc r25,r19   ; , tmp45
123
  call CRCcheck   ; 
124
/* epilogue: frame size=0 */
125
  ret
126
/* epilogue end (size=1) */
127
/* function Handle_Device size 9 (8) */
128
  .size  Handle_Device, .-Handle_Device
129
/* File "foo.c": code   79 = 0x004f (  59), prologues  10, epilogues  10 */

Fazit

Das ist komplett anders als das asm-Zeug, das du oben gepostet hast.

Wenn du wirklich ernsthaft Interesse daran hast, Hilfe bei einem 
(angeblichen) gcc-Bug zu bekommen, dann gibt es hier einige Leute, die 
Ahnung haben und dir weiterhelfen können, die sich aber möglicherweise 
zeimlich veräppelt fühlen, wenn du Märchen-Code postest so wie oben.

Das konkrete Verhalten eines agressiv optimierenden Compilers wie GCC 
ist ohne die Quelle nicht nachvollziehbar!

Nutzloser Code ist zB
-- Code der ... enthält (ausser natürlich in varargs-Funktionen)
-- Code, der externe Header verwendet
-- Unbekannte Optionen
-- etc.

Also noch mal von vorne: Ohne konkreten Testfall kann dir hier niemand 
helfen mit deinem Problem. Was die Erstellung eines Testfalles angeht 
sei dir
   http://gcc.gnu.org/bugs.html#need
ans Herz gelegt. Du verdienst deine Brötchen mit dem Zeug, also sollte 
das Englisch dort keine Hürde sein. Falls doch, steht es schon in
   Beitrag "Re: Fehler in AVR-GCC 3.4.6"
bzw. du kannst auch nachfragen, wenn da was unklar ist oder warum ... = 
Märchenstunde ist ;-)

Johann

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.