Kann der inline assembler auch nested loops verarbeiten? Das Manual gibt
zu den Labels nichts her. Eine einfache Schleife ist einfach, jedoch ist
nirgendwo beschrieben, wie nested Loops auszusehen haben und ob das
überhaupt geht.
Du kannst, wie überall im gas (GNU assembler), "local labels" benutzen.
Das sieht ungefähr so aus:
1
1: something
2
something else
3
2: more stuff
4
goes here
5
breq 99f
6
other stuff
7
brne 2b
8
even more junk
9
brne 1b
10
99:
Beim Sprungziel bezeichnet ein angehängtes `b', dass der entsprechende
Label rückwärts zu suchen ist, ein `f', dass die Suche vorwärts
statt findet. Wenn es Labels mit gleicher Nummer gibt, ,,gewinnt''
der, der in Suchrichtung am nächsten liegt.
Nachtrag. Und wenn man genau hinschaut, da steht in den Beispielen
tatsächlich 1b und nicht lb. Hier sieht es auch noch gleich aus. Ich
habe das 1b als Abkürzung für Label gelesen.
Gast wrote:
> Nachtrag. Und wenn man genau hinschaut, da steht in den Beispielen> tatsächlich 1b und nicht lb. Hier sieht es auch noch gleich aus. Ich> habe das 1b als Abkürzung für Label gelesen.Beitrag "Re: Merkwürdige Fragen (Forum-Trolle?)"
Habe jetzt ein wenig mit dem Syntax rumgespielt. Er ist einfach nur
furchtbar :-) Aber für eine einfache aber genaue delay-Routine sollte er
reichen.
Hier der Code, unabhängig davon, was er macht:
Gast wrote:
> Habe jetzt ein wenig mit dem Syntax rumgespielt. Er ist einfach nur> furchtbar :-)
Naja, sie ist unwahrscheinlich mächtig, aber das macht sie für einen
Anfänger nicht leicht zu benutzen. Wenn du sie aber mal mit anderen
Compilern vergleichst, bei denen darfst du oftmals darauf hoffen, dass
der Compiler deine internen Variablen in der nächsten Version noch im
gleichen Register ablegen wird wie in der aktuellen, da sie keine
Möglichkeit haben, derartige Dinge in das inline asm statement hinein
zu propagieren.
GCC benutzt für inline asm letztlich die gleiche Semantik wie für
seine compiler-internen "insns", d. h. es werden die gleichen Wege für
die Register-Allokation benutzt usw. Der Vorteil ist, dass damit dem
Implementierer der Systembibliothek ein mächtiges Werkzeug in die Hand
gegeben ist, seinen Nutzern für viele Details der Zielplattform
effektive Lösungen anbieten zu können. Für einen Anfänger sind sie
eher nicht geeignet, und sie können/sollen auch keinesfalls explizite
Assemblerprogramme ablösen.
> _asm_ __volatile__> (> "1: \n\t"> "2: \n\t"
Warum zwei Labels auf die gleiche Stelle?
> " dec %[inner] \n\t"> " jne 2b \n\t"> : [inner] "=r"(time)> " dec %[outer] \n\t"
Das geht nicht. Die Syntax ist:
[prepasm("string" : output operands : input operands [: clober
list]);[/pre]
Du versuchst gerade, mehrere Strings mit meheren Listen von Operanden
zu mischen.
> Abgeleitet war die Loop aus einem Beispiel, wo ein "+r" verwendet> wurde. Es ist nirgendwo beschrieben, scheint aber zu funktionieren.
"r" ist das constraint für einen Registeroperanden, das "+" macht ihn
read/write. Sollte beschrieben sein, müsste ich dir raussuchen.
Ich kenne mich mit MSP430 nicht aus, aber guck dir mal sowas an:
1
voiddelay_ms(inttime,intcount)
2
{
3
__asm____volatile__
4
(
5
"1: \n\t"
6
" dec %[inner] \n\t"
7
" jne 1b \n\t"
8
" dec %[outer] \n\t"
9
" jne 1b \n\t"
10
:
11
:[inner]"r"(time),[outer]"r"(count)
12
);
13
}
Vermutlich musst du dir register auch noch vorbelegen. Im Moment ist
es bissel Humbug, weil du die erste innere Schleife mit dem Wert von
"time" (aus den Funktionsparameters) zu zählen beginnst, die folgenden
dann aber bei 0. Vielleicht wolltest du ja sowas?
1
voiddelay_ms(inttime,intcount)
2
{
3
inti;
4
__asm____volatile__
5
(
6
"1: \n\t"
7
" mov %[inner], %[preload] \n\t"
8
"2: \n\t"
9
" dec %[inner] \n\t"
10
" jne 2b \n\t"
11
" dec %[outer] \n\t"
12
" jne 1b \n\t"
13
:[inner]"=&r"(i)
14
:[preload]"r"(time),[outer]"r"(count)
15
);
16
}
Ich hab's rudimentär auf einem AVR-GCC getestet, die Registerzuweisung
scheint mir erstmal OK zu sein.
Eine Alternative wäre es, für [inner] ein festes Register vorzusehen
und dies in der clobber list aufzuführen.
Wobei in r15 time steht. Optimiert werden könnte es, wenn die übergebene
Variable time nicht nach r15 sondern r14 geschrieben wird. Dann fällt
natürlich die erste Zeile weg.
Anfangs wurde immer ein clr r15 eingeschoben, nicht gerade hilfreich in
diesem Fall.
Was aus der Doku schwer raus kam:
Der erste Doppelpunkt beschreibt den Output, der zweite den Input, der
dritte die clopper-Liste. Outputs habe ich ja keine. Schreibe ich die
Doppelpunkte untereinander, wird ein Syntax Error ausgegeben.
In der Doku (ich habe mich an die des avr gelehnt), steht nur "r", "=r"
und "=&r" drin. Es wäre wirklich hilfreich zu erfahren, wo genau das
steht.
Mit einer guten Anleitung müssen die Jungs echt noch üben :-)
Gast wrote:
> Was aus der Doku schwer raus kam: Der erste Doppelpunkt beschreibt> den Output, der zweite den Input, der dritte die clopper-Liste.
"clobber".
info gcc -> C Extensions -> Extended Asm
`` Each operand is described by an operand-constraint string followed
by the C expression in parentheses. A colon separates the assembler
template from the first output operand and another separates the last
output operand from the first input, if any.''
(OK, die clobbers sind dort nicht beschrieben.)
> Outputs habe ich ja keine. Schreibe ich die Doppelpunkte> untereinander, wird ein Syntax Error ausgegeben.
Dann hast du noch was anderes vermurkst, das geht auf jeden Fall. Das
oben zitierte Beispiel war bei mir ja durch den Compiler gegangen (nur
assemblieren konnte ich es nicht mangels MSP430-Tools).
> In der Doku (ich habe mich an die des avr gelehnt), steht nur "r",> "=r" und "=&r" drin. Es wäre wirklich hilfreich zu erfahren, wo> genau das steht.
info gcc -> C Extensions -> Constraints -> Modifiers
```+' Means that this operand is both read and written by the
instruction.''
> Mit einer guten Anleitung müssen die Jungs echt noch üben :-)
Nein, ich würde stattdessen von der Bibliothek erwarten, dass sie dir
eine entsprechende delay-Funktion zur Verfügung stellt. Die
Entwickler der Bibliothek sollten wissen, wie man mit dem
inline-Assembler umgeht, du als Endnutzer musst das nicht unbedingt.
> Nein, ich würde stattdessen von der Bibliothek erwarten, dass sie dir> eine entsprechende delay-Funktion zur Verfügung stellt.
Codevision macht das für den AVR. Die haben es tatsächlich geschafft,
relevante Funktionen wie getchar, putchar oder delay in Assembler zu
definieren. Vielleicht bastle ich mir da selber etwas zusammen.