mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik C-Funktion per Pointer mit Inline ASM aufrufen


Autor: Henning Lorch (lorchi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo, das obige will ich tun ;) Da die normalen C-Funktionszeiger bei
mir nicht funktioniert haben, wollte ich es per inline asm versuchen.
Nach verschiedenfachem rumexperimentieren funktioniert nun das da:

asm volatile(
"push r16\n\t"
"push r17\n\t"
"mov r16, %0 \n\t"
"mov r17, %1 \n\t"
"movw r30, r16\n\t"
"icall\n\t"
"pop r17\n\t"
"pop r16\n\t"
:: "e" (pointer_lowbyte), "e" (pointer_highbyte));

Allerdings sieht das verdächtig nach überflüssigem Code aus. Das wäre
noch nicht so schlimm. Aber ich traue dem Braten nicht, denn folgende
frühere Version:

asm volatile(
"mov r30, %0 \n\t"
"mov r31, %1 \n\t"
"icall\n\t"
:: "e" (pointer_lowbyte), "e" (pointer_highbyte));

funktionierte zwar zuerst, aber der Kompiler hat unvorhersagbar die
Register durcheinandergewürfelt. Aus einem mov-Kommando macht er
nämlich ein ld (aus der Adresse, die er kennt, in ein Zwischenregister)
und dann ein mov (vom Zwischenregister in das angegebene Zielregister
(z.B.r30)). Als Zwischenregister hat er aber unterschiedliche genommen,
auch mal r30 oder r31, und damit jeweils das andere Byte überschrieben,
was zu sehr merkwürdigen Sprungadressen geführt hat, was auch sonst...

Die obere Funktion funktioniert nun, aber ich frage mich wie lange.
Denn es ist ja immer noch nicht vorgegeben, was der Compiler für ein
Zwischenregister benutzt, und damit kann dasselbe Problem auch oben
auftreten.

Also die Frage: wie rufe ich eine Funktion auf, die durch einen Pointer
adressiert ist (und natürlich keine Übergabeparameter hat)? Bzw. wie
bekomme ich den Pointer sicher in inline asm und führe einen call aus?

Um ehrlich zu sein: ich blicke durch inline asm nicht wirklich durch,
z.B. die echten Auswirkungen der compiler constraints, und das
Geschehen bei Übergabe von Parametern/Variablen sind mir noch etwas
schleierhaft. Vielleicht lässt sich ja die Registerbelegung steuern?
Ich hab mal als Alternative "O" ausprobiert, dachte, das muss er doch
akzeptieren als uint8_t oder so, aber da kamen nur Fehlermeldungen.

Ich hatte noch eine Alternative ausprobiert, und zwar die
Pointervariable an Register zu binden:

register uint8_t pL asm("r3");
register uint8_t pH asm("r4");
...code...
asm volatile(
"mov r30, r3 \n\t"
"mov r31, r4 \n\t"
"icall\n\t" :: );

Aber das binding hat gar nicht funktioniert, die Variablen lagen nicht
in den angegebenen Registern. Habe ich die Syntax auch nicht
verstanden?

Danke schonmal,
Grüße, Henning

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
.

  "Da die normalen C-Funktionszeiger bei
   mir nicht funktioniert haben, "

Was spricht dagegen, genau dieses Problem zu lösen?
Der Versuch, das mit Inline-Assembler zu "emulieren", dürfte aufgrund
der gesteigerten Komplexität noch eher zum Scheitern verurteilt sein.

Autor: Henning Lorch (lorchi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Rufus,

jedes gelöste Problem ist zwar ein schönes Problem, aber so ists für
meinen Fall praktischer. Ich sitze an einem kompakten Menü, wo jeder
Eintrag u.a. einen Pointer und ein Typ-Flag besitzt. Je nach Typ kann
nun entweder eine Funktion aufgerufen werden, die den Variablentyp
hinter Pointer bearbeitet, oder mit derselben Pointervariable direkt
eine benutzerdefinierte Spezialfunktion. So spare ich mir viele
Bedingungsabfragen. Mit C habe ich da einen Typen-Konflikt (vielleicht
ist avr-gcc aber auch toleranter, muss ich mal probieren).

Zweitens habe ich die Auswahl zwischen 2 Problemen. Das hier hat schon
gezeigt, dass es laufen kann. Ich muss nur einen Weg finden, die
Register unter Kontrolle zu halten.

Daher wollte ich es so probieren...
Die Definition von Funktionszeigern jedenfalls mochte der avr-gcc
bisher nicht (in meinen Versuchen).

Autor: Henning Lorch (lorchi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich nehm alles zurück.

Ich hab gestern stundenlang getüftelt.

Eben hab ich in 5 Minuten mal alles auf Funktionszeiger umgeschrieben,
und es läuft auf Anhieb perfekt, problemlos, übersichtlich.

...glaub ich bin überarbeitet... :))

Danke für den Hinweis auf den "normalen Weg zurück"...

Grüße, Henning

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.