Hallo zusammen! Ich müsste für ein AVR-Flash-Pages-Programmier-Programm die Anzahl Pages ermitteln. Dafür muss ich eine 16-Bit-Zahl (Programmgröße) durch eine 8-Bit-Zahl (32 Page-Bytes) teilen. Dieser Mikrocontroller unterstützt leider keine 16-Bit-Division. Zu meinem Entsetzen musste ich feststellen dass eine 16-Bit-Division in Assembler sehr kompliziert ist und möglicherweise mein mathematisches Verständnis übersteigt. Ist es wirklich nötig ein umfangreiches Programm mit Schiebereien und Schleifen mit diversen Registern zu verwenden ? Dummerweise scheine ich die Funktion dieses Programms nicht zu verstehen sodass ich wohl Fehler nicht erkennen werde...
Durch die Konstante 32 zu teilen ist ziemlich einfach: Ergebnis = Zahl >> 5 Den Rest ermittelst Du mit: Rest = Zahl & 0x1F Viele Grüße, Stefan
Wenn du nur durch eine Zweier-Potenz teilen musst, reicht ja shiften. Ansonsten: Gerade für den 8051 müsste man doch Libraries ohne Ende finden können, die frei benutzbar sind.
Hallo, spätestens hier solltest Du den Einsatz einer vernünftigen Programmiersprache in Betracht ziehen, in C51 gibt es sicherlich solch eine einfache Division. Üblicherweise schreibt kein effizient arbeitender Programmierer seine Divisionen selbst sondern er setzt fertige Bibliotheken ein. So was gab es früher (als ich noch mit dem 8031 gespielt habe) als Laufzeitbibliotheken oder als Makrobibliotheken. Gruß, Michael
Die Pages sind doch 2^n groß, d.h. nach rechts Schieben reicht. So kompliziert ist 16Bit DIV nicht, kann ich ja mal raussuchen.
Entschuldigung, es muss eine 16-Bit-Zahl durch 64 dividiert werden, da eine Page 32 Wörter (=64 Byte) hat. Also soll ich wohl eine gegebene 16-Bit-Zahl 6 mal nach rechts schieben ? Es wird nichts links wieder reingeschoben nehme ich an. Was rechts rausgeschoben wird das lasse ich einfach weg ? Ich benötige sowieso nur das Ergebnis das vor dem Komma steht, das inkrementiere ich um 1 und habe damit den Schleifenzähler-Startwert für die Page-Programmier-Schleife. Und ich bin gerade in purem Assembler unterwegs, eine Hochsprache kommt nicht in Frage.
Warum um 1 inkrementieren? Wenn Du korrekt runden willst, d.h. angefangene Pages sollen mitgezählt werden, musst Du VOR der Division die Pagegröße -1 zum Ausgangswert hinzuaddieren, in Deinem Fall dann also den Wert 63. Natürlich eine 16 bit addition. Anzahl_Pages = (Größe+63)>>6 Was links reingeschoben wird hängt von der Operation ab. Kenne den 8051 nicht, aber auf anderen CPUs gibt es genau zwei verschiedene Operationen: SHIFT RIGHT: Schiebt die Bits eins nach rechts, das oberste Bit wird auf 0 gesetzt ROTATE RIGHT: Schiebt die Bits eins nach rechts, das oberste Bit wird aus einem der CPU-Flags gefüllt (z.B. Carry), danach landet das rechts rausgeschobene bit in diesem Flag (analog dazu gibt es die gleichen Befehle für LEFT)
@ Gurbea Finde ich echt positiv von Dir, dass Du Deine Lehrerallüren hier rausläasst und nicht in der Schule an unseren Kindern.
Markus M. schrieb: > Warum um 1 inkrementieren? > > Wenn Du korrekt runden willst, d.h. angefangene Pages sollen mitgezählt > werden, musst Du VOR der Division die Pagegröße -1 zum Ausgangswert > hinzuaddieren, in Deinem Fall dann also den Wert 63. Natürlich eine 16 > bit addition. > > Anzahl_Pages = (Größe+63)>>6 Hä? Beides liefert doch das gleiche Ergebnis! Wenn der Programmcode 15 Bytes hat, ist nach dem Schieben das Ergebnis 0 aber es muß eine Page (+1) Programmiert werden. Deine Rechnung mit dem +63 ergibt 78 und nach dem Schieben ebenfalls 1 Page.
Route 6. schrieb: > Hä? Beides liefert doch das gleiche Ergebnis! Bei 64 Bytes: (64+63)/64 = 1 64/64 + 1 = 2
Route 6. schrieb: > Hä? Beides liefert doch das gleiche Ergebnis! Nicht ganz. Bei einer durch 64 teilbaren Programmgröße ergibt die Berechnung von Markus die richtige Pageanzahl, bei dem +1 Increment dagegen eine Page zuviel. Beispiel: 128 Byte Programmgröße (128 + 63) >> 6 = 191 >> 6 = 2 Dagegen: (128 >> 6) + 1 = 3 Bei nicht durch 64 ganzzahlig teilbaren Programmgrößen ergibt sich dagegen dasselbe Ergebnis. Viele Grüße, Stefan
OK überzeugt! Auch bei Null gibt das +1 kein richtiges Ergebnis.
:
Bearbeitet durch User
Peter D. schrieb: > Anbei mal die 16Bit Division. Peter war schneller (aber ich mußte auch erst mal wieder alte Sourcen durchforsten und ein Setup für MCS-51 machen, weil auf meinem Rechner kein MCS-51 Assembler mehr installiert war). Und: natürlich ist Peters Version wieder kürzer und deswegen poste ich meine nicht. Abgesehen davon, dass beim Problem des TO ein Ergebnis mit Schiebeoperationen besser zustande kommt ! ----------------------- Btw: Daraus soll ein MCS-51 basierender Flasher für AVR Controller herausspringen ?
Ihr habt recht: bei 64/128 usw. kommt das +1 zu einem falschen Ergebnis. Diese +1-Methode funktioniert nur wenn ein Nachkommarest existiert. Das heisst ich muss wohl wirklich erst 63 zur 16-Bit-Zahl addieren. Danke euch für die Korrektur! Es ist kein AVR-Flasher für ein MCS-51-Projekt sondern einer für ein 80c32er Bastelcomputer: Beitrag "Blechdosen-8-Bit-Rechner"
Ich sehe gerade ein mögliches Problem bei der Addition von 63 zum 16-Bit-Wert: Das sind doch die rechtesten 6 Bit, die da gesetzt werden. Aber diese werden doch dann beim 6 mal rechtsschieben einfach rausgeschoben. Ich brauche wohl eine andere Logik, um den Schleifenzähler richtig mit der Anzahl Pages zu laden (angefangene Pages sollen aufgerundet werden). Die 6-mal-rechtsschieben-Methode sollte dabei verwendet werden, also keine volle 16-durch-8-Division mit allem Schnickschnack.
H-G S. schrieb: > Das sind doch die rechtesten 6 Bit, die da gesetzt werden. Aber diese > werden doch dann beim 6 mal rechtsschieben einfach rausgeschoben. Es gibt aber einen eventuellen Ueberlauf in Bit No7.
Helmut L. schrieb: > H-G S. schrieb: >> Das sind doch die rechtesten 6 Bit, die da gesetzt werden. Aber diese >> werden doch dann beim 6 mal rechtsschieben einfach rausgeschoben. > > Es gibt aber einen eventuellen Ueberlauf in Bit No7. Wenn ich zu 64 die Zahl 63 addiere gibt es keinen Überlauf. Nach 6 mal rechtsschieben kommt 1 heraus. Wenn ich zB. zu 42 die Zahl 63 addiere kommt etwas größeres als 64 heraus (aber kleiner als 128), also kommt nach 6 mal rechtsschieben auch 1 heraus. Wenn ich zu 128 die Zahl 63 addiere und 6 mal rechtsschiebe kommt 2 heraus. Bei 129 kommt 3 heraus. Das klingt ja als wäre es in Ordnung :-)
Markus M. schrieb: > Kenne den 8051 > nicht, aber auf anderen CPUs gibt es genau zwei verschiedene > Operationen: Eigentlich 4. > SHIFT RIGHT: Schiebt die Bits eins nach rechts, das oberste Bit wird auf > 0 gesetzt Das ist das "logische" shiften. Es gibt auch das "arithmetische" shiften wobei das oberste Bit sein Wert behält: 0010.1000 --> 0001.0100 1010.1000 --> 1101.0100 > ROTATE RIGHT: Schiebt die Bits eins nach rechts, das oberste Bit wird > aus einem der CPU-Flags gefüllt (z.B. Carry), danach landet das rechts > rausgeschobene bit in diesem Flag ...und das unterste Bit landet in den Flag. Auch hier gibt's noch die Variante wobei die Bits nur innerhalb vom Register durchgeschoben werden: [b7 b6 b5 ... b1 b0] --> [b0 b7 b6 b5 ... b1] Auf dem Z80 sind das die Operationen SRA (shift right arithmatic), SRL (shift right Logical), RR (rotate right) und RRC (rotate right through Carry)
Ich werde es schon schaffen erst 63 zu addieren und dann 6 Stellen nach rechts zu schieben! Wenn nicht wird halt wieder eine Woche Fehler gesucht - wie bei dem grausamen letzten Unterprogramm für den Blechdosenrechner :-) Es war immer so aufbauend wenn man einen potentiellen Fehler fand - das weckte Hoffnung!
:
Bearbeitet durch User
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.