PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Frage zu Assembler-Anweisungen



Jaecko
11.10.2008, 19:13
Naabend.

In nem C-Programm verwend ich für kleine Wartezeiten eine Kombination aus Assembler-Befehlen. Diese Anweisung hab ich selbst auch nur per Copy&Paste übernommen. Da ich von Assembler selbst nicht wirklich viel Ahnung hab, wollt ich mal fragen, was genau dort eigentlich gemacht wird.



static inline void _delay4Cycles(ui16_t __count)
{
if (__count == 0)
{
__asm__ __volatile__("rjmp 1f\n 1:");
}
else
{
__asm__ __volatile__ (
"1: sbiw %0,1" "\n\t"
"brne 1b"
: "=w" (__count)
: "0" (__count)
);
}
}


Der "positive" If-Zweig geht ja noch; einfach nur ein Sprung eine Zeile weiter... Also als Basic-Pendant:


GOTO 1
1:

D.h. die Wartezeit wäre hier 1 Cycle.

Nur der "negative" If-Zweig stellt mich dann vor ein Problem.
Was macht dort jede Zeile im einzelnen?

mfG

fhs
11.10.2008, 19:22
Hi,

Im "if" Zweig wird getestet, ob "__count==0" und gegebenenfalls auf den nächsten Befehl gesprungen. Dieser Zweig wird übrigens unter der Dezember 2007 Version von WINAVR wegoptimiert (wenn nicht "-O0")!

Im "else"-Zweig wird von "__count" wird so oft "1" subtrahiert (sbiw="subtract immediate from word"), bis "__count" Null ist (d.h. die "branch not equal" {Sprung rückwärts zum Label "1"} Anweisung wird ausgeführt, wenn das Ergebnis der Subtraktion ungleich Null ist). Ist Null erreicht, geht der Programmzähler einfach auf die nächste Zeile, die dem Inline Code folgt.

In C (ohne Optimierung, sonst würde diese Zeile wahrscheinlich einfach verschwinden!):
while (--__count);

Je nach F_CPU und nötiger Wartezeit würde ich Dir eher zu "_delay_us(..)" aus "util/delay.h" raten (in der Klammer sollte ein Konstante stehen und Du musst die Optimierung eingeschaltet haben).

Gruß

Fred

Jaecko
11.10.2008, 20:49
Thx. Also _delay_ms war mir bekannt; dass es das gleiche mit µs auch noch gibt, nicht. Werds dann demnächst mal überall austauschen.

fhs
11.10.2008, 21:38
Hier die Dokumentation zu den Funktionen _delay_us(..) und _delay_ms(..): http://www.nongnu.org/avr-libc/user-manual/group__util__delay.html