Forum: Compiler & IDEs Inline Assembler: invalid 'asm': invalid %-code


von Marc L. (marc_l50)


Lesenswert?

Hallo,

ich habe einen Code vor mit, den ich nicht selbstgeschrieben habe, 
eigentlich wollte ich den nur kurz compilen und flashen. Der Code ist ca 
10 Jahre alt und ich habe schon einige Fehler behoben, aber ich bekomme 
bei mehreren Inline-Assembler Blöcken Probleme.
1
uint64_t *__a, *__b; \
2
__a = ((uint64_t *) a); \
3
__b = ((uint64_t *) b); \
4
uint8_t __res,__tmp1, __tmp2; \
5
asm volatile("ldi %0, 0x08" "\n" \
6
 ".L%_1:" "\n\t" \
7
 "ld %1, X+" "\n\t" \
8
 "ld %2, Z+" "\n\t" \
9
 "cp %1, %2" "\n\t" \
10
 "brcs .L%_2" "\n\t" \
11
 "dec %1" "\n\t" \
12
 "brne .L%_1" "\n\t" \
13
 "ldi %0, 0x01" "\n\t" \
14
 "rjmp .L%_3" "\n\t" \
15
 ".L%_2:" "\n\t" \
16
 "clr %0" "\n\t" \
17
 : "=d" (__res) \
18
 : "r" (__tmp1), "r" (__tmp2), "x" (__b), "z" (__a));
Dabei bekomme ich eben den Fehler "invalid 'asm': invalid %-code".
Ich bin mir recht sicher, dass es den .L%_1 liegt, denn wenn ich die "_" 
(underscore) durch "A" ersetzte funktioniert es. Wenn man sich die 
Zeilen so angucke, dann sieht man das die .L%_n immer als Label 
verwendet werden.
Wenn ich das richtig verstanden habe, weist .L auf ein lokales Symbol 
hin. Dann müsste das mit %_1 irgendwie einen Namen aus den Inputs unten 
(__tmp2) ableiten.

Also dann zu meiner Frage: was bedeutet der "_" und warum sollte jemand 
die Labels nicht einfach fest vergeben?

Danke im voraus und viele Grüße,
Marc

von Peter D. (peda)


Lesenswert?

Marc L. schrieb:
> aber ich bekomme
> bei mehreren Inline-Assembler Blöcken Probleme.

Dann laß den Assemblerquatsch und schreib es einfach in C hin.

Ältere AVR-GCC hatten Probleme mit 64Bit und haben dann riesen und 
schnarchlahmen Code erzeugt.
Nimm einen aktuellen AVR-GCC.

von Marc L. (marc_l50)


Lesenswert?

Würde ich gerne, aber wie schon geschrieben, es ist nicht mein eigener 
Code und ich habe auch nicht so recht ne ahnung, was dort passiert. 
Coderaten finde ich gerade bei Asm Code sehr schwer und da sind auch 
noch ein paar Blöcke drin, die wesentlich länger sind.

von denial (Gast)


Lesenswert?

Wo ist .L%_03? Ganz hinten?

Aber unabhängig davon sollte man in solchen schnipseln einfach nur 
Zahlen als Label verwenden und dann mit nachgestelltem b oder f darauf 
verweisen:

asm volatile("ldi %0, 0x08" "\n" \
 "0:" "\n\t" \
 "ld %1, X+" "\n\t" \
 "ld %2, Z+" "\n\t" \
 "cp %1, %2" "\n\t" \
 "brcs 1f" "\n\t" \
 "dec %1" "\n\t" \
 "brne 0b" "\n\t" \
 "ldi %0, 0x01" "\n\t" \
 "rjmp 2f" "\n\t" \
 "1:" "\n\t" \
 "clr %0" "\n\t" \
 "2:" "\n\t" \
 : "=d" (__res) \
 : "r" (__tmp1), "r" (__tmp2), "x" (__b), "z" (__a));

von Peter II (Gast)


Lesenswert?

Marc L. schrieb:
> und warum sollte jemand
> die Labels nicht einfach fest vergeben?

vermutlich weil sie im gesamten code eindeutig sein müssen. Man müsste 
also selber den überblick behalten welches Label wo ist.

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


Lesenswert?

Marc L. schrieb:
> ich habe auch nicht so recht ne ahnung, was dort passiert

64-Bit-Vergleich.

von Peter D. (peda)


Lesenswert?

Marc L. schrieb:
> Coderaten finde ich gerade bei Asm Code sehr schwer

Hat der Autor wirklich nichts kommentiert?
Aus dem Bauch heraus:
1
  if( a < b )
2
    r = 1;
3
  else
4
    r = 0;

von Marc L. (marc_l50)


Lesenswert?

> Wo ist .L%_03? Ganz hinten?
Keine Ahnung, es ist einfach nicht da. Das Fehlt in einem andern Block 
auch.

> vermutlich weil sie im gesamten code eindeutig sein müssen. Man müsste
also selber den überblick behalten welches Label wo ist.
Aber stellt nicht .L sicher, dass das Label nur lokal ist?

Eigentlich würde ich den _ nur gerne durch irgendetwas anders ersetzen, 
aber ich bekomme einfach nicht heraus, was _ als "Modifier" mal gemacht 
hat.

> 64-Bit-Vergleich.
Danke, das ist schonmal nen guter Anfang :)

von Markus F. (mfro)


Lesenswert?

Marc L. schrieb:
> Aber stellt nicht .L sicher, dass das Label nur lokal ist?

Nein.

Mach' es so, wie von denial oben vorgeschlagen.

Die Labels werden nummeriert und dort, wo sie referenziert werden, wird 
ein "b" (für "back") oder "f" (für "forward") angehängt. Benutzt wird 
dann jeweils das nächstgelegene Label mit derselben Nummer in der 
angegebenen Richtung.
Das ist die Standardvorgehensweise für lokale Labels bei gas. 
Einigermaßen seltsam, aber funktioniert.

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


Lesenswert?

Marc L. schrieb:
> Aber stellt nicht .L sicher, dass das Label nur lokal ist?

Lokal schon, aber nur lokal zur Übersetzungseinheit (also das, was bei
C ein „static“ bewirkt).

Aber die Labels müssen innerhalb der Übersetzungseinheit dennoch
eindeutig sein, also irgendwie hochgezählt.  Wie sollte der
Assembler denn sonst wissen, zu welchem .L_42 er springen soll, wenn
es deren mehrere gäbe?

Ich würde mich Peters Ratschlag anschließen: hau den Mist raus.  „Ich
verstehe nicht, was der Code macht und will ihn daher nicht anfassen.“
ist ja eine tickende Zeitbombe, die kann morgen schon hochgehen oder
in einem Jahr, aber in jedem Falle gefährlich.

Wenn du die Zeitbombe wirklich weiter ticken lassen willst, dann nimm
den Ratschlag mit den local labels an:

Beitrag "Re: Inline Assembler: invalid 'asm': invalid %-code"

Die Affinität einiger Leute zu diesen .L_xx-Labels habe ich ohnehin
nie verstehen können.  Dass der Compiler in seinem automatisch
generierten Code sowas benutzt, geht ja noch an (der nummeriert den
Salat halt stur durch), aber für handgeschriebenen Code sind doch
die local labels an dieser Stelle ganz genau das, was man braucht.

: Bearbeitet durch Moderator
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Markus F. schrieb:
> Das ist die Standardvorgehensweise für lokale Labels bei gas.

Nicht nur da übrigens; das Konzept entstammt meines Wissens den
alten Unix-Assemblern.

von Marc L. (marc_l50)


Lesenswert?

ich habe es jetzt einfach durchnummeriert und das funktioniert (wie von 
denial oben vorgeschlagen)

> Hat der Autor wirklich nichts kommentiert?
Ja wirklich, außer gelegentlich einem Datei Header leider nichts.

> Wenn du die Zeitbombe wirklich weiter ticken lassen willst, dann nimm
den Ratschlag mit den local labels an:
Ich habe mit dem Code eigentlich nichts zu tun, ich versuche das TTPA 
Protokoll auf einer Bit-Seriellen Architektur auf einem FPGA zu 
implementieren (im Rahmen meiner Masterarbeit) aber vielleicht verstehe 
ich ja, wenns dann läuft was die ASM Blöcke eigentlich machen und 
überführe sie dann in C.

Ich dachte das der "_" einfach irgendwie deprecated wär :D unter 
http://rn-wissen.de/wiki/index.php/Inline-Assembler_in_avr-gcc#Assembler-Template 
konnte ich jedenfalls kein _ bei den % Platzhaltern finden.

Danke an alle

von Karl H. (kbuchegg)


Lesenswert?

Marc L. schrieb:
> ich habe es jetzt einfach durchnummeriert und das funktioniert (wie von
> denial oben vorgeschlagen)
>
>> Hat der Autor wirklich nichts kommentiert?
> Ja wirklich, außer gelegentlich einem Datei Header leider nichts.
>
>> Wenn du die Zeitbombe wirklich weiter ticken lassen willst, dann nimm
> den Ratschlag mit den local labels an:
> Ich habe mit dem Code eigentlich nichts zu tun, ich versuche das TTPA
> Protokoll auf einer Bit-Seriellen Architektur auf einem FPGA zu
> implementieren (im Rahmen meiner Masterarbeit) aber vielleicht verstehe
> ich ja, wenns dann läuft was die ASM Blöcke eigentlich machen und
> überführe sie dann in C.

Wie schon gesagt, da steht nichts weiter als
1
    if( a <= b )

wobei ich mir mit dem 'gleich' nicht ganz sicher bin.
Analysier mit dem Hintergrund an der verwendenden Stelle, wie das ins 
Bild passt, und wenn du die Richtung hast, wer mit wem in welcher 
Relation verglichen wird, dann schmeiss den Assembler Teil raus. Denn so 
wie dir jetzt, geht es dann auch dem nächsten, der den Code studiert.
Verschwendete Zeit, das nicht ein für alle mal durch C Code zu ersetzen.


Und jetzt komm mir keiner damit, dass Assembler ja sooooo viel schneller 
wäre.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

denial schrieb:
> Wo ist .L%_03? Ganz hinten?

Das soll wohl .L%=_3 heißen.  %= vergibt eine für die Datei und das asm 
eindeutige Zahl.

> Aber unabhängig davon sollte man in solchen schnipseln einfach nur
> Zahlen als Label verwenden und dann mit nachgestelltem b oder f darauf
> verweisen:

Jo, geht auch wenn's weniger textig sein darf.

Marc L. schrieb:
> Ich dachte das der "_" einfach irgendwie deprecated wär :D

Nö, den gab es niw und wird es nicht geben.

> 
http://rn-wissen.de/wiki/index.php/Inline-Assembler_in_avr-gcc#Assembler-Template
> konnte ich jedenfalls kein _ bei den % Platzhaltern finden.

Was du suchst steht da:

http://rn-wissen.de/wiki/index.php/Inline-Assembler_in_avr-gcc#Labels_und_Schleifen

: Bearbeitet durch User
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.