mikrocontroller.net

Forum: Compiler & IDEs Sprungtabelle in Assembler


Autor: Christian Rötzer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo AVR-Fans,
um meinen Strom von Anfragen nicht abreissen zu lassen, kommt hier schon 
wieder die nächste :-)
Also:
Wie kann ich in GCC-Assembler-Code eine Sprungtabelle im ROM definieren 
und zwar so, daß die Adresse NICHT zur Laufzeit durch zwei geteilt wird 
(ich kenne bereits die Funktionen pm_lo8 und pm_hi8, mit denen man so 
ähnliche Dinge erreicht, aber die helfen nichts)

Beispiel:

ziel1:
  ; code...
ziel2:
  ; code...

sprung_tabelle:
  .word ziel1 >> 1
  .word ziel2 >> 1

So würde es im Prinzip aussehen, weil der Prozessor Wortadressen 
benötigt (von Vorwärtsreferenzen wage ich momentan noch gar nicht zu 
träumen). Leider packt das aber der Assembler nicht. Gibt's eine 
korrekte Vorgehensweise? Oder anders: Gibt's eine Doku mit allen 
Funktionen des Assemblers?

In freudiger Erwartung

Christian

Autor: Joerg Wunsch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nun, das einfachste ist, Du läßt das den Compiler machen und
schaust Dir den generierten Assemblercode an. ;-)

Ich habe folgendes Stückchen C mal durch den Compiler gejagt
(avr-gcc -S ...):

void foo(void) {
}

void doo(void) {
}

void (*footab[])(void) _attribute_ ((progmem)) = {
        foo, doo
};

Das pm() scheint der Trick zu sein.  Das besagt offenbar,
daß der entsprechende Wert aus dem program memory zu nehmen
ist.

Normalerweise findest Du die Doku des GNU Assemblers im Netz
(oder bei WinAVR auch mit auf der Platte).  Allerdings
scheinen mir die plattformabhängigen Teile für AVR nicht
dokumentiert worden zu sein. :-(  Wenn ich mal viel Zeit
habe, schaue ich mir mal an, ob man da wenigstens eine kurze
Zusammenfassung innerhalb der avr-libc Doku einarbeiten kann.

Autor: Christian Rötzer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, durch den Assembler jagen ist nicht schlecht...ich hab diese pm() 
Funktion mal direkt im Assembler getestet, die tut einfach nichts :-(. 
Naja, damit ich mal langsam vorwärts komme, rechne ich halt nun doch zur 
Laufzeit um (damit kann man "nur" 64k>Byte< des verwendeten ATmega128 
erreichen, was derzeit aber ein eher theoretisches Problem ist).
Ziel war es ursprünglich, einen bestehenden Quelltext 1:1 von GCC-AS 
übersetzen zu lassen und zwar so, daß sich der gleiche Binärcode ergibt. 
Damit könnte ich feststellen, ob sich Fehler bei der "Portierung" 
eingeschlichen haben. Man glaubt nicht, was das für Probleme aufwirft! 
Erst im nächsten Schritt wollte ich dann Schritt für Schritt C-Code 
einbinden. Naja vielleicht finden wir ja noch den Befehl (mal im 
Quelltext von GCC-AS nachschaun)

Autor: Joerg Wunsch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habe gerade mal ins tc-avr.c geschaut:

        case BFD_RELOC_AVR_16_PM:
          bfd_putl16 ((bfd_vma) (value >> 1), where);
          break;

Sieht also so aus, als würde dieser pm() Operator bereits die
Umrechnung von Byte- auf Wortadressen vornehmen.

Autor: Christian Rötzer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab mal Dein foo-Beispiel durch den Compiler geschoben: Damit liegt 
die Tabelle aber noch im RAM. Das sieht man deutlicher, wenn man mal 
eine Funktion über die Tabelle aufruft, z.B. footab[0](). Da greift er 
dann mittels lds-Befehl auf die Tabelle zu.
Wenn ich aber stattdessen statt _attribute_ ((progmem)) einfach nur 
PROGMEM schreibe (mit passendem Include), dann greift er mit dem 
lpm-Befehl in die Tabelle. Nur - die Tabelle wird einfach direkt vom 
Compiler korrekt erzeugt. Damit konnte ich also auch keine 
Assembler-Geheimnisse entlocken...es bleibt spannend!

Autor: Joerg Wunsch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ob Du __attribute__((progmem)) oder __attribute__((_progmem_))
schreibst (was anderes ist PROGMEM nicht), ist weitgehend egal.
Im generierten Assemblercode siehst Du, daß er das nach section
.progmem.data setzt, das ist genau das, wo es hingehört.

Daß Du auf ein progmem-Array nicht direkt zugreifen kannst
sondern nur mit LPM, liegt in der Verantwortung des Programmierers.
Der Compiler benutzt LPM nie von sich aus!  Wenn das also bei
Dir dann irgendwann doch geklappt hat, hast Du das irgendwo
in einem Macro oder sowas indirekt selbst getan.

Was fehlt Dir denn noch an Assembler-,,Geheimnissen''?  Das pm()
war der eigentliche Trick.

Autor: Christian Rötzer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, wie gesagt, der pm()-Operator liefert mir als Ergebnis leider nur 
das zurück, was ich als Argument übergeben habe (komisch). Benötigen tue 
ich das Teilen durch zwei.
Moment mal, hast Du .progmem.data gesagt? Das ist quasi eine subsection 
oder wie, da muß ich nochmal forschen!

Autor: Christian Rötzer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jetzt frag' mich mal jemand was ich früher gemacht habe: Es interessiert 
mich nicht mehr. Fakt ist: der pm()-Operator tut was er soll. Die 
Software ist jetzt 1:1 auf den neuen Assembler übernommen: Ab jetzt wird 
nur noch C programmiert :-)))))

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.