Forum: Compiler & IDEs forschleife: anzahl Takte??


von chrigu (Gast)


Lesenswert?

hi,
kann mir jemand sagen wie viele takte EIN Durchlauf einer simplen
for-Schleife hat bzw. wie ich das rausfinden kann?( z.B:
for(i=1;i<100;i++); )
und wie ist das mit einer while schleife?z.B.x=100; while(x--);

Und noch eine frage am rande kann man eine if-bedingung in eine
for-schleife einbauen? z.B. for(i=1;i<100;if(x==3)i++;);

Hoffe ihr könnt mir helfen
 Gruss Chrigu

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Die erste Frage lässt sich nur durch Ansehen des vom Compiler erzeugten
Assemblerlistings klären. Welche Compileroption für die Erzeugung eines
kommentierten Assemblerlistings (C-Quelltextzeilen als Kommentare
eingefügt) zuständig ist, wirst Du der Dokumentation entnehmen können.
Das wurde hier aber auch schon gelegentlich besprochen.

Was spricht dagegen, das in der zweiten Frage formulierte Konstrukt
einfach auszuprobieren?

Wenns nicht geht, wird das der Compiler schon sagen.

von chrigu (Gast)


Lesenswert?

hi,
danke:D auf die idee mit dem compilieren hätt ich au ckommen können,
danke!!
Aber nun habe ich in einer vom compiler erzeugten *.lss Datei
gefunden:
....
int x, y=3;
for(x=100;x;)if(y==3)x--;;
  64:  84 e6         ldi  r24, 0x64  ; 100
  66:  90 e0         ldi  r25, 0x00  ; 0
  68:  c2 97         sbiw  r24, 0x32  ; 50
  6a:  f1 f7         brne  .-4        ; 0x68
  6c:  00 c0         rjmp  .+0        ; 0x6e
....
ist das jetzt der asm-codefür dieses Konstrukt? also dauert dies 5
takte?
habe leider null ahnung von asm...
Danke schonmal ;-)

von Wolfram (Gast)


Lesenswert?

Ich denke, das was du da probierst wird nicht ganz funktionieren.
Die Eingangsbedingungen in die for-schleife sind vorbestimmt.
Ein Optimierer kann diese Schleife voll auflösen da er sämtliche
parameter kennt. Oder deutlicher gesagt die ganze Schleife kann
vollständig eliminiert werden.
Solltest du eine delay Routine programmieren wollen, so füge ein nop
ein.
Du willst warten bis y 100mal 3 war. y ändert sich nebenher z.B. aus
einem Interrupt. Ohne das kleine Wörtchen volatile wird das nicht
funktionieren.

von johnny.m (Gast)


Lesenswert?

Das ist tatsächlich der Assembler-Code für die for-Schleife. Aber wie
Wolfram schon sagte: Deine Schleife macht anscheinend nicht viel
Sinn... Da y nicht als volatile deklariert ist, wird die if-Abfrage
komplett wegoptimiert. Außerdem macht der Compiler aus der eigentlichen
for-Schleife mit (gewollten) 100 Durchläufen eine mit 2 Durchläufen (x
wird nicht um 1 sondern um 50 dekrementiert). Compilier das ruhig mal
mit ausgeschalteter Optimierung und schau Dir das Ergebnis an. Da kommt
wesentlich mehr Code raus...

Ganz allgemein: Wenn Du anhand der .lss-Datei die Ausführungszeiten
ermitteln willst, musst Du Dir das Instruction Set Manual mal
vornehmen. Da steht für jeden einzelnen Befehl drin, wie viele
Taktzyklen er braucht. Es gibt nämlich auch Befehle, die mehr als einen
Zyklus brauchen (z.B. sbiw braucht zwei) und es gibt Sprung- und
Verzweigungs-Befehle, die je nachdem, ob die Bedingung wahr oder falsch
ist, unterschiedliche Ausführungszeiten haben (z.B. brne).

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


Lesenswert?

> Solltest du eine delay Routine programmieren wollen, so füge
> ein nop ein.

Oder nimm gleich die Funktionen aus <util/delay.h>, dort haben
sich andere Leute schon die Mühe gemacht, die Zyklenzahlen
auszuzählen.

von Rolf Magnus (Gast)


Lesenswert?

Vor allem haben die auch inline-Assembler verwendet, so daß die
Zyklenzahlen nicht von den Optimierungseinstellungen oder der Version
des Compilers abhängen.

von Stefan (Gast)


Lesenswert?

Ganz anderer Ansatz: Mit einem Frequenzzähler am laufenden System
ausmessen. Das ist manchmal einfacher als komplexe Assembleropcodes
nachzuschlagen.

int main(void)
{
  while(1)
  {
    port_einschalten();

    /* Messobjekt z.B. */
    delay_funktion(1000);

    port_ausschalten();
  }
}

Die Ausführungszeit ist 1/Frequenz.

Die Messung wird um so genauer, je "enger" sich die Schaltbefehle am
Untersuchungsobjekt befinden. Also ggf. statt Funktionen Makros
benutzen.

Noch ein anderer Ansatz: Manche Debugger/Simulatoren zeigen die
benötigte Zyklenzahl für ein Stück Assemblercode auch an.

von Alex (Gast)


Lesenswert?

while(1)
  {
    port_einschalten();
    delay_funktion(1000);
    port_ausschalten();
    delay_funktion(1000);
  }

Sonst ist die Pulsweite ein wenig klein :)

von Stefan (Gast)


Lesenswert?

Stimmt. Danke!

Typischer Fall von ins Forum tippen und nicht nachdenken. Beim letzten
Mal hatte ich es nämlich so gemacht

  while(1)
  {
    port_toggle();

    /* Messobjekt z.B. */
    delay_funktion(1000);
  }

von chrigu (Gast)


Lesenswert?

Hey, danke viel mal!
Ich habe die optimierung mal ausgeschaltet und tatsächlich kam
ordentlich viel mehr code raus.
Damit das ganze nicht so wegoptimiert wird muss ich also die variablen
als volatile deklarierten.
Allerdings ist mir folgendes nicht ganz klar:
> Solltest du eine delay Routine programmieren wollen, so füge
> ein nop ein.
Wo soll ich nop einfügen?? einfach in die Schleife?
for(blabla)
{bla;
nop} ???
Grüsse
Chrigu

von peter dannegger (Gast)


Lesenswert?

Ich verstehe nicht, warum sich Leute immer das Leben unnötig schwer
machen müssen und vielleicht noch umständlich irgendwelche Delays
ausmessen müssen.

Und beim nächsten Quarz oder der nächsten Compilerversion stimmt dann
gar nichts mehr und der Ärger geht von vorne los.


Man kann doch prima einen Timer nehmen und Compiler unabhängig
beliebige Delays für beliebige Quarze bequem vom Präprozessor berechnen
lassen:

http://www.mikrocontroller.net/forum/read-4-84831.html#new


Peter

von Stefan (Gast)


Lesenswert?

Peter, dort wo du schon warst, müssen andere (ich) erst noch hinkommen
;-) Für einen Anfänger (wie mich) ist das Ausmessen der am schnellsten
erfolgversprechende Weg. Und der Appetit kommt bekanntlich beim
Essen... Zum Glück gibt es dann feine Kochrezepte wie deine "genaue
Sekunde"!

von chrigu (Gast)


Lesenswert?

den Timer könnte ich schon nehmen, habe den timer 0 und 1(mega8)
allerdings schon belegt, möchte nicht noch den letzten auch nehmen
(mühsam):-). Vielleicht nehme ich den am ende doch,
 aber wo muss ich grundsätzlich nop hinschreiben? kann ja auch sonst
mal nützlich sein denke ich.
Danke:)

(PS: ich brauche eigentlich nicht direkt ein delay, würde auf umwegen
aber auch damit gehen.)

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


Lesenswert?

Man nimmt im Wesentlichen einen Timer, der den "Systemtakt" liefert,
und lässt den dann alle zeitgesteuerten Ereignisse abarbeiten.  Damit
braucht man nicht für jede Verzögerun einen neuen Hardware-Timer.

Der NOP gehört in die Schleife:

_asm_ volatile("nop");

damit diese nicht wegoptimiert werden kann.  Aber s. o., wenn schon
Verzögerung mit Schleifen, nimm besser das, was andere dir schon
vorgearbeitet haben.  Für kurze Verzögerungen (also vor allem solche
im Mikrosekundenbereich) sind delays oft genug vonnöten, weil sich
das Anwerfen eines Timers dann nicht erst lohnt.

von Karl H. (kbuchegg)


Lesenswert?

> Für einen Anfänger (wie mich) ist das Ausmessen der am schnellsten
> erfolgversprechende Weg.

Für einen Anfänger ist der erfolgversprechendste Weg Funktionen
zu benutzen, die andere bereits vorgefertigt haben und die
daher auch funktionieren.

In 'delay.h' gibt es eine fix fertige funktionierende
Verzögerungsschleife, wenns denn unbedingt eine Verzögerung
sein soll.

von Wolfram (Gast)


Lesenswert?

>Für einen Anfänger ist der erfolgversprechendste Weg Funktionen
>zu benutzen, die andere bereits vorgefertigt haben und die
>daher auch funktionieren

aber nur wenn er deren Funktionsweise verstanden hat.
gilt insbesondere für die empfohlenen delayroutinen
Lies bitte die Dokumentation und Einschränkungen genau durch.

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.