www.mikrocontroller.net

Forum: Compiler & IDEs Fehler in AVR-GCC 3.4.6


Autor: Daniel S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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):
unsigned int CRCcheck(TBuffer * aBuffer)
{
  unsigned char stream[PAYLOAD_LEN + 7];
  unsigned char i=0;
  unsigned int crc;
  stream[0] = 0x02;          // STX
  stream[1] = (unsigned char)(aBuffer->Cmd >> 8);   // CMD HIGH
  stream[2] = (unsigned char)(aBuffer->Cmd);     // CMD LOW
  stream[3] = aBuffer->Len;       // Length of payload
      
  for(i = 0; ((i < stream[3]) && (i < PAYLOAD_LEN)); i++)
  {
    stream[4+i] = aBuffer->Payload[i];  // payload
  }
  
  
  stream[4+i] = aBuffer->Seq;      // sequence number
  stream[5+i] = (unsigned char)(aBuffer->CRC >> 8);   // CRC HIGH
  stream[6+i] = (unsigned char)(aBuffer->CRC);     // CRC LOW

  crc = 0; // < zum test, gleicher fehler wie: CRC16(stream, i+7);

  return crc;

}

unsigned int Handle_Device(TDevice * aDevice)
{
   unsigned int retval = 0x0000;
   // ...
   id = 0;
   retval = CRCcheck(&aDevice->Buffer[id]);
   // ...
   return retval;
}

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):
+0000115F:   922F        PUSH    R2               Push register on stack
+00001160:   923F        PUSH    R3               Push register on stack
+00001161:   924F        PUSH    R4               Push register on stack
+00001162:   925F        PUSH    R5               Push register on stack
+00001163:   926F        PUSH    R6               Push register on stack
+00001164:   927F        PUSH    R7               Push register on stack
+00001165:   929F        PUSH    R9               Push register on stack
+00001166:   92AF        PUSH    R10              Push register on stack
+00001167:   92BF        PUSH    R11              Push register on stack
+00001168:   92CF        PUSH    R12              Push register on stack
+00001169:   92DF        PUSH    R13              Push register on stack
+0000116A:   92EF        PUSH    R14              Push register on stack
+0000116B:   92FF        PUSH    R15              Push register on stack
+0000116C:   930F        PUSH    R16              Push register on stack
+0000116D:   931F        PUSH    R17              Push register on stack
+0000116E:   93CF        PUSH    R28              Push register on stack
+0000116F:   93DF        PUSH    R29              Push register on stack
+00001170:   B7CD        IN      R28,0x3D         In from I/O location
+00001171:   B7DE        IN      R29,0x3E         In from I/O location
+00001172:   9724        SBIW    R28,0x04         Subtract immediate from word
+00001173:   B60F        IN      R0,0x3F          In from I/O location
+00001174:   94F8        CLI                      Global Interrupt Disable
+00001175:   BFDE        OUT     0x3E,R29         Out to I/O location
+00001176:   BE0F        OUT     0x3F,R0          Out to I/O location
+00001177:   BFCD        OUT     0x3D,R28         Out to I/O location
+00001178:   018C        MOVW    R16,R24          Copy register pair
+00001179:   012A        MOVW    R4,R20           Copy register pair
+0000117A:   013B        MOVW    R6,R22           Copy register pair

Assembler FUNKTIONIERT NICHT!!! (Register wieder aus dem Stack holen):
+0000127F:   01C5        MOVW    R24,R10          Copy register pair
+00001280:   9624        ADIW    R28,0x04         Add immediate to word
+00001281:   B60F        IN      R0,0x3F          In from I/O location
+00001282:   94F8        CLI                      Global Interrupt Disable
+00001283:   BFDE        OUT     0x3E,R29         Out to I/O location
+00001284:   BE0F        OUT     0x3F,R0          Out to I/O location
+00001285:   BFCD        OUT     0x3D,R28         Out to I/O location
+00001286:   91DF        POP     R29              Pop register from stack
+00001287:   91CF        POP     R28              Pop register from stack
+00001288:   911F        POP     R17              Pop register from stack
+00001289:   910F        POP     R16              Pop register from stack
+0000128A:   90FF        POP     R15              Pop register from stack
+0000128B:   90EF        POP     R14              Pop register from stack
+0000128C:   90DF        POP     R13              Pop register from stack
+0000128D:   90CF        POP     R12              Pop register from stack
+0000128E:   90BF        POP     R11              Pop register from stack
+0000128F:   90AF        POP     R10              Pop register from stack
+00001290:   909F        POP     R9               Pop register from stack
+00001291:   907F        POP     R7               Pop register from stack
+00001292:   906F        POP     R6               Pop register from stack
+00001293:   905F        POP     R5               Pop register from stack
+00001294:   904F        POP     R4               Pop register from stack
+00001295:   903F        POP     R3               Pop register from stack
+00001296:   902F        POP     R2               Pop register from stack
+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

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Daniel S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
598:        if (aDevice->State == DEVICESTATE_Error)
+0000117D:   01EC        MOVW    R28,R24          Copy register pair
+0000117E:   8188        LDD     R24,Y+0          Load indirect with displacement
+0000117F:   8199        LDD     R25,Y+1          Load indirect with displacement
+00001180:   308A        CPI     R24,0x0A         Compare with immediate
+00001181:   0591        CPC     R25,R1           Compare with carry
+00001182:   F461        BRNE    PC+0x0D          Branch if not equal
601:          retval = DEVICEMERROR_GENERALDEVICEERROR;
+00001183:   2CA1        MOV     R10,R1           Copy register
+00001184:   E8E0        LDI     R30,0x80         Load immediate
+00001185:   2EBE        MOV     R11,R30          Copy register
+00001186:   C0F8        RJMP    PC+0x00F9        Relative jump

Autor: Daniel S. (Gast)
Datum:

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

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Daniel S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der gezeigte Assembler-Text ist für die Funktion
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:
unsigned int retval = 0x0000;

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

Autor: Daniel S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Peter Dannegger (peda)
Datum:

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

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


Peter

Autor: Daniel S. (Gast)
Datum:

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

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.
#include <stdint.h>

#define PAYLOAD_LEN 16

typedef struct
{
    uint8_t Cmd;
    uint8_t Len;
    uint16_t CRC;
    uint8_t Seq;
    uint8_t Payload[PAYLOAD_LEN];
} TBuffer;

typedef struct
{
    TBuffer Buffer[10];
} TDevice;

unsigned int CRCcheck(TBuffer * aBuffer)
{
  unsigned char stream[PAYLOAD_LEN + 7];
  unsigned char i=0;
  unsigned int crc;
  stream[0] = 0x02;          // STX
  stream[1] = (unsigned char)(aBuffer->Cmd >> 8);   // CMD HIGH
  stream[2] = (unsigned char)(aBuffer->Cmd);     // CMD LOW
  stream[3] = aBuffer->Len;       // Length of payload
      
  for(i = 0; ((i < stream[3]) && (i < PAYLOAD_LEN)); i++)
  {
    stream[4+i] = aBuffer->Payload[i];  // payload
  }
  
  
  stream[4+i] = aBuffer->Seq;      // sequence number
  stream[5+i] = (unsigned char)(aBuffer->CRC >> 8);   // CRC HIGH
  stream[6+i] = (unsigned char)(aBuffer->CRC);     // CRC LOW

  crc = 0; // < zum test, gleicher fehler wie: CRC16(stream, i+7);

  return crc;

}

unsigned int Handle_Device (TDevice * aDevice, uint8_t id)
{
   unsigned int retval = 0x0000;

   retval = CRCcheck (&aDevice->Buffer[id]);

   return retval;
}

Der erzeugt Code ist:
  .file  "foo.c"
  .arch at90can128
__SREG__ = 0x3f
__SP_H__ = 0x3e
__SP_L__ = 0x3d
__tmp_reg__ = 0
__zero_reg__ = 1
  .global __do_copy_data
  .global __do_clear_bss
 ;  GNU C version 3.4.6 (avr)
 ;   compiled by GNU C version 3.4.2 (mingw-special).
 ;  GGC heuristics: --param ggc-min-expand=47 --param ggc-min-heapsize=32702
 ;  options passed:  -iprefix -mmcu=at90can128 -auxbase -Os -W -Wall
 ;  -fverbose-asm
 ;  options enabled:  -feliminate-unused-debug-types -fdefer-pop
 ;  -fomit-frame-pointer -foptimize-sibling-calls -funit-at-a-time
 ;  -fcse-follow-jumps -fcse-skip-blocks -fexpensive-optimizations
 ;  -fthread-jumps -fstrength-reduce -fpeephole -fforce-mem -ffunction-cse
 ;  -fkeep-static-consts -fcaller-saves -freg-struct-return -fgcse
 ;  -fgcse-lm -fgcse-sm -fgcse-las -floop-optimize -fcrossjumping
 ;  -fif-conversion -fif-conversion2 -frerun-cse-after-loop
 ;  -frerun-loop-opt -fdelete-null-pointer-checks -fsched-interblock
 ;  -fsched-spec -fsched-stalled-insns -fsched-stalled-insns-dep
 ;  -fbranch-count-reg -freorder-functions -fcprop-registers -fcommon
 ;  -fverbose-asm -fregmove -foptimize-register-move -fargument-alias
 ;  -fstrict-aliasing -fmerge-constants -fzero-initialized-in-bss -fident
 ;  -fpeephole2 -fguess-branch-probability -fmath-errno -ftrapping-math
 ;  -minit-stack=__stack -mmcu=at90can128

  .text
.global  CRCcheck
  .type  CRCcheck, @function
CRCcheck:
/* prologue: frame size=23 */
  push r28
  push r29
  in r28,__SP_L__
  in r29,__SP_H__
  sbiw r28,23
  in __tmp_reg__,__SREG__
  cli
  out __SP_H__,r29
  out __SREG__,__tmp_reg__
  out __SP_L__,r28
/* prologue end (size=10) */
  movw r18,r24   ;  aBuffer, aBuffer
  ldi r25,lo8(0)   ;  i,
  ldi r24,lo8(2)   ;  tmp45,
  std Y+1,r24   ;  stream, tmp45
  movw r26,r18   ; , aBuffer
  ld r24,X   ;  <variable>.Cmd, <variable>.Cmd
  std Y+2,r25   ;  stream,
  std Y+3,r24   ;  stream, <variable>.Cmd
  movw r30,r18   ; , aBuffer
  ldd r24,Z+1   ;  <variable>.Len, <variable>.Len
  std Y+4,r24   ;  stream, <variable>.Len
  cp r25,r24   ;  i, <variable>.Len
  brsh .L3   ; ,
  movw r20,r28   ;  tmp75,
  subi r20,lo8(-(5))   ;  tmp75,
  sbci r21,hi8(-(5))   ;  tmp75,
  adiw r26,5   ;  tmp76,
.L5:
  ld r24,X+   ;  tmp58, <variable>.Payload
  movw r30,r20   ; , tmp75
  st Z+,r24   ;  stream, tmp58
  movw r20,r30   ;  tmp75,
  subi r25,lo8(-(1))   ;  i,
  ldd r24,Y+4   ;  stream, stream
  cp r25,r24   ;  i, stream
  brsh .L3   ; ,
  cpi r25,lo8(16)   ;  i,
  brlo .L5   ; ,
.L3:
  mov r20,r25   ;  i, i
  clr r21   ;  i
  movw r26,r28   ;  tmp61,
  add r26,r20   ;  tmp61, i
  adc r27,r21   ;  tmp61, i
  movw r30,r18   ; , aBuffer
  ldd r24,Z+4   ;  <variable>.Seq, <variable>.Seq
  movw r30,r26   ; , tmp61
  std Z+5,r24   ;  stream, <variable>.Seq
  movw r30,r18   ; , aBuffer
  ldd r24,Z+2   ;  <variable>.CRC, <variable>.CRC
  ldd r25,Z+3   ;  <variable>.CRC, <variable>.CRC
  mov r24,r25   ;  tmp67, <variable>.CRC
  clr r25   ;  tmp67
  movw r30,r26   ; , tmp65
  std Z+6,r24   ;  stream, tmp67
  add r20,r28   ;  i,
  adc r21,r29   ;  i,
  movw r30,r18   ; , aBuffer
  ldd r24,Z+2   ;  <variable>.CRC, <variable>.CRC
  movw r30,r20   ; , i
  std Z+7,r24   ;  stream, <variable>.CRC
  ldi r24,lo8(0)   ;  <result>,
  ldi r25,hi8(0)   ;  <result>,
/* epilogue: frame size=23 */
  adiw r28,23
  in __tmp_reg__,__SREG__
  cli
  out __SP_H__,r29
  out __SREG__,__tmp_reg__
  out __SP_L__,r28
  pop r29
  pop r28
  ret
/* epilogue end (size=9) */
/* function CRCcheck size 70 (51) */
  .size  CRCcheck, .-CRCcheck
.global  Handle_Device
  .type  Handle_Device, @function
Handle_Device:
/* prologue: frame size=0 */
/* prologue end (size=0) */
  ldi r18,lo8(21)   ;  tmp46,
  mul r22,r18   ;  id, tmp46
  movw r18,r0   ;  tmp45
  clr r1
  add r24,r18   ; , tmp45
  adc r25,r19   ; , tmp45
  call CRCcheck   ; 
/* epilogue: frame size=0 */
  ret
/* epilogue end (size=1) */
/* function Handle_Device size 9 (8) */
  .size  Handle_Device, .-Handle_Device
/* 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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
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.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.