Forum: Mikrocontroller und Digitale Elektronik atmega 8535 icall


von anfänger0815 (Gast)


Lesenswert?

Hallo Forum, habe ein kleines Problem. Folgendes Programm:

lpm tmp1,z+
lpm tmp2,z+
push zl
push zh
mov zl,tmp1
mov zh,tmp2
icall
pop zh
popzl
ret

Ich hab eine Tabelle in der Sprungadressen zu verschiedenen 
Unterprogrammen gespeichert sind. Ich lese also so eine Adresse mit lpm 
nach tmp1(R16) und tmp2(R17) aus. Danach bringe ich zl und zh auf den 
Stapel um diesen zu retten. Danach speichere ich tmp1/2 nach zl/zh. Wenn 
ich icall aufrufe springt dieser aber nich zu der durch das Z-Register 
adressierten Adresse sonder zu Adresse 9 im Programmspeicher. Kann mir 
jemand sagen warum?

von der alte Hanns (Gast)


Lesenswert?

Das wird wohl daran liegen, dass tatsächlich '9' drinsteht.
Wie sieht denn die Sprungtabelle aus, und wie wird ZH & ZL geladen?

von anfänger0815 (Gast)


Lesenswert?

Ich habe, sagen wir z.B., das Unterprogramm "Test".
Im Programmspeicher steht dann:
test:
  Befehl 1
  Befehl 2
      .

      .
  Befehl X

In die Tabelle las ich dann folgendes durch den Assembler ein schreiben:

.db low(test),high(test),12,0

danach lasse ich die zwei Speichstellen durch die ersten zwei 
lpm-Befehle auslesen. Siehe oben

von der alte Hanns (Gast)


Lesenswert?

Okay. Und wie wird nun ZH & ZL gesetzt, damit z auf die Tabelle zeigt?

von anfänger0815 (Gast)


Lesenswert?

Naja,

lpm tmp1,z+
lpm tmp2,z+
push zl
push zh
mov zl,tmp1
mov zh,tmp2

durch die zwei MOV-Befehle

von der alte Hanns (Gast)


Lesenswert?

Sie müssen doch vor dem lpm erstmal ZH & ZL geladen haben, und zwar mit 
der Adresse der Tabelle.

von der alte Hanns (Gast)


Lesenswert?

so irgendwie:

 ldi ZH,high(Tabelle*2)
 ldi ZL,low(Tabelle*2)
 lpm ...



Tabelle:
.db low(test),high(test),12,0

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Muss man die Adressen nicht noch durch 2 teilen?

von anfänger0815 (Gast)


Lesenswert?

Jetzt weiß ich was gemeint ist. Ich lade den Anfang der Tabelle in das 
Z-Register und addiere die Sprunweite die benötigt wird dazu und dann 
gehts oben weiter. Das mit der Sprungweite usw. funktioniert im 
Simulator. In den Z-Rgistern steht ja auch dann die richtige Adresse, 
nur sobald der Simulator zum icall-Befehl kommt springt er falsch, also 
immer zur Adresse 9, obwohl zuvor die richtige Adresse im Register 
gestanden hat. Er überträgt also nicht den Z-Registerinhalt sondern 
einen Wert den der Simulator sich aus den Fingnägle saugt.

von der alte Hanns (Gast)


Lesenswert?

Haben Sie das Problem nur in der virtuellen Welt, sprich im Simulator? 
Und wenn ja, in welchem?

Bei mir läuft real, es wird 'B' ausgegeben:

  ldi  ZH,high(Tabelle*2)
  ldi  ZL,low(Tabelle*2)
  adiw  ZL,2
  lpm  tmp0,z+
  lpm  tmp1,z+
  movw  ZL,tmp0
  icall
  rjmp  pc

Tabelle:
.db  low(Test1),high(Test1)
.db  low(Test2),high(Test2)
.db  low(Test3),high(Test3)

Test1:
  ldi  tmp0,'A'
  rcall  disp_byte
  ret

Test2:
  ldi  tmp0,'B'
  rcall  disp_byte
  ret

Test3:
  ldi  tmp0,'C'
  rcall  disp_byte
  ret

von der alte Hanns (Gast)


Lesenswert?

Auf einem ATmega1284P, sollte ich korrekterweise hinzufügen, ich habe 
keinen 8535.

von anfänger0815 (Gast)


Lesenswert?

Hallo, tschuldigung für meine späte Antwort. Ich denke ich habe den 
Fehler gefunden. Manchmal sollte man doch nichts ausschließen. Ich hab 
Ihr Programm abgetippt, welches auch im Simu funktioniert. Danach länger 
auf die Suche gegangen. Habe mir selber ins Bein geschossen. Ich greife 
gleichzeitig noch auf den Programmspeicher zu um Daten ins Ram 
einzulesen, diese Adressen muß man mit z.B. low(test*2), high(test*2) 
kodieren. Anders bei den Sprungadressen, diese werden nicht mit *2 
kodiert. Aber ich habe es trotzdem gemacht und habe es Tagen übersehen. 
Gott wie blind kann man sein. Ich danke für die schnelle Antwort, die 
mir zum Schluß den richtigen Stups gegeben hat.

von der alte Hanns (Gast)


Lesenswert?

Und ich war schon gespannt, ob Sie nicht über das

  movw  ZL,tmp0

gestolpert sind, das verlangt nämlich, was ich versehentlich 
unterschlug:

.def  tmp0  = r16
.def  tmp1  = r17

o.ä.

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
Noch kein Account? Hier anmelden.