Forum: Mikrocontroller und Digitale Elektronik negatives Ergebniss


von Tobias (Gast)


Lesenswert?

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!

von johnny.m (Gast)


Lesenswert?

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.

von johnny.m (Gast)


Lesenswert?

...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.

von Tobias (Gast)


Lesenswert?

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...

von johnny.m (Gast)


Lesenswert?

...Und FF9C ist genau die Zweierkomplement-Darstellung von -100...

von Christoph Kessler (db1uq) (Gast)


Lesenswert?

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

von Tobias (Gast)


Lesenswert?

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?

von Rahul (Gast)


Lesenswert?


von johnny.m (Gast)


Lesenswert?

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.

von Karl heinz B. (kbucheg)


Lesenswert?

> 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.

von johnny.m (Gast)


Lesenswert?

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...

von Karl heinz B. (kbucheg)


Lesenswert?

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

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Übrigens, wenn man weiß dass das Endergebnis der Berechnung im erlaubten
Wertebereich liegt, dann spielen Überläufe bei Zwischenergebnissen keine
Rolle.

von Tobias (Gast)


Lesenswert?

Vielen Dank!
Super Forum mit noch superen Nutzern ;-)

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.