Hi Im Rahmen einer Berechung errechne ich mir einen Zwischenwert. Mit diesem Zwischenwert muss später weitergerechnet werden. Nun ist das Problem dass dieser Zwischenwert auch negativ werden kann. So bis -200 ungefähr. Der Zwischenwert entsteht durch eine Subtraktion. Wenn das Ergebniss dieser Subtraktion nun eben negative ist bekomm ich total unrealistische Werte. Kann mir einer sagen wie man im AVR Assembler mit diesen negativen Zahlen umgeht? Vielen Dank schonmal dafür!
Poste doch bitte mal Deinen Code. Sonst kann Dir hier keiner sagen, was Du evtl. falsch machst. Grundsätzlich werden negative Zahlen mit der Zweierkomplement-Darstellung behandelt. Dafür haben die AVRs z.B. ein spezielles Flag, das anzeigt, wenn ein Berechnungs-Ergebnis negativ ist. Wenn Du normal nur mit vorzeichenlosen Zahlen arbeitest und dieses Flag außer acht lässt, kriegst Du natürlich Murks raus, wenn Du mehr subtrahierst als im Register drinsteht und das ganze wieder als positive Zahl interpretierst.
...Ach ja, und Du musst natürlich beachten, dass wenn Du mit 8-Bit-Werten rechnest, der Wertebereich durch die Zweierkomplement-Darstellung von -128 bis +127 geht. Bei -200 musste also mit 16 Bit rechnen.
Hier mal ein Beispiel. ldi r16,0x20 ldi r17,0x4E subi r16,0x84 sbci r17,0x4E Nun steht ja das Ergebniss in r16:r17 aber ist halt eine negative Zahl (20000-20100= -100) Wie geh ich nun vor um mit auch mit dem korrekten Wert (-100) weiterzurechnen? Als Ergebniss gibt er mir hier ja irgendwie FFFFFFFF9C oder so aus...
Umrechnen in normale Zahlen: das höchstwertige Bit ist das Minuszeichen, die restlichen 15 Bit müssen bitweise invertiert und dann 1 addiert werden. Invertieren am einfachsten mit dem COM-Befehl für beide Register und dann adiw 1
Und kannst du mir auch sagen wie ich damit jetzt weiter rechne? Wenn ich ganz normal mit r16:r17 weiter rechne rechnet er ja mit utopischen Zahlenwerten. Wie kann ich ihm nun sagen das er diese Zweierkomplement-Darstellung nun berücksichtigt oder richtig weiter rechnet?
BTW: Wenn Du mit 16-Bit-Zahlen rumspielst, benutze doch die Subtraktions- und Additions-Befehle sbiw und adiw. Musst dannn nur die richtigen Register verwenden, da diese Befehle nur mit den oberen vier Registerpaaren laufen.
> Und kannst du mir auch sagen wie ich damit jetzt weiter rechne?
Ganz normal.
Das schöne an der Zweierkomplementdarstellung ist,
dass du zumindest für Addition und Subtraktion keine
wie auch immer geartete Sonderbehandlung brauchst.
Es kommt hinten immer das richtige raus.
Genau, solange Du mit Deinen Werten im Bereich -32767...+32766 bleibst und nur addierst und subtrahierst, kannst Du ganz normal weiterrechnen, denn sobald Du zu deinem negativen Zwischenwert wieder etwas positives addierst, das betragsmäßig größer ist, biste wieder auf der positiven Seite, ohne dass Du was merkst. Lediglich dann, wenn Du einen negativen Wert irgendwo ausgeben willst, musst Du das Vorzeichen explizit beachten und die Umrechnung in Betrag und Vorzeichen (siehe Christophs Posting) durchführen. Aber Du sagst ja, es sei ein Zwischenwert, der vermutlich nur zur weiteren Berechnung verwendet wird und das Endergebnis ist dann ja wahrscheinlich positiv. Dann kannste das einfach ignorieren...
Um das nochmal deutlich zu sagen: Am Ende der Berechnung wirst du das Ergebnis wirgendwo anzeigen. Das ist die einzige Stelle (neben einer Zahleneingabe) wo du das Berücksichtigen musst. Dazu schaust du dir das höchste Bit (Bit 15) an. Ist es 0, dann handelt es sich um eine positive Zahl und du kannst sie ganz normal ausgeben. Ist es aber 1, dann handelt es sich um eine negative Zahl und du bildest wiederrum das 2-er Komplement: alle Bits umdrehen und 1 addieren. Bsp (mit 8 Bit wegen Schreibaufwand) 0000 1001 welche Zahl ist das, wenn wir mit 2-er Komplement, vorzeichen- behaftet rechnen? Nun: 0000 1001 ^ | +---- ist eine 0, also ist die Zahl schon mal positiv. Die restlichen Bits (Bit 0 bis Bit 6) ergeben direkt die Zahl: 9 dezimal Was ist mit: 1000 1001 ^ | +----- ist 1, daher ist das eine neagtive Zahl. die Bits 0 bis 6 sind: 000 1001 alles umdrehen 111 0110 und 1 addieren 111 0111 111 0111 ist dezimal 119, also entspricht 1000 1001 der dezimalen Zahl: -119 Um eine positive Zahl negativ zu machen, bzw. eine neagtive Zahl positiv zu machen, wendet man also das 2-er Komplement an: alle Bits umdrehen und 1 addieren. Welches Bitmuster (8Bit, 2-er Komplement) entspricht der Zahl -49 Nun: +53 hat das Bitmuster 011 0001 um das neagtiv zu machen, rechnen wir 0011 0001 alles umdrehen 1100 1110 und 1 addieren 1100 1111 das Bitmuster für -49 lautet also 1100 1111. Da es sich um eine neagtive Zahl handelt, muss das höchstwertige Bit 1 sein, was es auch ist. Trickreich: Was ist mit -0? Ist das dasselbe wie +0? Probieren wirs aus: 0 0000 0000 alles umdrehen 1111 1111 1 addieren 0000 0000 ( + 1 Übertrag im 9. ten Bit, da wir aber nur 8 Bit rechnen, fällt das ganz einfach unter den Tisch) Super: -0 und +0 sind tatsächlich die gleiche Zahl. Machen wir mal eine Rechnung: dezimal: 5 - 7 +5 0000 0101 -7 (negative Zahl, da brauchen wir wieder das 2-er Komplement +7 0000 0111 umdrehen 1111 1000 +1 1111 1001 ) Also: 0000 0101 + 1111 1001 --------- 1111 1110 das höchste Bit ist 1 -> negative Zahl: 1111 1110 0000 0001 0000 0010 -> 2 Das Ergebnis ist also -2
Übrigens, wenn man weiß dass das Endergebnis der Berechnung im erlaubten Wertebereich liegt, dann spielen Überläufe bei Zwischenergebnissen keine Rolle.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.