Forum: Mikrocontroller und Digitale Elektronik Was passiert bei einem Überlauf


von Regler (Gast)


Lesenswert?

Hallo,

ich will einen Überlauf in C bewusst einsetzen, und habe mich gefragt, 
was passiert, wenn ich ein uint8_t i = 0xff inkrementiere. Die geht doch 
dann auf 0 und sonst nichts, oder?

Hintergrund:

Habe einen Moving-Average-Filter und schalte zwischen mehreren AD-Ports 
um. Da dies in der Interrupt-Schleife geschieht ist der erste AD-Wert 
noch vom "alten" Port und daher für den neuen MA uninteressant und soll 
verworfen werden. Um dies festzustellen, nehme ich die Zählervariable, 
d.h. i. Dies ist die Anzahl der bisherigen Samples des Filters, die nach 
dem initialisieren hochzählt bis die Filterlänge erreicht ist. 
Anschließend arbeitet der Filter rekursiv.

Dient primär dem Einsparen unnötiger Variablen.

von Antwort (Gast)


Lesenswert?

Regler schrieb:
> Hallo,
>
> ich will einen Überlauf in C bewusst einsetzen, und habe mich gefragt,
> was passiert, wenn ich ein uint8_t i = 0xff inkrementiere. Die geht doch
> dann auf 0 und sonst nichts, oder?
Ja, und es wird das Überlauf Flag gesetzt.

von Regler (Gast)


Lesenswert?

Antwort schrieb:
> und es wird das Überlauf Flag gesetzt.

Okay?! Das könnte ich abfragen. Wo eigentlich?

Wenn ich's lasse, passiert nichts weiter, oder? Oder gibts noch weitere 
Konsequenzen, wie etwa das Beschreiben einer anderen, genauer der 
nächsten Speicherstelle.

Wie gesagt: Mir ist zu diesem Zeitpunkt völlig bewusst, dass ein 
Überlauf passiert.

von Antwort (Gast)


Lesenswert?

Schau im Datenblatt deines Controllers nach dem Carry-Flag (ich weiß 
nicht welchen du verwendest)

von Huch (Gast)


Lesenswert?

>>Antwort schrieb:
>> und es wird das Überlauf Flag gesetzt.

>Okay?! Das könnte ich abfragen. Wo eigentlich?

Die Antwort von "Antwort" ist so nicht richtig. Wenn wir von C 
Programmen reden, dann gibt es dort ein Überlauf Flag nicht. Nirgendwo 
ist sowas definiert. Also kann man das auch nicht abfragen.

Ein anderer Punkt ist natürlich, das das C Programm ja in ein 
Assembler-Programm umgesetzt wird und auf einer konkreten CPU läuft. 
Deswegen und weil die viele CPUs bei einem Inkrement auch ein 
Überlauf-Flag setzen, ist es, insbesondere wenn man in ein C Programm 
Assemblerbefehle inkorporieren kann, zwar möglich, diese Flag 
abzufragen,
aber es ist nirgendwo in der C-Sprachbeschreibung definiert, das und auf 
welche Weise ein Inkrement in Assembler umgesetzt wird, welcher Befehl, 
welches Register etc. dafür verwendet wird und das mischen von C mit 
Assemblercode ist auch nicht Standard sondern z.B. eine Besonderheit von 
GCC und anderen.

Da aber die Hauptfrage ja war: "Die geht doch dann auf 0 und sonst 
nichts, oder?" und man diese mit Ja beantworten muss, spielt das alles 
garkeine Rolle.

von C-Experte (Gast)


Lesenswert?

> ich will einen Überlauf in C bewusst einsetzen

Laut C-Standart ist das Ergebnis undefiniert.

von Regler (Gast)


Lesenswert?

Einen AVR (Genauer einen ATtiny26).
Programmiere in C und bin mir nicht ganz bewusst, ob der Missbrauch 
eines Überlaufs Konsequenzen hat. Was passiert mit dem Carry-Flag wenn 
es nicht für eine bestimmte Operation (z.B. eine 16-Bit Op) verwendet 
wird. Muss ich das selbst händisch zurücksetzen (da der Compiler das 
wahrscheinlich nicht automatisch macht!?) oder passiert das 
vollautomatisch, wenn es nicht abgefragt und eine neue Op ausgeführt 
wird?

von Michael B. (mb_)


Lesenswert?

C-Experte schrieb:
>> ich will einen Überlauf in C bewusst einsetzen
>
> Laut C-Standart ist das Ergebnis undefiniert.

Das ist Unsinn. Der C Standar>>>D<<< definiert den Überlauf einer 
unsigned Variable ziemlich exakt.

von Michael B. (mb_)


Lesenswert?

Regler schrieb:
> Einen AVR (Genauer einen ATtiny26).
> Programmiere in C und bin mir nicht ganz bewusst, ob der Missbrauch
> eines Überlaufs Konsequenzen hat. Was passiert mit dem Carry-Flag wenn
> es nicht für eine bestimmte Operation (z.B. eine 16-Bit Op) verwendet
> wird. Muss ich das selbst händisch zurücksetzen (da der Compiler das
> wahrscheinlich nicht automatisch macht!?) oder passiert das
> vollautomatisch, wenn es nicht abgefragt und eine neue Op ausgeführt
> wird?

Der Compiler kümmert sich um das carry flag wo nötig.

von Regler (Gast)


Lesenswert?

C-Experte schrieb:
> Laut C-Standart ist das Ergebnis undefiniert.

Und aus der Sicht von AVR-GCC?

Huch schrieb:
> Da aber die Hauptfrage ja war: "Die geht doch dann auf 0 und sonst
> nichts, oder?" und man diese mit Ja beantworten muss, spielt das alles
> garkeine Rolle.

Alles klar, d.h. ich brauch keine bösen Bugs durch diesen "Missbrauch" 
befürchten (z.B einen Fehler in der nächsten 16-Bit Op.)?

von Markus (Gast)


Lesenswert?

Huch schrieb:
> Die Antwort von "Antwort" ist so nicht richtig. Wenn wir von C
> Programmen reden, dann gibt es dort ein Überlauf Flag nicht. Nirgendwo
> ist sowas definiert. Also kann man das auch nicht abfragen.
>
> Ein anderer Punkt ist natürlich, das das C Programm ja in ein
> Assembler-Programm umgesetzt wird und auf einer konkreten CPU läuft.
> Deswegen und weil die viele CPUs bei einem Inkrement auch ein
> Überlauf-Flag setzen, ist es, insbesondere wenn man in ein C Programm
> Assemblerbefehle inkorporieren kann, zwar möglich, diese Flag
> abzufragen,

Speziell beim AVR kann man doch SREG abfragen. Das geht auch in C ohne 
Assembler-Befehle.

von Klaus W. (mfgkw)


Lesenswert?

nein

äh ja, du brauchst nichts zu befürchten.

von mar IO (Gast)


Lesenswert?

Michael Buesch schrieb:
> C-Experte schrieb:
>>> ich will einen Überlauf in C bewusst einsetzen
>>
>> Laut C-Standart ist das Ergebnis undefiniert.
>
> Das ist Unsinn. Der C Standar>>>D<<< definiert den Überlauf einer
> unsigned Variable ziemlich exakt.

An sowas kann ich mich auch erinnern irgendwann irgendwo gelesen zu 
haben. Man beachte, vorzeichenlos!

von Regler (Gast)


Lesenswert?

Michael Buesch schrieb:
> Der Compiler kümmert sich um das carry flag wo nötig.

Und da es eine 8-bit Variable ist, die inkrementiert wird, macht er das 
in dem Fall nicht, oder? Daher:

> Muss ich das selbst händisch zurücksetzen (da der Compiler das
> wahrscheinlich nicht automatisch macht!?) oder passiert das
> vollautomatisch, wenn es nicht abgefragt und eine neue Op ausgeführt
> wird?

und:

Muss ich einen bösen Bug im Programmablauf befürchten?

von Regler (Gast)


Lesenswert?

Markus schrieb:
> Speziell beim AVR kann man doch SREG abfragen. Das geht auch in C ohne
> Assembler-Befehle.

Ist mir völlig klar. Aber: was soll das bringen?
Ich weiß ja dass das Carry-Flag gesetzt sein wird.

Muss ich es händisch zurücksetzen ist die goldene Frage! Oder anders: 
Will nur wissen, was mit dem Carry-Flag passiert, wenn es NICHT 
abgefragt wird.

von Michael B. (mb_)


Lesenswert?

Markus schrieb:
> Speziell beim AVR kann man doch SREG abfragen. Das geht auch in C ohne
> Assembler-Befehle.

Das wird nur durch Zufall funktionieren, wenn überhaupt.

Beispiel:

a += 1
b = SREG

Niemand garantiert dir, dass zur zweiten Zeile das carry flag noch den 
Zustand von der "add" instruktion hat. Nein, auch nicht wenn interrupts 
abgeschaltet sind. Genauer gesagt garantiert auch niemand, dass 
überhaupt eine add instruktion verwendet wird. Der compiler könnte 
möglicherweise auch das ganze Konstrukt auflösen, weil vielleicht alles 
zur Compilezeit bekannt ist oder sonst eine andere beliebige 
Optimierung. Und dann kommt bei dem SREG nur nur zufälliges Gemüse raus.

Die einzige Möglichkeit ist es sowohl das add als auch das lesen des 
carry bits im inline-assembly auszuführen.

von Michael B. (mb_)


Lesenswert?

Regler schrieb:
> Muss ich es händisch zurücksetzen ist die goldene Frage! Oder anders:
> Will nur wissen, was mit dem Carry-Flag passiert, wenn es NICHT
> abgefragt wird.

Nichts. Du musst gar nichts machen. Der Überlauf einer unsigned Variable 
ist vollständig in C definiert und es passiert garantiert nichts 
Unvorhergesehenes.
Da es in C kein carry flag gibt, muss man es natürlich auch nicht 
zurücksetzen.

von Regler (Gast)


Lesenswert?

Habs gerade gefunden, hier:
http://www.mikrocontroller.net/articles/AVR-Tutorial:_Vergleiche

Zitat:
Überläufe, die durch Inkrementieren oder Dekrementieren (INC/DEC) 
erzeugt werden, beeinflussen das Carry-Flag jedoch nicht.

Damit hat sich die Antwort gefunden, da ich jetzt einfach mal davon 
ausgehe, dass der Compiler den ++-Operator nach INC übersetzt!

von Michael B. (mb_)


Lesenswert?

Regler schrieb:
> Damit hat sich die Antwort gefunden, da ich jetzt einfach mal davon
> ausgehe, dass der Compiler den ++-Operator nach INC übersetzt!

Da würde ich nicht von ausgehen.
Es spielt aber auch keine Rolle wie er es übersetzt. Die CPU Flags 
spielen in C keine Rolle und werden vom Compiler verwaltet (außer 
Spezialflags wie I, die der Compiler nicht antastet).

von Regler (Gast)


Lesenswert?

Michael Buesch schrieb:
> Da würde ich nicht von ausgehen.

So abwegig?

von Regler (Gast)


Lesenswert?

Danke an alle für die Hilfe! Wieder was gelernt!

von Michael B. (mb_)


Lesenswert?

Regler schrieb:
> Michael Buesch schrieb:
>> Da würde ich nicht von ausgehen.
>
> So abwegig?

Nein, aber er ergibt keinen sinn von C Ausdrücken auf generierten 
Assemblycode zu schließen.
Ich garantiere dir, dass ich zu jeder Annahme einen Compiler(version) 
finde dem diese Ahnahme egal ist und es anders macht. ;)

von Regler (Gast)


Lesenswert?

> Ich garantiere dir, dass ich zu jeder Annahme einen Compiler(version)
> finde dem diese Ahnahme egal ist und es anders macht. ;)

Das ist ja das Fiese! ;)

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.