Forum: Mikrocontroller und Digitale Elektronik AVR ASM 16 Bit / 180 teilen


von boese (Gast)


Lesenswert?

Mahlzeit,

ich benötige für eine Zeitkritische Geschichte eine Routine (ASM) womit 
ich auf einem ATmega1281 eine 16 Bit Variable durch eine Konstante (in 
diesem Fall 180) teilen kann.

Hat jemand vielleicht etwas Code-Geschnippsel da? Ich glaub mein 
Mathe-Verständnis reicht dafür nicht aus um durch 180 zu teilen (und nur 
Addition, Sub. sowie Div und Mul mit Potenzen von 2 (shift)) zu 
verwenden.

Ich hoffe jemand kann mir auf die Sprünge helfen :)


Viele Grüsse

von Kai G. (runtimeterror)


Lesenswert?

du kannst die 16 Bit Zahl einfach mit 364 multiplizieren und dann die 
obersten 16 Bits des Ergebnisses verwenden.
x / 180 = (x * (65536 / 180)) / 65536 = (x * 364,088888...) >> 16

Je nach geforderter Präzision geht das am Schnellsten.

von Benedikt K. (benedikt)


Lesenswert?

Oder du rechnest:
Ergebnis=Zahl/256+Zahl/512-Zahl/4096 usw.
Geht komplett ohne Multiplikation oder Division, nur durch Schieben. 
Wird aber vermutlich langsamer sein als die Lösung von Kai.

von boese (Gast)


Lesenswert?

Hmmm,

rein von der Idee her schon gut... Nur dann brauch ich wieder 32 Bit 
Variablen, da wird dadd ganze natürlich wieder sehr Komplex :(...

Zumal wenn man nur die High-bytes nimmt, dass das ergebnis wieder nur 8 
Bit ist... und 65535 / 180 = 364 ;)


Viele Grüsse

von Jochen M. (taschenbuch)


Lesenswert?

So wie Kai es beschrieben hat geht es.
Oder als universelle und schnelle Division in Assembler:

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

Jochen Müller

von boese (Gast)


Lesenswert?

Ihr seit top... Jörgs Variante braucht grad mal 20 Takte.... Sowas nenn 
ich doch mal Klasse ;D

Bascom hätte dafür mal locker über das 10-Fache gebraucht....

Vielen Dank an euch!!!!

von boese (Gast)


Lesenswert?

wieso is nu Kais Assembler-Schnippsel weg?

von boese (Gast)


Lesenswert?

Jörgs meinte ich...

von Joerg W. (joergwolfram)


Lesenswert?

Dad * 364 kann man noch vereinfachen, indem man *182 nimmt und dann nach 
links schiebt...

(16-Bit-Wert in X, Ergebnis in r22/r23)
1
        clr r22
2
        ldi r23,182
3
        mul XL,r23
4
        movw r20,r0
5
        mul XH,r23
6
        add r21,r0
7
        adc r22,r1
8
        clr r23
9
        lsl r20
10
        rol r21
11
        rol r22
12
        rol r23
13
        sbrc r21,7
14
        subi r22,0xff
15
        brne label
16
        subi r23,0xff
17
label:

auf die Schnelle, ohne Garantie...

Gruß Jörg

von Joerg W. (joergwolfram)


Lesenswert?

sorry, mir ist noch eingefallen, dass ich mir die Benutzung von r16 
sparen kann, deshalb die schnelle Löschung des vorherigen Codes.

Gruß Jörg

von Joerg W. (joergwolfram)


Lesenswert?

und prompt ist noch ein kleiner Fehler drin, ich hoffe, jetzt stimmts:
1
        clr r22
2
        ldi r23,182
3
        mul XL,r23
4
        movw r20,r0
5
        mul XH,r23
6
        add r21,r0
7
        adc r22,r1
8
        clr r23
9
        lsl r20
10
        rol r21
11
        rol r22
12
        rol r23
13
        ldi r20,0x80
14
        add r21,r20
15
        clr r20
16
        adc r22,r20
17
        adc r23,r20

Gruß Jörg

von Kai G. (runtimeterror)


Lesenswert?

Auch nur auf die Schnelle:

lsl r20
kann raus, da der Wert nicht mehr gebraucht wird.

Die Rundung am Ende kann durch eine Addition mit 91 am Anfang ersetzt 
werden - das spart u.U. noch mal ein Bisschen. Je nach Anforderung kann 
die auch komplett entfallen.

Ansonsten lässt sich da vermutlich nicht mehr viel dran machen.

von Kai G. (runtimeterror)


Lesenswert?

>und prompt ist noch ein kleiner Fehler drin, ich hoffe, jetzt stimmts:
Dann les' ich jetzt nochmal :)

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.