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?
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
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.
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
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.
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.ä.