[avrassembler] Division Problem mit Rest

Gast #2668974
Lesenswert?

Hi,

wie der Titel schon beschreibt, versuche ich momentan als total blutiger 
Anfänger einen Dividierer zu schreiben.

Ich habe vier Register r16, r17, r18 und r19. In diesen Registern habe 
ich eine einzige Zahl gespeichert, die durch 12 dividiert werden soll. 
Das höchstwertigste Register ist r19.

Leider konnte ich bis jetzt nur Schleifen programmieren die die 
einzelnen Register dividiert haben bis eine Zahl über geblieben ist, die 
kleiner war als der Divisor.

Mein Problem ist nun, dass diese Zahl ignoriert wird, wodurch mein 
Ergebnis zu ungenau wird. Z.B.: Ist in r19 die Zahl 11 gespeichert und 
wird durch 12 dividiert, kommt 0 raus und die 11 wird weggeschmissen.

Wie kann man das nun lösen, dass die 11 weiter verwendet wird?


Vielen Dank für deine Hilfe schon im voraus,

Fabi
Gast #2669016
Lesenswert?

Hi

>Leider konnte ich bis jetzt nur Schleifen programmieren die die
>einzelnen Register dividiert haben bis eine Zahl über geblieben ist, die
>kleiner war als der Divisor.

Willst du jetzt aufrunden? Wenn ja, dann vergleiche den Rest einfach mit 
6.

MfG Spess
#2669018
Lesenswert?

mein Problem ergibt sich durch folgendes:

Ich habe meine clock0 in einem attiny 2313, jedesmall wenn es einen 
clockoverflow gibt, wird r16 incrementiert. Wenn r16 voll ist wird r17 
danach r18 und dann r19 erhöht.

Irgendwann kommt dann ein Interrupt, was die clock0 anhält.

Jetzt will ich nach 1/12 der gemessenen Zeit die 1. LED anschalten, nach 
einem weiteren 12tel will ich die 2. LED anschalten und so weiter.

Dafür brauch ich die Division.

Aber mit deine Idee mit Register nach Links verschieben ist eine gute 
Idee, werde ich mal weiter nachverfolgen. Allerdings problematisch, wenn 
ich im Register 0xFF geladen habe und das dann verschiebe, weil ich dann 
die obersten 1er verliere.
#2669193
Lesenswert?

Brauchst du wirklich 32bit Auflösung für die zu messende Zeit? In 
welchem Bereich (von - bis) liegen denn die zu messenden Zeiten?

Für 32bit ist wohl die entsprechende Dividier-Routine von elm-chan die 
einfachste Lösung:

http://elm-chan.org/docs/avrlib/div32.txt

Die könnte man sicher noch kürzen, da dein Divisor ja in ein einzelnes 
8bit-Register passt.

Wenn es nicht absolut genau sein muss, könnte man auch mit 21 
multiplizieren und dann das niederwertigste Register verwerfen. (x * 21 
/ 256 = x / 12,19...)
#2669470
Lesenswert?

wie kommst du auf die zahl 21?

Wie groß die zeit min und max ist, hab ich mir noch nicht so viele 
Gedanken gemacht. Aber ich habe festgestellt, wenn ich einfach so 11 / 
12 teile und den rest wegschmeis, bleibt mir als ergebnis 0 über. Im 
"obersten / höchstwertigsten" Register ist das verdammt viel Zeit die 
ich wegwerfe, wodurch meine LED's zu früh angehen.
#2669545
Lesenswert?

ich habe mir mal die vorgeschlagene 32-bit-divison angeschaut.

Leider bin ich noch blutiger anfänger (mit maximal 30 h "erfahrung")
und kann mit meinem Wissen diese Schleife noch nicht richtig deuten.

Ich habe mir erlaubt meine Kommentare noch weiter rechts hinzuschreiben.
Die bezifferten Kommentare sind fragen meinerseits, bzw versuchte 
Interpretationen, bei denen ich mein Wissen hingeschrieben habe, bei 
denen ich aber glaube, dass sie nicht richtig sind

Die weiter rechts sind einfach nur Kommentare von mir, um den 
Programmcode soweit möglich zu verstehen.
Bitte trotzdem wieder durchlesen und korrigieren.


Bitte helft mir das zu verstehen.
Und vielen dank für eure Hilfe bis hier hin.

fabi
#2669608
Lesenswert?

Fabian Scheidig schrieb:

> Wie groß die zeit min und max ist, hab ich mir noch nicht so viele
> Gedanken gemacht. Aber ich habe festgestellt, wenn ich einfach so 11 /
> 12 teile und den rest wegschmeis, bleibt mir als ergebnis 0 über. Im
> "obersten / höchstwertigsten" Register ist das verdammt viel Zeit die
> ich wegwerfe, wodurch meine LED's zu früh angehen.

Das kommt halt auf die Zeit drauf an.
Wenn deine Register die Zeit in Millisekunden zählen, dann sind 11 
Millisekunden nicht so wahnsinnig viel Zeit.


Im übrigen. Ja natürlich. Das Problem hast du immer. Mathematiker nennen 
das das Schubladenargument: Es ist nicht möglich n Socken in m 
Schubladen zu verstauen, so dass in allen Schubladen gleich viele Socken 
drinnen sind. Es sei denn n ist ein ganzzahliges Vielfaches von m.

So ist das nun mal, wenn man mit ganzen Zahlen hantiert. Da musst du dir 
was einfallen lassen, wie du die Situation handhaben willst.
#2669632
Lesenswert?

soweit, ich die divisions-schleife verstanden hab, ist die einfach nur 
genial und ich werde sie verwenden.

Mir ist klar, dass ich den allerletzten rest nicht verwenden kann, aber 
ich will halt den rest vom höchstwertigsten Register noch im 
2.höchstwertigsten verwenden, weil sonst einfach irre viel zeit weg 
geht.

Ich habs ausgerechnet, was für zeiten ich hab. Meine min:0,17 sec. und 
meine max: 1,7 sec.

Jetzt muss ich sie nur noch bis zum ende durch verstehen und dann für 
mich modifizieren. Vielen Dank, weitere Proleme kommen sicher bald, 
vielen Dank noch mal an alle


p.s. wo finde ich solche Schleifen?

fab
#2669991
Lesenswert?

Jobst M. schrieb:
> Du kannst Deine 32-Bit Zahl mit 357913941 (auch 32 Bit) multiplizieren.
> Von dem 64-Bit Ergebnis schmeisst Du die unteren 32 Bit einfach weg.
> Evtl. verwendest Du von den unteren 32 Bit das MSB zum Runden.

Auch wenn ich nicht der TO bin, interessiert mich dieses Thema auch 
gerade ziemlich und würde gern mal den Sinn hinter deinem geschriebenen 
verstehen wollen. Also wie kommst du auf die 357913941?


MfG Dennis
#2670013
Lesenswert?

Jobst M. schrieb:
> Dennis H. schrieb:
>> wie kommst du auf die 357913941?
>
> 2^32 / 12
>
> Du Multiplizierst also mit 1/12 und schmeisst die Nachkommastellen weg.
>
>
> Gruß
>
> Jobst

Das leuchtet sogar mir ein, das ist ja mal ein richtig interessanter 
Ansatz.

Aber du lässt da sozusagen die Nachkommastellen einfach unter den Tisch 
fallen? Also wenn ich 2^32/12 rechne, habe ich ja nach dem Komma noch 
.33333..33 stehen.

Vielen Dank für die gute Erklärung


MfG Dennis
#2670035
Lesenswert?

Jobst M. schrieb:
> Eine genauere Auflösung als ein LSB hast Du eben nicht. Egal, ob Du
> teilst oder multiplizierst.

Stimmt schon, und bei einer 32Bit Zahl sollte das nicht so ganz ins 
Gewicht fallen. Ich glaube, in den seltensten Fällen benötigt man so 
genaue Berechnungen, schwierig wirds bloß, wenn man mit dem errechneten 
Wert noch lange weiter rechnet, weil sich dann der Fehler schnell 
potenziert. Aber trotzdem vielen Dank für die ehrlich gesagt sehr 
elegante Lösung, die gefällt mir richtig gut.


MfG Dennis
Gast #2670852
Lesenswert?

Auch von mir vielen dank an alle, die mir weiter geholfen haben.

Mein Problem war, dass ich vier Register durch 12 dividiert hatte und 
somit mir 4 mal ein Rest zwischen 0 und 11 übergeblieben ist. Wobei ich 
davon die "oberen oder höherwertigeren" Reste hätte noch verwenden 
können. Ich wusste aber nicht wie.
Mit der 32-Bit-Division, die oben als Textanhang dabei ist, hat sich 
mein problem gelöst und der letzte Rest kann einfach verfallen.

Vielen Dank noch einmal an alle,


fabi

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren