www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Lookup-Tabelle mit Sprungbefehlen


Autor: Julien M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

vieleicht wurde meine Problematik schon einmal durchgesprochen. Ich
konnte aber leider keinen passenden Post finden.

Nun zum Problem...
Hardware: ATmega8515
Firmware: Assembler

Ich habe in einem Register einen Wert zwischen 1 und 32 stehen.
Nun habe ich gedacht, dass ich den Z-Pointer an den Anfang meiner
Lookup-Tabelle setze und anschließend den Pointer mit dem Registerwert
addiere. In der Lookup-Tabelle sollen sich aber nur Sprungbefehle für
Unterprogramme befinden. Funktioniert das überhaupt??

Aufbau der Tabelle:

Lookup:
.dw rjmp Prg1 ;Programm 1 aufrufen
.dw rjmp Prg2 ;Programm 2 aufrufen
.dw rjmp Prg3 ;Programm 3 aufrufen

etc...

Zum zweiten stell ich mir die Frage mit welchem Befehl ich den Pointer
dazu bringe auch wirklich zu springen. "lpm" wird ja nicht
funktionieren.

Über Lösungsansätze wäre ich sehr dankbar.

Mfg

Julien

Autor: Santa Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Nun habe ich gedacht, dass ich den Z-Pointer an den Anfang meiner
>Lookup-Tabelle setze und anschließend den Pointer mit dem
>Registerwert addiere. In der Lookup-Tabelle sollen sich aber nur
>Sprungbefehle für
>Unterprogramme befinden. Funktioniert das überhaupt??

Und ob das funktioniert.  Zur Realisierung dieses Vorhabens (Stichwort:
indirekte Adressierung des Programmspeichers) gibt es zwei Befehle:
icall und ijmp (der lpm-Befehl hat hiermit nichts zu tun!).

Hier ein Codebeispiel mit "icall", das dem Thread
http://www.mikrocontroller.net/forum/read-1-157002...
entstammt:


menu:
   ; immer zuerst "low", und dann "high"!
   ldi zl,low(Sprungtabelle)
   ldi zh,high(Sprungtabelle)
   add zl, r16  ; Überlauf nicht ausgeschlossen!
   adc zh, _0   ; Ggf. aufgetretenen Überlauf berücksichtigen
   icall
   ret

menue1:
   ; hier menue1
ret

menue2:
   ; hier menue2
ret

menue3:
   ; hier menue3
ret

menue4:
   ; hier menue4
ret

Sprungtabelle:
   rjmp menue1
   rjmp menue2
   rjmp menue3
   rjmp menue4

Autor: Werner Böllmann (wernerb)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aber Achtung - Falle: bei den verschiedenen AVRs sind die rjmp/jmp
befehle (je nach FLASH ausstattung) unterschielich lang. Eventuell
musst Du den Index erst *2 nehmen (Das gleiche "Problem" wie mit den
interruptvektoren.)

Autor: Julien M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank für die schnellen Antworten.

Soweit ist mir alles klar.
Muß in der Sprungtabelle dann gar kein .db oder .dw verwendet werden?

Autor: Santa Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Muß in der Sprungtabelle dann gar kein .db oder .dw verwendet werden?

Nein, gerade nicht, das ist ja der Clou daran.  Es ist
selbstverständlich möglich, das mit einer Tabelle zu proggen, in der
tatsächlich nur die Sprungziele als Daten stehen (also keine
Sprung*instruktionen* "rjmp ..."), aber wie Du siehst, ist das
umständlicher, weil dann noch das Lesen der Daten mit "lpm"s nötig
ist:

Achtung: Code nur aus dem Kopf hingeschrieben; nicht getestet; keine
Haftung für Fehler aller Art...
menu:
   ; immer zuerst "low", und dann "high"!
   ldi zl, low(Sprungtabelle)
   ldi zh, high(Sprungtabelle)
   add zl, r16  ; Überlauf nicht ausgeschlossen!
   adc zh, _0   ; Ggf. aufgetretenen Überlauf berücksichtigen

   ; Sprungziel aus Tabelle mit zwei "lpm"s lesen
   ; Reihenfolge: erst High-Byte, dann Low-Byte
   lsl zl
   rol zh
   inc zl
   lpm         ; Sprungziel-High-Byte --> r0
   mov r1, r0
   dec zl
   lpm         ; Sprungziel-Low-Byte --> r0
   ; Registerpaar r1:r0 enthält jetzt das Sprungziel,
   ; muß in Registerpaar zh:zl kopiert werden
   mov zl, r0
   mov zh, r1
   icall
   ret

menue1:
   ; hier menue1
ret

menue2:
   ; hier menue2
ret

menue3:
   ; hier menue3
ret

menue4:
   ; hier menue4
ret

Sprungtabelle:
.DW menue1
.DW menue2
.DW menue3
.DW menue4

PS: ".DW rjmp ..." gibt es grundsätzlich nicht!

Autor: Philipp Burch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
.dw rjmp ... Gibt's eigentlich schon, dann hättest du im Register
einfach das Byte, das den Befehl "rjmp" repräsentiert, oder?

Autor: Santa Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> .dw rjmp ... Gibt's eigentlich schon, dann hättest du im Register
> einfach das Byte, das den Befehl "rjmp" repräsentiert, oder?

Der Assembler erwartet hinter ".DW" eine Liste von Konstanten (nur
eine einzige Konstante geht natürlich auch), die irgendwo im Programm
definiert sind. "rjmp" ist jedoch keine Konstante, sondern das
"Gerüst" einer Instruktion. "rjmp Sprungmarke" ist ebenfalls keine
Konstante, sondern eine "komplette" Instruktion (mit dem OpCode
1100kkkkkkkkkkkk; in den k's ist die Sprungzieladresse codiert).  rjmp
"gewaltsam" als Konstante zu definieren ist nicht möglich - der
Assember läßt es (verständlicherweise) nicht zu.  Damit ist alles
gesagt.

Wenn Du das Wort, das den Befehl "rjmp Sprungmarke" repräsentiert, in
ein Register(-paar) einlesen willst, mußt Du einfach

Label:
  rjmp Sprungmarke

ohne ein ".DW" vornedran hinschreiben, den Z-Pointer auf "Label"
setzen und zweimal lpm wie im letzten Beispiel von mir gezeigt
anwenden.

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.