Ich habe viel Zeit darauf verwandt, die Inline Assembler constrains, zu
versuchen zu verstehen.
Ich bin zu dem Schluss gekommen, dass viele Quellen ungenügend bis
falsch sind.
Ich konnte dennoch genug verstehen um ein paar Fragen zu formulieren:
Muss man eine Variable mehr als einmal nennen, wenn sie sowohl Eingabe
als auch Ausgabe ist, oder reicht ein '+'? (Vermutung: Einmal reicht.)
Sind alle Eingaben read-only, auch wenn sie sich mit '0' ,'1' , ... auf
ein Ausgaberegister beziehen? (Vermutung: Ja, der Bezug bedeutet dem
Compiler eine Kopie anzufertigen.)
Muss man alle Ausgaben die nicht auch Eingaben sind, mit einem '='
versehen, kann es also kein alleinstehendes "r" als Ausgabe-constraint
geben? (Vermutung: Das '=' wird nur gebraucht, wenn man sich bei den
Eingaben auf das selbe Register bezieht, der Compiler beschwert sich
aber nicht, wenn man dies später unterläßt und das '=' dennoch angibt.)
Beziehen sich die modifier ('+', '=', ...) auf die Variable oder das
Register? (Vermutung: Auf die Variable.)
Wo ist der Unterschied zwischen
1)
und
2)
? (Vermutung:
Es sind beide falsch und müssten:
1.
2.
heißen.)
Moritz G. schrieb:
> Ich bin zu dem Schluss gekommen, dass viele Quellen ungenügend bis
> falsch sind.
Die Constraints kommen ursprünglich aus der Maschinenbeschreibung von
GCC, siehe Internals:
http://gcc.gnu.org/onlinedocs/gccint/Modifiers.html#Modifiers
Die Beschreibung
http://www.rn-wissen.de/index.php/Inline-Assembler_in_avr-gcc#Operanden_und_Constraints
sollte auch korrekt sein, ansonsten bitte sagen, was inkorrekt ist.
> Muss man eine Variable mehr als einmal nennen, wenn sie sowohl Eingabe
> als auch Ausgabe ist, oder reicht ein '+'?
Entweder '+' oder die Variable muss bei den Output- und den
Input-Operanden genannt werden
> Sind alle Eingaben read-only, auch wenn sie sich mit '0' ,'1' , ... auf
> ein Ausgaberegister beziehen?
Ja.
Diese Constraints dienen dazu, In- und Output in gleiche Register zu
legen. Das ist bei AVR oft nötig, weil er nur 2-Operanden-Befehle kennt: 1 | asm ("add %0,%2"
| 2 | : "=r" (summe)
| 3 | : "0" (addend1), "r" (addend2))
|
> Muss man alle Ausgaben, die nicht auch Eingaben sind, mit einem '='
> versehen, kann es also kein alleinstehendes "r" als Ausgabe-constraint
> geben?
Nein, und der Compiler wird dann auch meckern.
> Beziehen sich die modifier ('+', '=', ...) auf die Variable oder das
> Register?
Auf beide, denn die Variable ist mit dem Register "verknüpft" —
zumindest zu diesem Zeitpunkt; das kann sich im Coververlauf allerdings
ändern.
> Wo ist der Unterschied zwischen
> 1)
> und
> 2)
2) würde ich unterlassen da var1 2× als Output auftaucht. Stattdessen:
3)
> 1.
> 2.
Beide sind ok, sagen aber was anderes. 2. ist gleichbedeutend mit 1 | "=r" (var1) : "0" (var1)
|
Im Zweifelsfalle in die mit -fdump-rtl-asmcons-details erzeugte
Compilerdump schauen; da ist "+r" durch "=r":"0" ersetzt.
Johann L. schrieb:
Danke für die schnelle Antwort.
> Die Constraints kommen ursprünglich aus der Maschinenbeschreibung von
> GCC, siehe Internals:
> http://gcc.gnu.org/onlinedocs/gccint/Modifiers.htm...
> Die Beschreibung
> http://www.rn-wissen.de/index.php/Inline-Assembler...
> sollte auch korrekt sein, ansonsten bitte sagen, was inkorrekt ist.
Ich kenne beide Seiten. Zur Korrektheit kann ich z.Z. leider nichts
beitragen.
>> Muss man eine Variable mehr als einmal nennen, wenn sie sowohl Eingabe
>> als auch Ausgabe ist, oder reicht ein '+'?
> Entweder '+' oder die Variable muss bei den Output- und den
> Input-Operanden genannt werden
> Im Zweifelsfalle in die mit -fdump-rtl-asmcons-details erzeugte
> Compilerdump schauen; da ist "+r" durch "=r":"0" ersetzt.
Es sind also ohne Ausnahme Zwang guten Grund zwei Schreibweisen für
das Selbe? (Ich hasse so etwas.)
>> Muss man alle Ausgaben, die nicht auch Eingaben sind, mit einem '='
>> versehen, kann es also kein alleinstehendes "r" als Ausgabe-constraint
>> geben?
> Nein, und der Compiler wird dann auch meckern.
Verstehe ich nicht. (wieso dann "nein"?)
Ich habe folgende Theorie:
:"=r"(var1):"r"(var2)
hier könnte der Compiler beide variablen zu einem Register machen. Aus:
"befehl %0,%1" würde quasi "befehl %0,%0".
:"r"(var1):"r"(var2)
hier darf nicht das selbe Register verwandt werden, weil %0
überschrieben werden könnte bevor %1 zum letzten mal gelesen wurde:
mov %0,%1
lsl %0
eor %0,%1
Es macht also eine Unterschied ob man "=r" oder "r" schreibt. Würde man
immer '=' schreiben müssen, wäre es redundant.
Moritz G. schrieb:
>>> Muss man eine Variable mehr als einmal nennen, wenn sie sowohl Eingabe
>>> als auch Ausgabe ist, oder reicht ein '+'?
>> Entweder '+' oder die Variable muss bei den Output- und den
>> Input-Operanden genannt werden
>> Im Zweifelsfalle in die mit -fdump-rtl-asmcons-details erzeugte
>> Compilerdump schauen; da ist "+r" durch "=r":"0" ersetzt.
>
> Es sind also ohne Ausnahme / Zwang / guten Grund zwei Schreibweisen für
> das Selbe? (Ich hasse so etwas.)
Zeig mir die Programmiersprache, die nur eine einzige Darstellungsweise
für eine Aufgabe zulässt.
Zudem werden beide Ausdrucksweisen benötogt und keine kann die andere
vollständig ersetzte — zumindest was die GCC-Interna angeht:
wird verwendet, wenn Operand op sowohl Ein- als auch Ausgabe ist man
aber nur einen Operanden hat. In dem Falle ist es folglich nicht
möglich, op zweiman hinzuschreiben (im Gegensatz zu C/Inline-Assembler)
Hier können sich op0 und op1 unterscheiden, zB kann op0 ein 16-Bit Wert
sein und op1 ein 8-Bit Wert. In dem Falle werden op0 und op1 ins gleiche
Register allokiert. Zumindest für little-Endian wie AVR, auf big-Endians
sieht das anders aus.
>>> Muss man alle Ausgaben, die nicht auch Eingaben sind, mit einem '='
>>> versehen, kann es also kein alleinstehendes "r" als Ausgabe-constraint
>>> geben?
>> Nein, und der Compiler wird dann auch meckern.
>
> Verstehe ich nicht. (wieso dann "nein"?)
Nein, man kann kein alleinstehended "r" als Ausgabe-Contraint
vewrwenden. Vielleicht in einen Fragesatz nur eine Frage packen ;-)
> Ich habe folgende Theorie:
>
> : "=r" (var1) : "r" (var2)
> hier könnte der Compiler beide variablen zu einem Register machen. Aus:
> "befehl %0,%1" würde quasi "befehl %0,%0".
Jepp. %0,%1 bedeutet nicht, daß %0 und %1 in unterschiedliche Register
zu liegen kommen.
> : "r" (var1) : "r" (var2)
> hier darf nicht das selbe Register verwandt werden, weil %0
> überschrieben werden könnte bevor %1 zum letzten mal gelesen wurde:
Wie oben erklärt ist diese Schreibweise nicht möglich und führt zu einer
Fehlermeldung.
Wenn var1 verändert wird, bevor var2 komplett ausgewertet wurde, sind
die korrekten Constraints 1 | : "=&r" (var1)
| 2 | : "r" (var2)
|
Für var1 wird dann auf jeden Fall ein "frisches" Register verwendet.
Beachte, daß der COmpiler den Inine-Assembler nur als einen Klumpen Text
bekommt. Er geht davon aus, daß dieser Klumpen Text sich verhält wie
ein Stück Code, das zu einem Zeitpunkt ausgeführt wird.
So etwas wie eine sequenzielle Abfolge der einzelnen
Zeilen/Befehle/Zeichen/Direktiven/Was-auch-immer in
dem Klumpen gibt es nicht.
Johann L. schrieb:
>>>> Muss man alle Ausgaben, die nicht auch Eingaben sind, mit einem '='
>>>> versehen, kann es also kein alleinstehendes "r" als Ausgabe-constraint
>>>> geben?
>>> Nein, und der Compiler wird dann auch meckern.
>> Verstehe ich nicht. (wieso dann "nein"?)
> Nein, man kann kein alleinstehended "r" als Ausgabe-Contraint
> vewrwenden. Vielleicht in einen Fragesatz nur eine Frage packen ;-)
Also auf beides ein: Ja.
>> : "r" (var1) : "r" (var2)
>> hier darf nicht das selbe Register verwandt werden, weil %0
>> überschrieben werden könnte bevor %1 zum letzten mal gelesen wurde:
> Wie oben erklärt ist diese Schreibweise nicht möglich und führt zu einer
> Fehlermeldung.
> Wenn var1 verändert wird, bevor var2 komplett ausgewertet wurde, sind
> die korrekten Constraints 1 | : "=&r" (var1)
| 2 | : "r" (var2)
|
> Für var1 wird dann auf jeden Fall ein "frisches" Register verwendet.
_ Danke!
Ich möchte es nochmal für mich und andere nach mir (es soll Leute geben
die Foren so nutzen) zusammenfassen:
Bei den Ausgaben ist immer ein =, +, & zu setzen.
'=' Die Variable dient nur der Ausgabe, das Register kann zur Eingabe
verwandt werden.
'+' Die Variable und ihr Register ist sowohl Ausgabe als auch Eingabe.
'&' Die Variable dient nur der Ausgabe, das Register darf nicht zur
Eingabe verwandt werden.
Keine Eingabevariable wird verändert, soll ein Register für die Eingabe
einer Variablen und die Ausgabe einer anderen verwandt werden, muss in
der Eingabesektion mit einer Ziffer auf die betreffende Ausgabe Bezug
genommen werden.
Es ist lediglich guter Stil jede Variable nur einmal zu nennen.
Suchbegriffe: vergabebeschränkung atmel übergabe early clobber
Moritz G. schrieb:
> Ich möchte es nochmal für mich und andere nach mir (es soll Leute geben
> die Foren so nutzen) zusammenfassen:
>
> Bei den Ausgaben ist immer ein =, +, & zu setzen.
& ist nicht immer zu setzen, nur falls nötig. Ausserdem gibe es nur 3
gültige Varianten: "=", "+" und "=&".
> '=' Die Variable dient nur der Ausgabe, das Register kann zur Eingabe
> verwandt werden.
Ja. Auf die Variable wird nur schreibend zugegriffen.
> '+' Die Variable und ihr Register ist sowohl Ausgabe als auch Eingabe.
Auch ok.
> '&' Die Variable dient nur der Ausgabe, das Register darf nicht zur
> Eingabe verwandt werden.
"=&", siehe oben
> Keine Eingabevariable wird verändert, soll ein Register für die Eingabe
> einer Variablen und die Ausgabe einer anderen verwandt werden, muss in
> der Eingabesektion mit einer Ziffer auf die betreffende Ausgabe Bezug
> genommen werden.
"Input-Operanden". "Section/Sektion" mein in der Regel was anderes.
> Es ist lediglich guter Stil jede Variable nur einmal zu nennen.
Ja nach Code muss eine Variable mehrfach genannt werden, etwa 1 | asm ("mov %0,%1"
| 2 | : "=l" (data8)
| 3 | : "d" (data8));
|
> Suchbegriffe: vergabebeschränkung atmel übergabe early clobber
GCC Inline-Assembler Constraints. "Vergabebeschränkung" versteht kein
Mensch.
...und was hat Atmel damit am Hut??
Johann L. schrieb:
> & ist nicht immer zu setzen, nur falls nötig. Ausserdem gibe es nur 3
> gültige Varianten: "=", "+" und "=&".
Ah, schöne Zusammenfassung.
> ...und was hat Atmel damit am Hut??
Eigentlich nichts, aber unsere Beispiele beziehen sich auf die AVR-ISA
von dieser Firma. Sollte jemand also "atmel avr mikrocontroller gcc
constraint inline assembler" bei Google eingeben, kommt er dennoch hier
her.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
|