Sprungtabelle

Gast #279914
Lesenswert?

Hab folgendes Problem:

Abhängig von einem BYte soll ein entsprechendes Programm ausgeführt
werden:
Bisher mache ich das so:
byte --> r16

cpi r16,0x00
breq prg0jmp
cpi r16,0x01
breq prg1jmp
...

prg0jmp:
rjmp prog0
prg1jmp:
rjmp prog1
...
prog0:
 //code

prog1:
//code

Das muss aber viel viel einfacher gehen mit ijmp oder so etwas.
Hat da jemand ne elegante Lösung für mich?
Gast #279916
Lesenswert?

Ja, wenn du die absolute Adresse von deiner Sprungtabelle im Register Z
hast (
  ldi  ZL,low(prg0jmp*2)    ; low
  ldi  ZH,high(prg0jmp*2)    ; high
), dann geht es bisschen einfacher:

  add zl, r16
  brcc no_carry
  inc zh
no_carry:
  ijmp
Gast #279917
Lesenswert?

JA der ist zu lang. Und mit deinem Vorschlag kann ich zunächst auch nur
8 Programme ansteuern. ODER ? Dachte an sowas wie

(i)jmp label + r16 * (länge vom rjmp)

Label:
Rjmp prog0
Rjmp prog1
Rjmp prog2
Rjmp prog3
Rjmp prog4

nur ich würde ganz gerne einer multiplikation aus dem weg gehen.
#279920
Lesenswert?

Oder so:

menujump:               ;Menüpunktaufruf
 ldi zl,low(menujmp)        ;Zeiger auf Sprungtabelle
 ldi zh,high(menujmp)
 add zl,mp                  ;Menüpunkt
 adc zh,null                ;dazu
 ijmp                       ;Menüpunkt aufrufen


menujmp:                ;Menü-Sprungtabelle
 rjmp mp_00
 rjmp mp_01
 rjmp mp_02
 ...

mp_00:                  ;Hauptmenü, Ebene Edit
 sbrc flags,v24rx           ;PC-Verbindung aktiv? nein...
 rcall usart_aus            ;ja, deaktivieren...
 mov ztl,ff                 ;Uhr auf
 mov zth,ff                 ;-1
 cbr flags,1<<aktiv         ;und aus
 rcall testmax              ;Anzahl Schüsse ermitteln
 rjmp editliste             ;Liste aufbauen und Menütexte anzeigen


Alles im Zusammenhang hier zu sehen:
http://www.hanneslux.de/avr/zuenduhr/ZndUhr01.asm

...
Gast #279921
Lesenswert?

DRei fragen an Aleksej:
a)
wofür die multiplikation mit zwei?
b)
reicht es den Wert von Z einfach mit meinem Inhalt von r16 zu erhöhen?
oder muss ich die länge eines rjmp-Befehl noch multiplizieren
c)
meine tabelle sähe dann so aus?:
prg0jmp:
rjmp prog0
rjmp prog1
rjmp prog2
Gast #279926
Lesenswert?

Das geht auch einfacher mit IJmp oder ICall.
Aufpassen: diese Befehle können manche AVR Controller nicht, also
besser vorher im Datenblatt nachschlagen.

Im Prinzip funktioniert das so (habs die Syntax nicht ausprobiert):

; Sprungtabelle in Z-Pointer laden
   LDI ZL, low(Sprungtabelle)
   LDI ZH, high(Sprungtabelle)
;hier musste nochmals nachschlagen das Prinzip sollte klar sein, der
Assembler soll das low byte der Adresse der Sprungtabelle in ZL laden
dito für ZH, die Syntax sieht bestimmt ein bischen anders aus.

; Nachdem jeder Eintrag in der Sprungtabelle 2 byte gross ist musst du
den Index-Wert in R16 noch mit 2 multiplizieren das enspricht einem
linksshift.
   LSL R16
;Nun index auf Z draufaddieren (auf überlauf des lowbyte achten!)
; daher vorher ein Register mit 0 laden
   SUB R0,R0      ; R0 wird mit 0 geladen
   ADD ZL, R16    ; R16 wird auf ZL addiert und C ggfs. gesetzt
   ADC ZH, R0     ; ZH = ZH + 0 + C, ggfs carry draufaddieren. zum
Registersparen geht das auch ohne R0 mit Abfrage des Carrybits und
einem eventuellen INC des ZH.

; Nun der eingentliche Sprung
   Ijmp
; Hier nun die Sprungtabelle
Srungtabelle:
   rjmp prog0
   rjmp prog1
   rjmp prog2
   ....

ciao
Remo

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren