Forum: Mikrocontroller und Digitale Elektronik 16 Bit Division auf 8051


von H-G S. (haenschen)


Lesenswert?

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

von Stefan K. (stefan64)


Lesenswert?

Durch die Konstante 32 zu teilen ist ziemlich einfach:

Ergebnis = Zahl >> 5

Den Rest ermittelst Du mit:

Rest = Zahl & 0x1F


Viele Grüße, Stefan

von Detlev T. (detlevt)


Lesenswert?

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.

von Michael A. (micha54)


Lesenswert?

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

von Peter D. (peda)


Lesenswert?

Die Pages sind doch 2^n groß, d.h. nach rechts Schieben reicht.

So kompliziert ist 16Bit DIV nicht, kann ich ja mal raussuchen.

von hänschen (Gast)


Lesenswert?

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.

von Gurbea (Gast)


Lesenswert?

@ hänschen

Hat dir deine Mutti nicht gesagt, dass plenken unfein ist.

von Markus M. (adrock)


Lesenswert?

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)

von Stefan K. (stefan64)


Lesenswert?

@ Gurbea
Finde ich echt positiv von Dir, dass Du Deine Lehrerallüren hier 
rausläasst und nicht in der Schule an unseren Kindern.

von Peter D. (peda)


Angehängte Dateien:

Lesenswert?

Anbei mal die 16Bit Division.

von Route_66 H. (route_66)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

Route 6. schrieb:
> Hä? Beides liefert doch das gleiche Ergebnis!

Bei 64 Bytes:
  (64+63)/64 = 1
  64/64 + 1 = 2

von Stefan K. (stefan64)


Lesenswert?

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

von Route_66 H. (route_66)


Lesenswert?

OK überzeugt!
Auch bei Null gibt das +1 kein richtiges Ergebnis.

: Bearbeitet durch User
von Ralph S. (jjflash)


Lesenswert?

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 ?

von hänschen (Gast)


Lesenswert?

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"

von H-G S. (haenschen)


Lesenswert?

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.

von Helmut L. (helmi1)


Lesenswert?

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.

von H-G S. (haenschen)


Lesenswert?

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  :-)

von Eric B. (beric)


Lesenswert?

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)

von H-G S. (haenschen)


Lesenswert?

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