Forum: Compiler & IDEs Bad expression


von Benno Müller (Gast)


Lesenswert?

Hallo!

Hab folgende C-Funktion geschrieben mit eingebettetem Assembler-Code, 
welche nichts weiter machen soll als einen gewissen Delay.

...void delay05(void)
...{
...  asm volatile
...  (
...    // =============================
...    //    delay loop generator
...    //     8333333 cycles:
...    // -----------------------------
...    // delaying 8333325 cycles:
297    "          ldi  R17, #37h"  "\n\t"
298    "WGLOOP0:  ldi  R18, #D6h"  "\n\t"
299    "WGLOOP1:  ldi  R19, #EBh"  "\n\t"
...    "WGLOOP2:  dec  R19"  "\n\t"
...    "          brne WGLOOP2"  "\n\t"
...    "          dec  R18"  "\n\t"
...    "          brne WGLOOP1"  "\n\t"
...    "          dec  R17"  "\n\t"
...    "          brne WGLOOP0"  "\n\t"
...    // -----------------------------
...    // delaying 6 cycles:
306    "          ldi  R17, #02h"  "\n\t"
...    "WGLOOP3:  dec  R17"  "\n\t"
...    "          brne WGLOOP3"  "\n\t"
...    // -----------------------------
...    // delaying 2 cycles:
...    "          nop"    "\n\t"
...    "          nop"    "\n\t"
...    // =============================
...    :
...    :
...  );
...}

Ich bekomme jedoch folgende Fehler vom Compiler:

C:\TEMP\ccXbaaaa.s: Assembler messages:
C:\TEMP\ccXbaaaa.s:297: Error: Bad expression
C:\TEMP\ccXbaaaa.s:297: Error: garbage at end of line
C:\TEMP\ccXbaaaa.s:298: Error: Bad expression
C:\TEMP\ccXbaaaa.s:298: Error: garbage at end of line
C:\TEMP\ccXbaaaa.s:299: Error: Bad expression
C:\TEMP\ccXbaaaa.s:299: Error: garbage at end of line
C:\TEMP\ccXbaaaa.s:306: Error: Bad expression
C:\TEMP\ccXbaaaa.s:306: Error: garbage at end of line

die Zeilen hab ich mit Zahlen markiert!

Was ist daran falsch und wie muss es richtig heißen?

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Was soll "#D6h" sein? Probier's mal mit "0xD6".

von Benno Müller (Gast)


Lesenswert?

supi funzt!

#D6h hatte ich genommen weil ich das von der Asm-Programmierung mit dem 
80C517 kannte. Urpsürnglich stand aber &D6 dort, aus dem 
AVRDelayLoop-Generator, dort hatte ich aber auch einen Fehler ;)

von Peter (Gast)


Lesenswert?

Ob das so gut geht wenn man einfach in einem eingebetteten Assemblercode 
ein paar Register überklatscht ohne den Compiler zu informieren? Auch 
wenn es sich um eine eigenständige Funktion handelt hätte ich hierbei 
trotzdem schwerste Bedenken. Das muss ja nicht notwendigerweise 
bedeuten, dass der Compiler alle seine Register leerräumt. Aber er wird 
es ja merken, wenn auf einmal seltsame Effekte auftreten.

Gruss,

Peter

von Benno Müller (Gast)


Lesenswert?

Hast du nen besseren Vorschlag was man machen könnte?

Ich hatte zuerst auch folgenden Code:

void delay05(void)
{
  int i;

  for(i=0; i < 833; i++)
  {
    asm volatile("nop"::);
  }
}

Macht genau das selbe, nur das Problem ist nur das ich nicht weiß 
wieviel Zyklen die For-Schleife pro Durchgang beansprucht und bei meinem 
Programm muss ich relativ genau sein.

von Schmittchen (Gast)


Angehängte Dateien:

Lesenswert?

> Hast du nen besseren Vorschlag was man machen könnte?
Ich benutze den angehängten Code dafür. Ist zwar etwas umfangreicher (51 
Bytes), dafür aber auch genau und sauber/sicher.

> ich nicht weiß wieviel Zyklen die For-Schleife pro Durchgang beansprucht und bei 
meinem Programm muss ich relativ genau sein.

Ich habe den Code mittels AVR-Studio ausgemessen.

Schmittchen.

von Jonas Diemer (Gast)


Lesenswert?

genau. das mit dem ausmessen hab ich auch immer so gemacht. das klappt 
recht gut, und dann haste nicht diese assembler krücke.

von Benno Müller (Gast)


Lesenswert?

Danke. Werds mal ausprobieren wenn mein anderes Problem behoben ist ;-)

von Peter (Gast)


Lesenswert?

Das mit dem eingebetteten Assembler ist ja an sich ok, man sollte nur 
die Clobber-Liste ausfüllen, damit der Compiler weiss, welche Register 
man für seinen eigenen Code in Beschlag nimmt. Hier hat sich nämlich ein 
netter Kollege mal die Mühe gemacht, einen Code-Generator (Assembler) 
für Warteschleifen zu programmieren, der einem für jede gewünschte 
Verzögerung den exakten Code ausgibt. Den so erzeugten Assembler-Code 
kann man z.B. gut in C einbetten. Wenn man einmal die zusätzliche Zeit 
für den Funktionsaufruf in C ermittelt hat, kann man sich fortan 
Verzögerungsroutinen auf den Taktzyklus genau programmieren ohne das 
Timing mit dem AVR-Studio jedesmal zurechtfutscheln zu müssen. Nur mal 
so als Tip.

Gruss,

Peter

von Jonas Diemer (Gast)


Lesenswert?

hmmm.. die frage ist: dauert der funktionsaufruf nicht länger für ne 
warteschleife, die 3 regs benutzt, als eine, die 2 benutzt? der compiler 
muss doch vorher dann die regs sichern und zurückholen... oder ist die 
clobber liste global?

von Benno Müller (Gast)


Lesenswert?

wie definier ich denn solch eine clobber liste?

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.