Forum: Mikrocontroller und Digitale Elektronik 8-Bit Überlauf erkennen, bei addtion einer Konstanten


von Bernd S. (Firma: Anscheinend Corner-Cases ;-)) (bernd_stein)


Lesenswert?

Hallo zusammen,

habe vorher den MC68HC11 programmiert und dachte bisher immer im Groben,
das das Carry-Flag beim Überschreiten der der 8-Bit Grenze
oder beim unterschreiten der Null-Grenze gesetzt wird.
Nun kommt noch hinzu das, das addieren einer Konstanten beim AVR nur 
durch subrahieren des Zweierkomplements möglich ist (subi 
Rd,-Konstante).
Und hier natürlich darauf zu achten ist das Rd >= r16 ist.

Egal, jetzt kommt es aber noch besser. Beim subrahieren der 
Zweierkomplementkonstante ist der Wert des Ergebnisses zwar gleich wie 
bei der addition der Konstanten, aber das Carry-Flag verhält sich genau 
invetiert.

Zum Beispiel :

ldi  r16,255
subi r16,-5

Das Carry-Flag wird nicht gesetzt, auch kein anderes Flag,
aber wie erkenne ich das der 8-Bitwert übergelaufen ist ?

Anscheinend nur daran, das der Wert des Ergebnisses kleiner als 5 ist.

Hoffe auf aufschlußreiche Antworten.
Bis dann
Bernd_Stein

von Steffen H. (avrsteffen)


Lesenswert?

Das ist ja höchst interressant. Hab es gerade ausprobiert und 
tatsächlich wird kein einziges Flag beeinflusst.

Dann gibt es da nur noch die Möglichkeit über die benutzung eines 
2.Registers und den add-Befehl.

ldi  r16, 255
ldi  r17, 5
add  r16, r17

von Peter D. (peda)


Lesenswert?

Bernd Stein schrieb:
> Beim subrahieren der
> Zweierkomplementkonstante ist der Wert des Ergebnisses zwar gleich wie
> bei der addition der Konstanten, aber das Carry-Flag verhält sich genau
> invetiert.

Jau, so isses und wo is nu Dein Problem.

Du weißt nun, daß das CY-Flag invertiert reagiert,
also CY = 0: Überlauf.


Peter

von spess53 (Gast)


Lesenswert?

Hi

>Das ist ja höchst interressant. Hab es gerade ausprobiert und
>tatsächlich wird kein einziges Flag beeinflusst.

Warum auch?

Bei

>ldi  r16,255
>subi r16,-5

wird 255-250 gerechnet. Subi setzt die Flags H,S,V,N,Z und C. Bei der 
Beispielrechnung wird aber keine Bedingung zum Setzen eines dieser Flags 
erfüllt.

MfG Spess

von Bernd S. (Firma: Anscheinend Corner-Cases ;-)) (bernd_stein)


Lesenswert?

Steffen H. schrieb:
> Das ist ja höchst interressant. Hab es gerade ausprobiert und
> tatsächlich wird kein einziges Flag beeinflusst.
>
> Dann gibt es da nur noch die Möglichkeit über die benutzung eines
> 2.Registers und den add-Befehl.
>
> ldi  r16, 255
> ldi  r17, 5
> add  r16, r17

Hallo,

gute Idee.
Ich merke schon, die neue Generation von µC verlangt flexibles denken.
Oder ich bin einfach nur durch die CISC-Archetektur verwöhnt.

Bis dann
Bernd_Stein

von Peter D. (peda)


Lesenswert?

Bernd Stein schrieb:
>> ldi  r16, 255
>> ldi  r17, 5
>> add  r16, r17
>
> Hallo,
>
> gute Idee.

Schlechte Idee, weil vollkommen überflüssig.


Peter

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Peter Dannegger schrieb:
> Bernd Stein schrieb:
>>> ldi  r16, 255
>>> ldi  r17, 5
>>> add  r16, r17
>>
>> Hallo,
>>
>> gute Idee.
>
> Schlechte Idee, weil vollkommen überflüssig.

Das Carry wird bei Unterlauf der Subtraktion gesetzt. Gefragt ist aber 
der Überlauf bei Addition.
1
SUBI Rd, K
2
3
C: Set if the absolute value of K is larger than the absolute 
4
   value of Rd; cleared otherwise

von Bernd S. (Firma: Anscheinend Corner-Cases ;-)) (bernd_stein)


Lesenswert?

spess53 schrieb:
...
>
> Bei
>
>>ldi  r16,255
>>subi r16,-5
>
> wird 255-250 gerechnet. Subi setzt die Flags H,S,V,N,Z und C. Bei der
> Beispielrechnung wird aber keine Bedingung zum Setzen eines dieser Flags
> erfüllt.
>
> MfG Spess

Hallo,

ich habe schon oft gemerkt, das Leute die sich mit einer Materie schon 
lange auseinander setzen oder Ihnen diese absolut klar ist, sich nicht 
in die Lage der anderen versetzen können.

Ich will hier keine Haarspalterei herbei führen, aber als lernender 
nehme ich an jeder mir unverständlichen Kleinigkeit anstoß.

Also, -5 ist $FA sprich wirklich 250.
Im obigen Programm kommt laut Simulator 4 heraus, was ich auch so sehe.
255-250 ist 5 was ich ebenfalls als Richtig erachte.

Wo ist mein Denkfehler oder evtl. deiner ?

Bis dann
Bernd_Stein

von Sven P. (Gast)


Lesenswert?

Bernd Stein schrieb:
> Also, -5 ist $FA sprich wirklich 250.
Ne, es ist Zweierkomplement:
1
 5 = 0b00000101
2
-5 = 0b11111010 + 1 =
3
     0b11111011 = 0xFB = 251

von spess53 (Gast)


Lesenswert?

Hi

>Also, -5 ist $FA sprich wirklich 250.
>Im obigen Programm kommt laut Simulator 4 heraus, was ich auch so sehe.
>255-250 ist 5 was ich ebenfalls als Richtig erachte.

Da hat sich bei mir ein Fehler eingeschlichen: -5 ist $FB also dezimal 
251. Und damit ist 4 als Ergebnis verständlich.

MfG Spess

von Detlev T. (detlevt)


Lesenswert?

Sorry, aber ich verstehe die Diskussion nicht.

Wieso ist der eine Operand unsigned, der ander signed. Auch bei 
Assembler gilt doch: Entweder oder, aber immer beide - oder nicht?

Interpretation als signed:
0xFF = -1
0XFA = -5

-1 - -5 = 4. Ist doch vollkommen korrekt, wo soll hier ein fracking 
Überlauf passieren? Das korrekte Ergebnis ist weder kleiner als -128 
noch größer als +127.

Interpretation als unsigned:
0xFF = 255
0xFA = 251

255 - 251 = 4, ebenfalls korrekt, ebenfalls kein Überlauf.

Oder bin ich jetzt auf dem Holzweg?

Gruß, DetlevT

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Detlev T. schrieb:
> Sorry, aber ich verstehe die Diskussion nicht.
>
> Wieso ist der eine Operand unsigned, der ander signed.
Weil es darum geht eine Addition durch eine Subtraktion darzustellen 
also gilt: x + 5 = x - (-5)

von Sven P. (Gast)


Lesenswert?

Detlev T. schrieb:
> Sorry, aber ich verstehe die Diskussion nicht.
>
> Wieso ist der eine Operand unsigned, der ander signed. Auch bei
> Assembler gilt doch: Entweder oder, aber immer beide - oder nicht?

> Interpretation als signed:
> 0xFF = -1
> 0XFA = -5
Nein, 0xFA = -6!

Der Instruktion ist das egal, die rechnet immer vorzeichenlos. Lediglich 
dein Assembler verwandelt -5 ins Zweierkomplement, und -5 ist dort eben 
0xFB!
Es wird 0xFF - 0xFB gerechnet, das ist eben 4. Und da ist nichts dabei, 
was einen Übertrag auslösen würde.

von Detlev T. (detlevt)


Lesenswert?

Läubi .. schrieb:
> Weil es darum geht eine Addition durch eine Subtraktion darzustellen
> also gilt: x + 5 = x - (-5)
Schon klar, aber in dieser Fall kann x nur Werte [-128...127] annehmen. 
Der Controller kennt doch gar keine negativen Zahlen, gerade deswegen 
nimmt man doch den Trick mit dem Zweierkomplement. Die Interpretation 
des Ergebnisses ergibt sich erst aus dem weiteren Programm.

Beispiel x = 127 = 0x7F

x + 5 = x - (-5) = 0x7F - 0xFB (Hast ja recht, Sven) = 0x84 = -124 ist 
z.B. ein Überlauf, da der korrekte Wert (132) in 8-Bit(signed) nicht 
mehr darstellbar ist. In diesem Fall wird aber auch das carry-Flag 
beeinflusst!

Es ist einfach der Denkfehler, zu denken, beim subi könnte der 
Controller den einen Operanden als unsigned und den anderen als signed 
betrachten.

Ich sehe immer noch keinen Fehler beim Controller.

Gruß, DetlevT

von Peter D. (peda)


Lesenswert?

Du hast es schon richtig erkannt, das CY ist invertiert bei
a = a - (-b)
Also mußt Du nur BRCC anstelle BRCS nehmen.

Bzw. wenn Du ne 16Bit Konstante addieren willst:
SBI rl, low(-Konstante)
SBCI rh, high(-Konstante)

Wird z.B. gemacht für nen Indexzugriff, die Konstante ist dann der 
Offset des Arrays.


Peter

von Bernd S. (Firma: Anscheinend Corner-Cases ;-)) (bernd_stein)


Lesenswert?

Sven P. schrieb:
> Bernd Stein schrieb:
>> Also, -5 ist $FA sprich wirklich 250.
> Ne, es ist Zweierkomplement:
>
1
>  5 = 0b00000101
2
> -5 = 0b11111010 + 1 =
3
>      0b11111011 = 0xFB = 251
4
>

Oh ja danke,
hatte mich erst vertan.
-5 => 0b1111 1001 => $F9.
Keine Ahnung was da in meinem Gerhirn falsch gelaufen ist.

Dann habe ich mich korregiert 0b1111 1011
und dachte ein Bit mehr als vorher, deshalb $FA passte auch gut zu den 
250 von Spess53.

Also schon wieder eine Fehlfunktion in meinem Gehirn.

Habe aber eigentlich genau das vorgehabt was Du oben beschreibst,
nämlich die Zweierkomplementbildung von 5.

Nochmals Danke für deine ausführliche Hilfe.

Bis dann
Bernd_Stein

von Bernd S. (Firma: Anscheinend Corner-Cases ;-)) (bernd_stein)


Lesenswert?

Bernd Stein schrieb:
>
> Zum Beispiel :
>
> ldi  r16,255
> subi r16,-5
>
> Das Carry-Flag wird nicht gesetzt, auch kein anderes Flag,
> aber wie erkenne ich das der 8-Bitwert übergelaufen ist ?
>
> Anscheinend nur daran, das der Wert des Ergebnisses kleiner als 5 ist.
>
Hallo,

das sollte nur ein Beispiel sein.
Meine generell : Hole einen Meßwert und addiere einen Offset hinzu.

Wie erkenne ich nun Programmtechnisch elegant (Assembler), das der 
Zahlenbereich von 8-Bit überschritten wurde ?

Bis dann
Bernd_Stein

von Andreas F. (aferber)


Lesenswert?

Bernd Stein schrieb:
> Wie erkenne ich nun Programmtechnisch elegant (Assembler), das der
> Zahlenbereich von 8-Bit überschritten wurde ?

Wie schon von Peter gesagt wurde, das Carry-Bit reagiert schlicht und 
einfach nur invertiert. Also einfach die Verzweigung nach der 
Subtraktion gegenüber der eigentlich gewollten Addition vertauschen, 
entweder durch Negation der Sprungbedingung (BRCC durch BRCS bzw. 
umgekehrt ersetzen), oder eben die Sprungziele vertauschen.

Andreas

von Floh (Gast)


Lesenswert?

Bernd Stein schrieb:
> Wie erkenne ich nun Programmtechnisch elegant (Assembler), das der
> Zahlenbereich von 8-Bit überschritten wurde ?

Falls der rauskommende Wert kleiner als dein Offset ist, wars ein 
Überlauf, ansonsten hat es gepasst.
z.B.
68 + 5 = 73 ->passt
200 + 60 = 260 = 4 ->Überlauf
255 + 255 = 510 = 254 ->Überlauf
23 + 200 = 223 -> passt
...
Hoffe mein gedankengang ist richtig :-)

von Bernd S. (Firma: Anscheinend Corner-Cases ;-)) (bernd_stein)


Lesenswert?

Andreas Ferber schrieb:
> Bernd Stein schrieb:
>> Wie erkenne ich nun Programmtechnisch elegant (Assembler), das der
>> Zahlenbereich von 8-Bit überschritten wurde ?
>
> Wie schon von Peter gesagt wurde, das Carry-Bit reagiert schlicht und
> einfach nur invertiert. Also einfach die Verzweigung nach der
> Subtraktion gegenüber der eigentlich gewollten Addition vertauschen,
> entweder durch Negation der Sprungbedingung (BRCC durch BRCS bzw.
> umgekehrt ersetzen), oder eben die Sprungziele vertauschen.
>
> Andreas

Peter Dannegger schrieb:
> Du hast es schon richtig erkannt, das CY ist invertiert bei
> a = a - (-b)
> Also mußt Du nur BRCC anstelle BRCS nehmen.

Guten morgen liebe schlaflosen,

vielleicht bin ich noch nicht wach genung, um zu verstehen warum das so 
ist.
Aber egal, belassen wir es dabei.
Jetzt ist für mich wirklich ein Punkt erreicht wo ich damit abschliesse 
dies auch noch verstehen zu wollen.
Es ist halt so !!!

Vielen Dank an alle, die hier mitgewirkt haben.

Bis demnächst
Bernd_Stein

von Andreas F. (aferber)


Lesenswert?

Bernd Stein schrieb:
> Jetzt ist für mich wirklich ein Punkt erreicht wo ich damit abschliesse
> dies auch noch verstehen zu wollen.
> Es ist halt so !!!

Und damit liegst du goldrichtig, es ist letztlich einfach so 
definiert.

Jetzt kann man sich natürlich fragen, warum das so und nicht anders 
definiert wurde. Dafür gibt es einen einfachen Grund, es macht die 
Hardware-Implementierung einfacher, nicht mehr und nicht weniger. Siehe 
auch

http://de.wikipedia.org/wiki/Additionsschaltung#Subtrahierer

Andreas

von Detlev T. (detlevt)


Lesenswert?

Hallo Bernd,

das kann ich nachvollziehen. Ich habe auch eine ganze Zeit gebraucht bis 
ich es verstanden zu haben glaube.

Also, du willst y = x + d ausrechnen. Wegen der Einschränkung berechnet 
der Controller jedoch y = x - (-d). (-d) ist das Zweierkomplement von d, 
das wissen aber nur du und dein Compiler. Für den Controller ist das 
eine ganz normale (positive) Binärzahl. Nun sind bei d<> 0 zwei 
Ergebnisse denkbar:

1.) y > x: Für dich ist das kein Überlauf, denn es wurde eine so kleine 
Zahl "addiert", dass der Wertebereich nicht verlassen wurde. Der 
Controller kommt hier aber nur hin, indem er über "Null" subtrahiert, 
für ihn ist das also ein Überlauf.

2.) y <= x: Für dich ist das ein Überlauf, weil mathematisch die Summe 
zweier positiver Zahlen nicht kleiner sein kann als die einzelnen 
Summanden. Für den Controller ist das aber gerade kein Überlauf, denn er 
kommt wegen der Subtraktion ja gerade an diese Stelle ohne "über Null" 
zu gehen.

Insgesamt stimmt es also, dass die Funktion des Carry-Flags genau 
invertiert ist, deshalb aber sehr wohl genutzt werden kann.

q.e.d. :D

Gruß, DetlevT

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.