Forum: Mikrocontroller und Digitale Elektronik Assembler: absolute Adresse einer Marke


von Eckhard R. (eckhard03)


Lesenswert?

Hallo,
ich habe einen ADuC831 mit Assembler-Programm (8051), wo noch was 
zusätzliches rein soll. Dafür wäre es gut. von der Interruptroutine INT0 
nicht normal sondern immer auf eine bestimmte Marke zurückzuspringen.

Meine Idee: 2xpoppen(ich meine natürlich entkellern) und dann meine 
Wunschadresse pushen. Dazu müßte ich die absolute Adresse, die ja erst 
beim übersetzen entsteht, herbeizaubern.

Hat jemand eine Idee? oder vielleicht eine Alternative?

von holger (Gast)


Lesenswert?

Auch wenn ich dein Vorhaben für keine gute Idee halte ;) :

Kennt dein Assembler kein "org"?

von Hc Z. (mizch)


Lesenswert?

Wenn die Zieladresse als Label vorliegt, sollte es kein Problem sein, 
label&0xff sowie Label>>8 zu pushen.  Manche Assemler bieten dafür auch 
Makros wie hi() und lo() an, und das dann einzukell(n)ern, um in Deinem 
eigenwilligen Sprachgebrauch zu bleiben.

von Hc Z. (mizch)


Lesenswert?

Aber vielleicht schilderst Du lieber das Problem selbst, anstelle nach 
Hilfe bei einer vorgegebenen Lösung zu suchen, die doch ziemlich seltsam 
anmutet.

von holger (Gast)


Lesenswert?

>Meine Idee: 2xpoppen(ich meine natürlich entkellern) und dann meine
>Wunschadresse pushen.

Da hab ich doch glatt was vergessen.
Wer entkellert eigentlich den Stack wenn der
Interrupt in einer Routine auftritt die eigentlich
per return verlassen werden müsste?

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

holger schrieb:
> Da hab ich doch glatt was vergessen.
> Wer entkellert eigentlich den Stack wenn der
> Interrupt in einer Routine auftritt die eigentlich
> per return verlassen werden müsste?
Der Kellner natürlich!

In so einem fall könnte man einfach den Stackpointer wieder auf Anfang 
setzen, da eh alles wofür der Stack brauchbar wäre ab dem Moment 
verloren ist.

von holger (Gast)


Lesenswert?

>Der Kellner natürlich!

He, he;)

>In so einem fall könnte man einfach den Stackpointer wieder auf Anfang
>setzen, da eh alles wofür der Stack brauchbar wäre ab dem Moment
>verloren ist.

Wenn eventuelle unterbrochene Berechnungen in Unterprogrammen
dann möglicherweise falsche Werte liefern ist das auch nicht so schön.

von eckhard03 (Gast)


Lesenswert?

der mir über die Schulter schauende Kollege hatte halt bei "meine Idee: 
2x poppen" gewisse Kommentare parat. Und ganz früher - ich bin nicht 
mehr der Jüngste - nannte man einen Stack eben gut deutsch 
Kellerspeicher.

Stack auf Anfang finde ich ganz plausibel: Alles angefangene kann weg.

Die Operation "label&0xff" bringe ich allerdings mit meinen verfügbaren 
Assembler-Kenntnissen nicht zusammen. Das sieht irgendwie nach 16 Bit 
aus - und ich habe doch nur 8 - oder?

von (prx) A. K. (prx)


Lesenswert?

eckhard03 schrieb:

> nannte man einen Stack eben gut deutsch Kellerspeicher.

War das nicht Siemens-Spezialsprache? Ich erinnere mich an beides, aber 
Stapelspeicher war öfter zu hören.

Ist ausserdem Blödsinn, denn wer seinen Vorratskeller so stapelt, der 
darf sich nicht wundern wenn viel vergammelt.

von holger (Gast)


Lesenswert?

>Stack auf Anfang finde ich ganz plausibel: Alles angefangene kann weg.

Dann wundere dich nicht über die Nebenwirkungen.
Mach doch einfach einen Jump auf den Resetvektor.
Dann ist alles angefangene einigermassen weg.
Wenn auch nicht alles.

>Die Operation "label&0xff" bringe ich allerdings mit meinen verfügbaren
>Assembler-Kenntnissen nicht zusammen. Das sieht irgendwie nach 16 Bit
>aus - und ich habe doch nur 8 - oder?

Wenn dein uC nur 256 Byte Codespeicher hat, ja.
Falls nicht solltest du dich mal näher über deinen uC informieren
bevor du so einen Gurkenkram planst.

von eckhard03 (Gast)


Lesenswert?

'Tschuldigung. Jetzt nochmal für Holger: Mit "8 bit" meinte ich 
natürlich nicht den Adressraum sondern die Verarbeitungsbreite der 
Befehle.

von Hc Z. (mizch)


Lesenswert?

> Die Operation "label&0xff" bringe ich allerdings mit meinen verfügbaren
> Assembler-Kenntnissen nicht zusammen. Das sieht irgendwie nach 16 Bit
> aus - und ich habe doch nur 8 - oder?

Das Label wird doch wohl 16 Bit sein.  Obige Konstruktion macht zusammen 
mit der anderen gezeigten aus dem Label zwei 8-Bit-Happen, die Du bequem 
in Deinem Keller stapeln kannst.  Zusammen ergeben sie die gewünschte 
16-Bit-Adresse zum entstapeln.

von eckhard03 (Gast)


Lesenswert?

Danke für Eure Geduld.

Mein Problem ist aber eben gerade die 16-bit-Breite. Im 8051-Assembler 
gibt es kein 16-Bit-Arbeitsregister und damit auch keinen Befehl, der 
zwei 16-Bit-Werte verknüpft (marke&maske).

Hier noch die eigentliche Aufgabe:
Der µC steuert/regelt eine analoge Prozessgröße folgendermaßen: Bei 
Interrupt beginnt eine Rampenfunktion mit vorgegebenen Anstieg - bis 
erreichen eines vorgegebenen Endwertes.
Dann wird dieser als Konstantwert nachgeregelt (Messen, 
Regelabweichung-->Stellwertkorrektur).

Zu beliebigen Zeitpunkten kommt neuer Interrupt (während der Rampe oder 
dem Konstant-Plateau). Dann beginnt eine neue Rampe bis neuem Endwert, 
der wieder nachgeregelt wird.

Die Endwerte variieren von Null bis Vdd. Die Anstiegszeiten von 
10...300ms und die Interrupt-Abstände von 4...800ms. Alles soll in 
willkürlicher Kombination möglich sein.

von Klaus (Gast)


Lesenswert?

Hört sich für mich so an, als ob sich das ohne Probleme sauber durch 
eine State-Maschine lösen lässt, ganz ohne schmutzige 
Stackvergewaltigungsmaßnahmen.

von Anton (Gast)


Lesenswert?

Wer den Stack vergewaltigt ist selber schuld wenns schief geht.
Warum nich nicht in dem besagten Int ein Flag setzen, der Aduc hat eine 
ganzen Menge direkt anspechbare, und dann in der Main-Loop abfragen.
Sauber, einfach und ohne obskure Stackmanipulation!

Und das 16 Bit-Label auf den Stack bekommen:

ldi acc,low(label)
push acc
ldi acc,high(label)
push acc

Achtung ggf. muss die Reihenfplge L-H vertaucscht werden!

Aber besser KEINE Stack-Manipulation (brrr, Kopf-schüttel)

von Karl H. (kbuchegg)


Lesenswert?

Sehe das wie Klaus.
Das alles klingt für mich nach einem verkorkstem Ansatz.

Wenn die Regelung ständig mitläuft, dann kann man auch Rampen dadurch 
realisieren, dass man den Sollwert für die Regelung verändert. Das kann 
ganz einfach gehen, indem man in regelmässigen Abständen den Sollwert 
mit einem Vorgabewert vergleicht. Ist der Sollwert kleiner als die 
Vorgabe, dann wird der Sollwert um einen bestimmten Anteil erhöht, ist 
der Sollwert größer als die Vorgabe, wird der Sollwert um einen 
konstanten Anteil verringert.

Auf diese Art kann man den Vorgabewert ändern wann immer man will, der 
Sollwert (und damit hoffentlich auch der Istwert durch den PID-Regler) 
wird auf einer Rampe nachgeführt. Und das Ganze funktioniert auch dann, 
wenn die 'Sollwertrampe' gerade nach oben geht und ein neuer Vorgabewert 
eintrifft, der den Sollwert plötzlich auf ganz tief stellt. Die nach 
oben führende 'Rampe' wird sofort abgebrochen und der Sollwert fährt auf 
einer neuen Rampe nach unten.

Durch die Zeitabstände dieser 'regelmässigen Sollwertnachführung' bzw. 
durch die Wahl des Inkrements/Dekrements kann die Steigung der Rampe 
bestimmt werden.

Aber Stackmanipulation wie angedeutet braucht da kein Mensch.

von Hc Z. (mizch)


Lesenswert?

> Mein Problem ist aber eben gerade die 16-bit-Breite. Im 8051-Assembler
> gibt es kein 16-Bit-Arbeitsregister und damit auch keinen Befehl, der
> zwei 16-Bit-Werte verknüpft (marke&maske).

Es ist zwar viele Jahre her, dass ich 8051 gemacht habe, mit der 
Keil-Toolchain.  Aber natürlich konnte dessen Assembler Grundarithmetik. 
Und natürlich brauchst Du dafür kein Register der CPU.  Ich denke, dass 
Du da ein Grundproblem mit dem Verständnis von Assembler hast. 
Assembler-Arithmetik auf einem Label hat mit der CPU, deren 
arithmetischen Befehlen und deren Registern nichts, aber auch wirklich 
gar nichts zu tun.

Abgesehen davon: Ich glaube, dass schon die Grundidee überprüft werden 
soll, wie ich und andere schon schrieben.

von eckhard03 (Gast)


Lesenswert?

OK. Tut mir leid, kein Profi zu sein. Was ich hier habe ist ein 
vorhandenes Programm/Programmierumgebung auf Niveau 8051-Assembler. Da 
gibt's halt keinen Befehl "ldi" - siehe auch 8051-Befehlsliste - und nur 
8-bit breite UND-Verknüpfungen.
Dass mehr Progammiererfahrung für mich dienlicher wäre, weiß ich 
natürlich selber. Bin eben auf der Suche, wo/wie ich was dazulernen 
kann, um das hier zu schaffen.

Das mit den variablen Sollwerten von Karl Heinz geht nicht, denn das 
eigentliche Problem bei dem Regler ist die Trägheit des Prozesses: 
Zeitverzögerung 2.Grades + Totzeit - leider nicht zeitkonstant. D.h. bei 
manchen Einstellungen reagiert derzeit einfach gar nichts. Meine 
eigentliche Aufgabe ist, da noch was sinnvolles rauszuholen. Und da 
wollte ich das Flagsetzen und immer in genügend kurzen Abständen 
abfragen usw. einsparen.

Wenn Ihr Euch alle einig seid, dass man sowas niemals tut, nehm' ich's 
zur Kenntnis. Wäre aber eben schön gewesen.

von Anton (Gast)


Lesenswert?

Stimmt, der asm51 kennt kein ldi, heißt hier
mov. Also ein 16Bit Label wird dann mit
mov acc,low(label)
...
und
mov acc,high(label)
.....
verarbeitet. Konnte schon der Intel-Asm und der Keil asm in den 80-er
Jahren.......

Ein suboptimales Programm, möglichst noch schlecht dokumentiert,
zu ergänzen bzw. zu "verschlimmbessern", ist echt nicht einfach,
manchmal wäre ein "Neuschreiben" schneller und einfacher.

Ich wünsche Dir trotzdem viel Erfolg.

von Hc Z. (mizch)


Lesenswert?

eckhard03 schrieb:
> OK. Tut mir leid, kein Profi zu sein. Was ich hier habe ist ein
> vorhandenes Programm/Programmierumgebung auf Niveau 8051-Assembler. Da
> gibt's halt keinen Befehl "ldi" - siehe auch 8051-Befehlsliste - und nur
> 8-bit breite UND-Verknüpfungen.

Nochmal: Dein Assembler kann Arithmetik, die unabhängig vom Befehlssatz 
der CPU ist, denn sie dient dazu, lokale Berechnungen durchzuführen, 
bevor daraus ein Befehl für die CPU wird.

Das hat nichts damit zu tun, ob irgendwelche CPU-Befehle ldi oder mov 
heißen (was sowieso nur ein syntaktischer, kein semantischer Unterschied 
ist - das Ding heißt anders, tut aber dasselbe).

Es gibt so Dinger, die heißen Manuals.  Da steht drin, welche Arithmetik 
ein Assembler für sich mitbringt, um Dinge zu berechnen, deren 
Rechenergebnis in die CPU-Befehle einfließt, ohne dass deshalb die CPU 
irgendwas zu rechnen hätte.  Da steht drin, wie die Ausdrücke dafür 
auszusehen haben.

Es sollte doch einem Assemblerprogrammierer klar sein, dass die 
(fiktive) Zeile
1
 mov acc,2+(3*13)
eine einfaches Laden des Akkus mit einer Konstanten bewirkt und die 
Ziel-CPU keine Rechnung dabei ausführt, genauso wenig wie der 
Assembler-Ausdruck "label&0xff" etwas mit Registerbreiten zu tun hat.

Ich bin vielleicht etwas zu ungeduldig, aber ich klinke mich jetzt aus.

von eckhard03 (Gast)


Lesenswert?

Also, hier gibt's keinen Progammierer. Ich bin einfach das Mädchen für 
alles uns sehe was ich zu Stande bringe. Und vor vielen Jahren hab ich 
auch schon mal ein Assembler-Programm geschrieben (da gabs noch keine 
µCs).

Ihr habt mir jedenfalls ein ganzes Stück weiter geholfen und dafür 
möchte ich mich bedanken. Und Entschuldigung, für die Nervigkeit.

Eckhard

von Hc Z. (mizch)


Lesenswert?

> Also, hier gibt's keinen Progammierer. Ich bin einfach das Mädchen für
> alles uns sehe was ich zu Stande bringe.

Gut, vielleicht habe ich überreagiert.  Oder Du hättest es früher 
klarstellen können statt dabei zu bleiben, der Assembler könne nicht mit 
16-Bit-Quantitäten rechnen.  Heute war kein besonders guter Tag für 
mich, und Du kannst nichts dafür, belassen wir's dabei.

Ich denke, dass der Assembler auch zum Rechnen mit Labels da ist und die 
Ziel-CPU mit diesen Rechnungen nichts zu tun hat, ist nun klar.  Auch 
klar dürfte sein, dass die Manipulation der Rücksprungadresse im Stack 
nur in sehr seltenen Fällen eine gute Idee ist, die nur mit guten 
Assemblerkenntnissen angegangen werden kann.

von eckhard03 (Gast)


Lesenswert?

sollte überhaupt keine Kritik sein. Ich meinte das ganz ehrlich, mit dem 
Dankeschön und auch mit der Entschuldigung. Bin jetzt echt ein ganzes 
Stück weiter. Der vergewaltigte Stack scheint zu funzen und ist immer 
noch meine Vorzugsversion. Wenn man ihn ständig nullt, kann er zumindest 
nicht überlaufen.

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.