izaseba
07.02.2008, 00:30
Hallo,
irgendwie steh ich auf dem Schlauch :-(
Meine Mision -> Vorzeichenbehaftetes Multiplizieren von zwei 24 Bit Zahlen.
Meine Lösung sieht so aus,daß ich zuerst beide Zahlen teste, ob da was negatives ist, wenn ja wird ein Zweierkomplement angewendet und entsprechend das Produkt positiv gelassen, oder aber wieder negativ gemacht.
Multipliziert wird dann nur im positivem Bereich.
Soweit klappt es auch sehr gut, ich frage mich aber, ob es nicht einfacher(kürzer) geht.
Vor allem der Zweierkomplement kostet mich zu viel.
bei einer 8 Bit Zahl nimmt man einfach neg und fertig.
Wie geht das bei >8 Bit ?
Eine Kombination aus neg bei LSB und com bei MSB wird ja nicht gehen, weil es ja bei neg ein Überlauf stattfinden könnte, der dann von com nicht mitberechnet wird, oder ?
Ich mache es im Moment so, daß ich alle Bytes mit com 'drehe' und 1 dazuaddiere, wie gesagt, es geht, aber glücklich bin ich damit nicht...
Naja, ich poste mal eben den Ausschnitt, vieleicht sieht jemand noch Optimierungsmöglichkeiten.
Kurze Erklärung zu Registern:
null = 0
full = 0xFF
one = 1
tmp1,tmp2 einfache Wegwerfregister.
Der rest ist eigentlich ausreichend dokumentiert
;************************************************* ******
;* Signedmul24 Bit *
;* Zahl1 MSB r2 r3 r4 LSB *
;* Zahl2 MSB r5 r6 r7 LSB *
;* Rueckgabe MSB r8 r9 r10 r11 LSB *
;************************************************* ******
s_mul24:
rcall vorzeichen_pruefen ;Vorzeichen pruefen und ev. Zahlen positiv machen
clr r8 ;Rueckgabe leeren
clr r9 ;Rueckgabe leeren
clr r10 ;Rueckgabe leeren
clr r11 ;Rueckgabe leeren
clr r12 ;Ueberlaufbyte leeren
s_mul24_1:
cp r7,null ;Testen, ob noch was zu tun ist
cpc r6,null
cpc r5,null
breq s_mul24_3 ;Wenn nicht, Schleife verlassen
lsr r5 ;Multiplikator rechts schieben
ror r6 ;Multiplikator rechts schieben
ror r7 ;Multiplikator rechts schieben
brcc s_mul24_2 ;wenn eine 0 rausgeschoben wurde den naechsten Schritt ueberspringen
add r11,r4 ;Multiplikanten zum Produkt addieren
adc r10,r3 ;Multiplikanten zum Produkt addieren
adc r9,r2 ;Multiplikanten zum Produkt addieren
adc r8,r12 ;Ueberlaufbyte zum Produkt addieren
s_mul24_2:
lsl r4 ;Multiplikanten links schieben
rol r3 ;Multiplikanten links schieben
rol r2 ;Multiplikanten links schieben
rol r12 ;Herausfallende Bits auffangen
rjmp s_mul24_1 ;Weiterrechnen
s_mul24_3:
brtc s_mul23_end;Wenn T Flag gesetzt ist muss das Produkt negativ werden
com r11 ;2-er Komplement
com r10 ;2-er Komplement
com r9 ;2-er Komplement
com r8 ;2-er Komplement
add r11,one ;2-er Komplement
adc r10,null ;2-er Komplement
adc r9,null ;2-er Komplement
adc r8,null ;2-er Komplement
s_mul23_end:
ret ;fertig
;************************************************* ************************
;* wandelt negative Zahlen in positive um *
;*T Flag signalisiert, ob das Ergebnis positiv (0) oder negativ(1) wird *
;************************************************* ************************
vorzeichen_pruefen:
clr tmp1
sbrs r2,7
rjmp vorzeichen_pruefen2 ;Zahl 1 positiv kein Komplement + Flag 0 in tmp1
;Zahl 1 negativ Komplement + Flag 1 in tmp1
com r2
com r3
com r4
add r4,one
adc r3,null
adc r2,null
ser tmp1
vorzeichen_pruefen2:
;Zahl 1 positiv,kein Komplement + Flag 0 in tmp1
clr tmp2
sbrs r5,7
rjmp vorzeichen_pruefen4 ;Zahl 2 positiv kein Komplement + Flag 0 in tmp2
vorzeichen_pruefen3:
;Zahl 2 negativ Komplement + Flag 1 in tmp2
com r5
com r6
com r7
add r7,one
adc r6,null
adc r5,null
ser tmp2
vorzeichen_pruefen4:
;Produkt bekommt positives Vorzeichen T Flag im Status loeschen
clt
eor tmp1,tmp2 ;Pruefe welches Vorzeichen das Produkt bekommt
breq vorzeichen_pruefen5 ;Produkt bekommt positives Vorzeichen
;Produkt bekommt negatives Vorzeichen T Flag im Status setzen
set
vorzeichen_pruefen5:
ret
Gruß Sebastian
P.S. Bevor jemand meint, warum nimmt er nicht mul,
es läuft auf einem Tiny...
irgendwie steh ich auf dem Schlauch :-(
Meine Mision -> Vorzeichenbehaftetes Multiplizieren von zwei 24 Bit Zahlen.
Meine Lösung sieht so aus,daß ich zuerst beide Zahlen teste, ob da was negatives ist, wenn ja wird ein Zweierkomplement angewendet und entsprechend das Produkt positiv gelassen, oder aber wieder negativ gemacht.
Multipliziert wird dann nur im positivem Bereich.
Soweit klappt es auch sehr gut, ich frage mich aber, ob es nicht einfacher(kürzer) geht.
Vor allem der Zweierkomplement kostet mich zu viel.
bei einer 8 Bit Zahl nimmt man einfach neg und fertig.
Wie geht das bei >8 Bit ?
Eine Kombination aus neg bei LSB und com bei MSB wird ja nicht gehen, weil es ja bei neg ein Überlauf stattfinden könnte, der dann von com nicht mitberechnet wird, oder ?
Ich mache es im Moment so, daß ich alle Bytes mit com 'drehe' und 1 dazuaddiere, wie gesagt, es geht, aber glücklich bin ich damit nicht...
Naja, ich poste mal eben den Ausschnitt, vieleicht sieht jemand noch Optimierungsmöglichkeiten.
Kurze Erklärung zu Registern:
null = 0
full = 0xFF
one = 1
tmp1,tmp2 einfache Wegwerfregister.
Der rest ist eigentlich ausreichend dokumentiert
;************************************************* ******
;* Signedmul24 Bit *
;* Zahl1 MSB r2 r3 r4 LSB *
;* Zahl2 MSB r5 r6 r7 LSB *
;* Rueckgabe MSB r8 r9 r10 r11 LSB *
;************************************************* ******
s_mul24:
rcall vorzeichen_pruefen ;Vorzeichen pruefen und ev. Zahlen positiv machen
clr r8 ;Rueckgabe leeren
clr r9 ;Rueckgabe leeren
clr r10 ;Rueckgabe leeren
clr r11 ;Rueckgabe leeren
clr r12 ;Ueberlaufbyte leeren
s_mul24_1:
cp r7,null ;Testen, ob noch was zu tun ist
cpc r6,null
cpc r5,null
breq s_mul24_3 ;Wenn nicht, Schleife verlassen
lsr r5 ;Multiplikator rechts schieben
ror r6 ;Multiplikator rechts schieben
ror r7 ;Multiplikator rechts schieben
brcc s_mul24_2 ;wenn eine 0 rausgeschoben wurde den naechsten Schritt ueberspringen
add r11,r4 ;Multiplikanten zum Produkt addieren
adc r10,r3 ;Multiplikanten zum Produkt addieren
adc r9,r2 ;Multiplikanten zum Produkt addieren
adc r8,r12 ;Ueberlaufbyte zum Produkt addieren
s_mul24_2:
lsl r4 ;Multiplikanten links schieben
rol r3 ;Multiplikanten links schieben
rol r2 ;Multiplikanten links schieben
rol r12 ;Herausfallende Bits auffangen
rjmp s_mul24_1 ;Weiterrechnen
s_mul24_3:
brtc s_mul23_end;Wenn T Flag gesetzt ist muss das Produkt negativ werden
com r11 ;2-er Komplement
com r10 ;2-er Komplement
com r9 ;2-er Komplement
com r8 ;2-er Komplement
add r11,one ;2-er Komplement
adc r10,null ;2-er Komplement
adc r9,null ;2-er Komplement
adc r8,null ;2-er Komplement
s_mul23_end:
ret ;fertig
;************************************************* ************************
;* wandelt negative Zahlen in positive um *
;*T Flag signalisiert, ob das Ergebnis positiv (0) oder negativ(1) wird *
;************************************************* ************************
vorzeichen_pruefen:
clr tmp1
sbrs r2,7
rjmp vorzeichen_pruefen2 ;Zahl 1 positiv kein Komplement + Flag 0 in tmp1
;Zahl 1 negativ Komplement + Flag 1 in tmp1
com r2
com r3
com r4
add r4,one
adc r3,null
adc r2,null
ser tmp1
vorzeichen_pruefen2:
;Zahl 1 positiv,kein Komplement + Flag 0 in tmp1
clr tmp2
sbrs r5,7
rjmp vorzeichen_pruefen4 ;Zahl 2 positiv kein Komplement + Flag 0 in tmp2
vorzeichen_pruefen3:
;Zahl 2 negativ Komplement + Flag 1 in tmp2
com r5
com r6
com r7
add r7,one
adc r6,null
adc r5,null
ser tmp2
vorzeichen_pruefen4:
;Produkt bekommt positives Vorzeichen T Flag im Status loeschen
clt
eor tmp1,tmp2 ;Pruefe welches Vorzeichen das Produkt bekommt
breq vorzeichen_pruefen5 ;Produkt bekommt positives Vorzeichen
;Produkt bekommt negatives Vorzeichen T Flag im Status setzen
set
vorzeichen_pruefen5:
ret
Gruß Sebastian
P.S. Bevor jemand meint, warum nimmt er nicht mul,
es läuft auf einem Tiny...