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?
Das wird wohl daran liegen, dass tatsächlich '9' drinsteht. Wie sieht denn die Sprungtabelle aus, und wie wird ZH & ZL geladen?
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
Naja, lpm tmp1,z+ lpm tmp2,z+ push zl push zh mov zl,tmp1 mov zh,tmp2 durch die zwei MOV-Befehle
Sie müssen doch vor dem lpm erstmal ZH & ZL geladen haben, und zwar mit der Adresse der Tabelle.
so irgendwie: ldi ZH,high(Tabelle*2) ldi ZL,low(Tabelle*2) lpm ... Tabelle: .db low(test),high(test),12,0
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
Auf einem ATmega1284P, sollte ich korrekterweise hinzufügen, ich habe keinen 8535.
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.ä.
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.