- MultiPlus Wechselrichter Insel und Nulleinspeisung Conrad         
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 16

Thema: Zweierkomplement bei Zahlen > 8Bit

  1. #1
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    53
    Beiträge
    2.236

    Zweierkomplement bei Zahlen > 8Bit

    Anzeige

    LiFePo4 Akku selber bauen - Video
    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
    Code:
    ;*******************************************************
    ;*         				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...
    Software is like s e x: its better when its free.
    Linus Torvald

  2. #2
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    25.11.2003
    Beiträge
    1.112
    Also prinzipiell bin ich recht sicher, dass die Bildung des 2er Kompl auf diese Weise die einfachste Lösung ist. Die Kombination neg und com funktioniert aus genanntem Grund nicht. Kann mir zwar gerade nicht erklären, warum neg nur bei 0x80 das V-Flag setzt, aber das erscheint mir ein Problem.
    Deine Variante kann ich jetzt auch nicht weiter optimieren, bin aber auch kein Spezialist.
    Gruß

  3. #3
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    25.10.2007
    Ort
    41462 Neuss
    Alter
    56
    Beiträge
    375
    ich hab mir mal nen alten professionellen z80 code angeschaut. die haben das auch so gemacht (erst vorzeichen behandeln, dann multiplizieren) also gehts wohl so am besten.

    an den details kann man sicher noch etwas schrauben. z.b. ists nicht nötig immer r5,r6 und r7 gemeinsam zu shiften. nach 8 shifts hast du ja nur das eine register in ein anderes kopiert.
    ich vermute, das 2er komplement könnte man einfacher berechnen, aber da müste ich mich jetzt richtig reinknien.

  4. #4
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Eventuell man Atmel Application Note 222 anschauen, da steht was über die Multiplicationen mit dem Hardware Multipier (Megaxxx). Wenn es auf Geschwindigkeit ankommt ist hier ein Tinyxx nicht die beste Wahl.

  5. #5
    Super-Moderator Robotik Visionär Avatar von PicNick
    Registriert seit
    23.11.2004
    Ort
    Wien
    Beiträge
    6.842
    Denke auch, dass zumindest mal das 2-er kompl so am besten ist.
    Du könntest zwar auf die ADC's der oberen Register verzichten, wenn Bit 0 nach der 1-addition =1 ist (kein überlauf) aber ein if-jump sind ja auch 3-cycles, also bringt das nix (Erst, wenn die Zahlen deutlich länger werden zB 64 Bit).

    Ich würde nur raten, die Zahlen mit Pointer anzusprechen, damit du nicht alle routinen mehrfach hast. Das kostet zwar im Moment, aber wenn du deine Mathe-Lib noch ausbaust, wirst du froh sein. (ein pointer auf einem Tiny is ja nur ein byte)
    mfg robert
    Wer glaubt zu wissen, muß wissen, er glaubt.

  6. #6
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Das 2 er Komplement geht noch etwas kürzer:
    Für das Addieren von eins gibt es als Alternative das Abziehen von 0xFF. Dafür gibt es den SUBI bzw SBCI Befehl. Außerdem kann man für das low byte den NEG Befehl nehmen und nur noch die hoheren Bytes per SBCI 0xFF korrigieren. Bei einigen Prozessoren gibt es auch noch ein SBCWI um gleich 2 Register zusammen zu bearbeiten, spart aber nicht viel.

    (Ist nicht auf meinem Mist gewachsen, war geraden eine Frage bei ARVFREAKS (englisch)):
    http://www.avrfreaks.net/index.php?n...wtopic&t=59526

  7. #7
    Super-Moderator Robotik Visionär Avatar von PicNick
    Registriert seit
    23.11.2004
    Ort
    Wien
    Beiträge
    6.842
    ..für das low byte den NEG Befehl nehmen ..
    Da ist aber die Sache mit 0x80, die stört in diesem Fall.
    mfg robert
    Wer glaubt zu wissen, muß wissen, er glaubt.

  8. #8
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    25.11.2003
    Beiträge
    1.112
    @Besserwessi
    Du sparst aber nichts, wenn Du addierst statt subtrahierst.
    Gruß

  9. #9
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    53
    Beiträge
    2.236
    Danke für Eure Antworten,

    gut zu wissen, daß es doch nicht einfacher geht, bin doch nicht ganz bala bala ;.)

    z.b. ists nicht nötig immer r5,r6 und r7 gemeinsam zu shiften. nach 8 shifts hast du ja nur das eine register in ein anderes kopiert.
    Das ist zwar richtig, ich will aber wissen, was rechts aus dem Low Register rausfällt, oder verstehe ich Dich jetzt falsch ?

    Wenn es auf Geschwindigkeit ankommt ist hier ein Tinyxx nicht die beste Wahl.
    Ja ich weiß, es kommt aber nicht auf die Geschwindigkeit an sondern eher Speicherverbrauch und Tiny und kein Mega, wegen Platzmangel...

    Ich würde nur raten, die Zahlen mit Pointer anzusprechen, damit du nicht alle routinen mehrfach hast. Das kostet zwar im Moment, aber wenn du deine Mathe-Lib noch ausbaust, wirst du froh sein. (ein pointer auf einem Tiny is ja nur ein byte)
    Das hört sich nicht schlecht an...
    Ich muß das mal überdenken, versteh nicht ganz
    Könntest Du bitte etwas genauer werden ?

    Gruß Sebastian
    Software is like s e x: its better when its free.
    Linus Torvald

  10. #10
    Super-Moderator Robotik Visionär Avatar von PicNick
    Registriert seit
    23.11.2004
    Ort
    Wien
    Beiträge
    6.842
    etwas genauer
    Gern.
    Die Register kannst du genauso über XYZ Pointer addressieren wie den ganzen SRAM
    z.b du hast eine Funktion "SignCheck" wie oben. du lädst X mit der Adresse vom R2 und rufst sie mit Call. Die Funktion verwurstelt immer die 4 Byte vom Pointer aufwärts. Das braucht mehr code, stimmt.
    aaaaaber
    Die gleiche Funktion kann aber sofort jedes beliebige 32-Bit Feld auf Vorzeichen prüfen (oder rotieren oder sonstwas)

    Ein wenig System braucht man der der Registerverteilung natürlich schon. Beim TINY sind ja die ressourcen knapp

    Man kann aber strukturierter arbeiten, objekt-orientierter Assembler++,
    gewissermassen

    Vielleicht sollt' ich an deinen funktionen ein konkretes Konzept darlegen, damit du besser weisst, was ich mein.
    mfg robert
    Wer glaubt zu wissen, muß wissen, er glaubt.

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

fchao-Sinus-Wechselrichter AliExpress