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
>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.html#157316 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
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.)
Vielen Dank für die schnellen Antworten. Soweit ist mir alles klar. Muß in der Sprungtabelle dann gar kein .db oder .dw verwendet werden?
>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...
1 | menu:
|
2 | ; immer zuerst "low", und dann "high"! |
3 | ldi zl, low(Sprungtabelle) |
4 | ldi zh, high(Sprungtabelle) |
5 | add zl, r16 ; Überlauf nicht ausgeschlossen! |
6 | adc zh, _0 ; Ggf. aufgetretenen Überlauf berücksichtigen |
7 | |
8 | ; Sprungziel aus Tabelle mit zwei "lpm"s lesen |
9 | ; Reihenfolge: erst High-Byte, dann Low-Byte |
10 | lsl zl |
11 | rol zh |
12 | inc zl |
13 | lpm ; Sprungziel-High-Byte --> r0 |
14 | mov r1, r0 |
15 | dec zl |
16 | lpm ; Sprungziel-Low-Byte --> r0 |
17 | ; Registerpaar r1:r0 enthält jetzt das Sprungziel, |
18 | ; muß in Registerpaar zh:zl kopiert werden |
19 | mov zl, r0 |
20 | mov zh, r1 |
21 | icall
|
22 | ret
|
23 | |
24 | menue1: |
25 | ; hier menue1 |
26 | ret
|
27 | |
28 | menue2: |
29 | ; hier menue2 |
30 | ret
|
31 | |
32 | menue3: |
33 | ; hier menue3 |
34 | ret
|
35 | |
36 | menue4: |
37 | ; hier menue4 |
38 | ret
|
39 | |
40 | Sprungtabelle: |
41 | .DW menue1 |
42 | .DW menue2 |
43 | .DW menue3 |
44 | .DW menue4 |
PS: ".DW rjmp ..." gibt es grundsätzlich nicht!
.dw rjmp ... Gibt's eigentlich schon, dann hättest du im Register einfach das Byte, das den Befehl "rjmp" repräsentiert, oder?
> .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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.