Forum: PC-Programmierung Overflow, Carry?


von Overflow (Gast)


Lesenswert?

Habe ich das richtig verstanden:

Wenn man (z.B. in C) einen Integer definiert. Auf einem 16-Bit System. 
Dann hat man einen Wertebereich von -32.768 bis 32.767.
Wird ein Wert eingegeben der nicht mehr innerhalb dieses 
Werftenbereiches definiert ist, dann gibt den den Überlauf (Overflow) 
und der Datenbereich wird verlassen, sprich:
Nach 32.767 kommt wieder die -32.768 und es geht von vorne los.

Bei einem unsigned int auf dem selben Betriebssystem hätte man einen 
Wertebereich von 0 bis 65.535.
Beim Verlassen des Wertebereichs entsteht ein Übertrag (Carry).
Addiert man z.B. zu 65.530 die Zahl 10 hinzu, wäre der ausgegebene Wert 
5.

Ist das soweit richtig?
Wie kann man sich das technisch vorstellen?
Kann das gerade nur schwer begreifen und hoffe, es überhaupt irgendwie 
verstanden zu haben...

Was wäre dann übrigens der bekannte Stack Overflow?

: Wiederhergestellt durch Moderator
von MaWin (Gast)


Lesenswert?

Overflow schrieb:
> Ist das soweit richtig?

Bei vorzeichenbehafteten Typen ist der Überlauf in C Undefined Behavior.

von Wolfgang (Gast)


Lesenswert?

Overflow schrieb:
> Wie kann man sich das technisch vorstellen?

In dem 16-Bit Register ist kein Platz für mehr als Bits, d.h. die können 
nirgends abgelegt werden. Das Carry im Statusregister dient quasi als 
Verlängerung.

von (prx) A. K. (prx)


Lesenswert?

Overflow schrieb:
> Wie kann man sich das technisch vorstellen?

Wenn du dich mit dem Binärsystem schwer tust, denk dir einen 4-stelligen 
Dezimalrechner mit 0..9999 oder -5000..+4999.

von Lars R. (larsr)


Lesenswert?

Overflow schrieb:
> Wie kann man sich das technisch vorstellen?
> Kann das gerade nur schwer begreifen und hoffe, es überhaupt irgendwie
> verstanden zu haben...

Lasse dir mal mit dem Taschenrechner die einzelnen Bits ausgeben. Dann 
verstehst du es sofort.

von Georg A. (georga)


Lesenswert?

Overflow ist eigentlich ein nachgelagerter Effekt. Carry ist allgemein 
das Übertragsbit zwischen den Stellen und das Carry(Flag) ist wie von 
Wolfgang gesagt, das das aus der höchsten Bitstelle rauskommt und extra 
gemerkt wird.

Ob es einen Überlauf gibt, hängt von der Interpretation ab. Bei unsigned 
ist schon das Carry-Flag ein Über/Unterlauf (zB. 0xff + 1 = (1)0x00).

Bei signed ist es nicht so einfach, da wäre -1 + 1 = 0 OK (0xff+1 und 
C=1). Das Overflow-Flag wird daher aus einem Vergleich vom Carryflag und 
dem Carrybit in die höchste Stelle gebildet. Wenn die nicht gleich 
sind, ist in signed ein Überlauf entstanden.

> Was wäre dann übrigens der bekannte Stack Overflow?

Nein, das ist das "Ausgehen/Vollfüllen" eines bestimmten 
Speicherbereichs.

von Fpgakuechle K. (Gast)


Lesenswert?

Overflow schrieb:

> Was wäre dann übrigens der bekannte Stack Overflow?

Nein!

von c-hater (Gast)


Lesenswert?

Overflow schrieb:

> Habe ich das richtig verstanden:

Nein.

> Wenn man (z.B. in C) einen Integer definiert. Auf einem 16-Bit System.
> Dann hat man einen Wertebereich von -32.768 bis 32.767.

Das ja.

> Wird ein Wert eingegeben der nicht mehr innerhalb dieses
> Werftenbereiches definiert ist, dann gibt den den Überlauf (Overflow)
> und der Datenbereich wird verlassen

Nein. Bei einer "Eingabe" (sprich: Zuweisung), bei der der Wertebereich 
verlassen wird, aber es gibt eben keinen Überlauf. Genau das ist der 
C-Dreck!

Sprich: es wird nicht geprüft, ob die Zuweisung überhaupt möglich ist

Viel schlimmer ist aber: wenn man mit dem Kram rechnet, kann man 
ebenfalls die Grenzen des Bereichs verlassen. Das ist noch viel 
tödlicher und wird ebenfalls von dem C-Dreck nicht abgefangen, weil er 
nichtmal hier die Flags der CPU/MCU prüft, die das eindeutig anzeigen.

C ist Dreck!

> Wie kann man sich das technisch vorstellen?

Man lernt, wie das auf Maschinenebene funktioniert und sorgt dafür, dass 
der Scheiß überhaupt nicht passieren kann...

> Was wäre dann übrigens der bekannte Stack Overflow?

Hat damit rein garnix zu tun.

von Fpgakuechle K. (Gast)


Lesenswert?

Overflow schrieb:

> Wie kann man sich das technisch vorstellen?

Indem man sich den Assembloercode samt carry -flags anschaut .
 Da für nen 8 bit prozessor: 
https://www.xilinx.com/support/documentation/ip_documentation/ug129.pdf 
S.88f

von Fpgakuechle K. (Gast)


Lesenswert?

c-hater schrieb:

>> Was wäre dann übrigens der bekannte Stack Overflow?
>
> Hat damit rein garnix zu tun.

Genau, also von wegen 'bekannt'. Und was nicht bekannt ist, kann man 
googlen um damit bekannt gemacht zu werden:
https://www.pcwelt.de/ratgeber/Buffer-Overflow-So-funktioniert-ein-Pufferueberlauf-Die-Hacker-Bibel-4838377.html

von Irgend W. (Firma: egal) (irgendwer)


Lesenswert?

Georg A. schrieb:
> Overflow ist eigentlich ein nachgelagerter Effekt. Carry ist allgemein
> das Übertragsbit zwischen den Stellen und das Carry(Flag) ist wie von
> Wolfgang gesagt, das das aus der höchsten Bitstelle rauskommt und extra
> gemerkt wird.

Dabei sollte man beachten das C sowas wie eine Carry überhaupt nicht 
kennt sonder das dies ein reines Assembler/CPU konstruckt ist. Es ist 
also abhängig davon wie ein konkreter Compiler die C-Befehle in 
entsprechendes ASM übersetzte. Und da es eben keine Vorgaben im 
C-Standard gibt wie oder ob das überhaupt umzusetzen ist gilt daher 
folgendes:

MaWin schrieb:
> Bei vorzeichenbehafteten Typen ist der Überlauf in C Undefined Behavior.

von MaWin (Gast)


Lesenswert?

Fpgakuechle K. schrieb:
>> Was wäre dann übrigens der bekannte Stack Overflow?
>
> Nein!

Super Antwort auf eine Was-Frage. ;)

Ein Stack-Overflow ist der Überlauf des sogenannten Stapel- oder 
Kellerspeichers.
Es wird also mehr Speicher verwendet, als vorhanden/zugewiesen ist.

Was du hast ist hingegen ein Integerüberlauf bzw. Integer Overflow.

von Philipp Klaus K. (pkk)


Lesenswert?

Irgend W. schrieb:
>
> Dabei sollte man beachten das C sowas wie eine Carry überhaupt nicht
> kennt sonder das dies ein reines Assembler/CPU konstruckt ist.

Auch manche Architekturen, wie Alpha, kennen kein Carry-Bit.

>
> MaWin schrieb:
>> Bei vorzeichenbehafteten Typen ist der Überlauf in C Undefined Behavior.

Zusätzlich gibt es demnächst wohl noch chk_add etc. Damit hat man dann 
beim Überlauf kein undefiniertes Verhalten, sondern kann diesen anhand 
des Rückgabewerts erkennen.

Also z.B.
1
if(chk_add(&ergebnis, a,  b))
2
  fprintf(stderr, "Es gab einen Überlauf\n");

Wobei ergebnis, a und b Ganzzahlen sind.

von Fpgakuechle K. (Gast)


Lesenswert?

MaWin schrieb:
> Fpgakuechle K. schrieb:
>>> Was wäre dann übrigens der bekannte Stack Overflow?
>>
>> Nein!
>
> Super Antwort auf eine Was-Frage. ;)

Ein Satz im Konjunktiv ist IMHO keine Frage sondern eine dümmliche 
Floskel, bei der man, wegen der unexakt-feigen Formulierung einige 
Interpretationsfreiheit besitzt.

Hier "Ist Stack overflow das gleiche wie Overflow bei addition wie oben 
beschrieben". Klare Antwort -> Nein!

Dem TE ist hiermit geraten, bei seinen Fragen zur Programmierung ein 
Lenhrbuch  zu Computer-Architektur zu Rate zu ziehen und nicht ein 
Wörterbuch.

von Bauform B. (bauformb)


Lesenswert?

c-hater schrieb:
> C ist Dreck!

Irgendwie ist zur Zeit eine schlechte Jahreszeit für C. Ich hab' gerade 
das Vergnügen, ein Assemblerprogramm aus dem letzten Jahrtausend zu 
erweitern. Das klappt (bis jetzt?) so gut, dass ich mir dachte, man 
hätte niemals den Compiler erfinden dürfen. Dann hätten wir heute ganz 
andere Hardware-Architekturen, ohne Undefined Behavior. Vielleicht gäbe 
es Digital noch, oder Motorola, aber dafür kein Intel und ARM.

von Franz M. (elmo64)


Lesenswert?


von Wolfgang (Gast)


Lesenswert?

MaWin schrieb:
> Ein Stack-Overflow ist der Überlauf des sogenannten Stapel- oder
> Kellerspeichers.

Man könnte auch direkt sagen: Der Stackpointer (Stapelzeiger) verlässt 
den zulässigen Wertebereich. Der Speicher selbst kann nicht überlaufen.

von Profifahrer (Gast)


Lesenswert?

Statt Overflow und Carry, solltest du bei Ketchup und Curry bleiben.

von Fpgakuechle K. (Gast)


Lesenswert?

Wolfgang schrieb:

> Man könnte auch direkt sagen: Der Stackpointer (Stapelzeiger) verlässt
> den zulässigen Wertebereich. Der Speicher selbst kann nicht überlaufen.

Überlauf ist bei Stack-Overflow die falsche Wahl für einen exakten 
Begriff. Auch bei der Addition passt es nicht wirklich.

Überlaufen tuen Zähler, die nach "1111" wieder bei "0000" anfangen. Das 
wurde auch mal "wrap around" genannt, also "Überschlagen" was ich 
persönlich als passneder empfinde - der Ausgabe-Bereich fängt wieder neu 
von unten an.

Beim Buffer-Über-/Unterlauf daggeen wird nicht zwangsläufig wieder von 
Vorn begonnen, sondern es wird eine Bereichsgrenze illegaler Weise 
überschritten (oder auch unterschritten). Wie das konkret realisiert 
ist, hängt vom jeweiligen Prozessor ab. Bei denen mit segmentierte 
Addresse (8086) kann es dabei zu einem Wrap-around kommen.

Und bei der Addition gibt es auch gerne die Möglichkeiten der Sättigung 
(Saturation); überschreitet die Summe den maximal darstellbaren Bereich 
wird ein fixer Wert (der maximal zulässiger Wert) ausgegeben.

Findet man gerne in DSP's

https://microchipdeveloper.com/dsp0201:overflow-and-saturation
https://de.wikipedia.org/wiki/S%C3%A4ttigungsarithmetik

von Philipp Klaus K. (pkk)


Lesenswert?

Fpgakuechle K. schrieb:
> Überlaufen tuen Zähler, die nach "1111" wieder bei "0000" anfangen. Das
> wurde auch mal "wrap around" genannt, also "Überschlagen" was ich
> persönlich als passneder empfinde - der Ausgabe-Bereich fängt wieder neu
> von unten an.

Wobei C eben zwischen Overflow (bei vorzeichenbehafteten Ganzzahlen - 
undefiniertes Verhalten) und Wrapping (bei vorzeichenlosen Ganzzahlen - 
definiertes Ergebnis) unterscheidet.

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

Fpgakuechle K. schrieb:
> Überlauf ist bei Stack-Overflow die falsche Wahl für einen exakten
> Begriff.

Es ist der richtige Begriff. Er beschreibt hier genauso wie bei Rechnung 
mit Zahlen eine arithmetische Situation - aber kein bestimmtes dabei 
auftretendes Verhalten. Der Begriff "wrap around" hingegen beschreibt 
ein bei Überlauf mögliches Verhalten. Daher ist der Begriff Überlauf 
auch auf Speicherbereiche anwendbar.

Überlauf bei Arithmetik:
 Das Ergebnis liegt ausserhalb des definierten Bereichs [A .. B].
Überlauf im Speicher:
 Die Adresse liegt ausserhalb des definierten Bereichs [A .. B].

> Überlaufen tuen Zähler, die nach "1111" wieder bei "0000" anfangen. Das
> wurde auch mal "wrap around" genannt, also "Überschlagen" was ich
> persönlich als passneder empfinde - der Ausgabe-Bereich fängt wieder neu
> von unten an.

Das Verhalten bei Überlauf von Integers mit Vorzeichen ist in C 
undefiniert. Das trägt dem Umstand Rechnung, dass es auch mit Hardware 
einsetzbar sein soll, bei der eben kein wrap around auftritt. Sondern 
beispielsweise eine Exception.

Es gibt Programmiersprachen, die für Integers definierbare Wertebereiche 
vorsehen. Angefangen von PL/I mit in gewissen Grenzen frei wählbarer 
Angabe von Bits, bis zu Pascal/Ada mit explizitem Wertebereich. Da in 
solchen Fällen kein Zusammenhang zwischen dem definierten Bereich und 
der zugrundeliegenden Arithmetik der Hardware besteht, kann es zwar auch 
hier einen Überlauf geben, aber kein scheinbar "natürliches" 
Überlaufverhalten.

Es gibt auch saturierte Arithmetik, dann gilt 32767+1 => 32767. Das ist 
in C für normale Integers zwar nicht üblich, wäre aber bei Typen mit 
Vorzeichen zulässig und immer noch vom Begriff "Überlauf" abgedeckt. In 
IEEE Fliesskommadarstellung hat man für das Überlaufverhalten eine 
spezielle Darstellung für "unendlich" definiert.

: Bearbeitet durch User
von Georg (Gast)


Lesenswert?

Fpgakuechle K. schrieb:
> Überlaufen tuen Zähler, die nach "1111" wieder bei "0000" anfangen

Das ist falscher Sprachgebrauch. Wenn du in ein Glas mehr Bier schüütest 
als reinpasst, ist das Glas doch nicht plötzlich leer, sondern es läuft 
eben über, ist aber voll. Bei meinen Gläsern und meinem Bier jedenfalls.

Georg

von (prx) A. K. (prx)


Lesenswert?

Georg schrieb:
> Das ist falscher Sprachgebrauch. Wenn du in ein Glas mehr Bier schüütest
> als reinpasst, ist das Glas doch nicht plötzlich leer, sondern es läuft
> eben über, ist aber voll. Bei meinen Gläsern und meinem Bier jedenfalls.

Schönes Beispiel für Sättigungsarithmetik.

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

Overflow schrieb:
> Wird ein Wert eingegeben der nicht mehr innerhalb dieses
> Werftenbereiches definiert ist, dann gibt den den Überlauf (Overflow)
> und der Datenbereich wird verlassen, sprich:

Nö, das Laden eines Registers setzt keinerlei Flags.
Flags werden nur als Ergebnis einer Operation gesetzt. Damit hat man 
eine elegante Möglichkeit, Operationen auszuführen, die den Wertebereich 
eines Registers übersteigen. Das Carry wird einfach zum nächst 
höherwertigen Register addiert bzw. abgezogen. Du kannst also problemlos 
Operationen z.B.  über 128 Bit Werte ausführen, durch Kaskadieren der 
entsprechenden Operationen über mehrere Register bzw. RAM-Plätze.

von (prx) A. K. (prx)


Lesenswert?

Peter D. schrieb:
> Nö, das Laden eines Registers setzt keinerlei Flags.

Oh doch, z.B. bei 68xx(x), 6502, TMS9900, TMS7000.

: Bearbeitet durch User
von MaWin (Gast)


Lesenswert?

(prx) A. K. schrieb:
> Oh doch, z.B. bei 68xx(x), 6502, TMS9900, TMS7000.

Auch overflow und carry? Welchen Sinn sollte das ergeben?

von (prx) A. K. (prx)


Lesenswert?

MaWin schrieb:
> Auch overflow und carry? Welchen Sinn sollte das ergeben?

Man kann mehrere Flags zu einer stets gemeinsam gesetzten Statusgruppe 
zusammenfassen, und sei es mit 0 für V und C. Andere trennen die Flags 
in solche, bei denen es Sinn ergibt, wie Zero und Sign, während andere 
Flags nur bei ALU-Operationen gesetzt werden.

68000 hat deshalb gleich 2 Carry-Flags. Das C-Flag als Teil der 
NZVC-Statusgruppe, und zusätzlich das bei Add-With-Carry (ADDX) genutzte 
X-Flag.

TI hat es bei den TMS7000 allerdings besonders dusselig hingekriegt, 
denn da löscht ein Ladebefehl das Carry. Ist halt einfacher, wenn immer 
alle 3 Statusflags gesetzt werden, ob sinnvoll oder nicht. Eine Sequenz 
wie ADD,LDA,ADC ist also nicht drin, keine Ahnung wie man das damals 
machte.

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

Auch nicht besonders sinnvoll ist die Handhabung von Carry bei x86. Bei 
Shift/Rotate-Operationen wird es nur gesetzt, wenn die Count != 0 ist, 
bleibt sonst unverändert. Darüber haben seit den spekulativen OOO-Cores 
Mitte der 90er sämtliche Generationen von Prozessorentwicklern geflucht. 
Denn dadurch entsteht eine bremsende Abhängigkeit vom vorherigen Befehl 
mit C-Resultat, weil das C ggf durchgereicht werden muss - oder man 
spekuliert auf != 0 und wiederholt ggf den Befehl (AMD K5).

von David V. (dadido3)


Lesenswert?

Overflow schrieb:
> Bei einem unsigned int auf dem selben Betriebssystem hätte man einen
> Wertebereich von 0 bis 65.535.
> Beim Verlassen des Wertebereichs entsteht ein Übertrag (Carry).
> Addiert man z.B. zu 65.530 die Zahl 10 hinzu, wäre der ausgegebene Wert
> 5.

Mal ganz davon abgesehen ob "overflow" der korrekte Begriff ist, oder ob 
das "undefined behavior" in C ist: Der ausgegebene Wert müsste 4 anstatt 
5 sein.

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

MaWin schrieb:
> Auch overflow und carry? Welchen Sinn sollte das ergeben?

Overflow zu löschen ergibt Sinn, weil man dann bedingte Sprungbefehle 
für Vergleiche mit Vorzeichen nutzen kann, für die Bedingungen >0 oder 
<=0. Stören tut es nicht, anders als bei Carry (s.o.).

: Bearbeitet durch User
von Rolf M. (rmagnus)


Lesenswert?

Philipp Klaus K. schrieb:
> Fpgakuechle K. schrieb:
>> Überlaufen tuen Zähler, die nach "1111" wieder bei "0000" anfangen. Das
>> wurde auch mal "wrap around" genannt, also "Überschlagen" was ich
>> persönlich als passneder empfinde - der Ausgabe-Bereich fängt wieder neu
>> von unten an.
>
> Wobei C eben zwischen Overflow (bei vorzeichenbehafteten Ganzzahlen -
> undefiniertes Verhalten) und Wrapping (bei vorzeichenlosen Ganzzahlen -
> definiertes Ergebnis) unterscheidet.

Naja, diese Unterscheidung sieht dann so aus: Das Verhalten bei einem 
Integer-Overflow ist grundsätzlich undefiniert. Bei vorzeichenlosen 
Typen kann allerdings kein Overflow eintreten, weil jede Berechnung 
modulo größtmöglicher Wert + 1 gerechnet wird.

: Bearbeitet durch User
von c-hater (Gast)


Lesenswert?

Rolf M. schrieb:

> Bei vorzeichenlosen
> Typen kann allerdings kein Overflow eintreten, weil jede Berechnung
> modulo größtmöglicher Wert + 1 gerechnet wird.

Häh? Weil implizit ein wrap around passiert, kann es keine Overflows 
geben?

Das ist starker Tobak. Nur C-Gläubige erfrechen sich, einen derartig 
offensichtlichen Schwachsinn ernsthaft zu äußern.

Realistisch betrachtachtet ist es vielmehr so: natürlich passiert hier 
ggf. ein Overflow. Nur diese verschissene, untaugliche Sprache bietet 
keine effiziente Möglichkeit, flexibel darauf zu reagieren.

Eben weil es keine Möglichkeit gibt, effizent mit den in praktisch jeder 
heute noch relevanten Hardware existierenden Hardwareflags zu 
interagieren.

Untauglicher Vollrotz.

von (prx) A. K. (prx)


Lesenswert?

c-hater schrieb:
> Häh? Weil implizit ein wrap around passiert, kann es keine Overflows
> geben?

Modulo-Arithmetik kann nicht überlaufen. Und so ist sie definiert.

> Das ist starker Tobak. Nur C-Gläubige erfrechen sich, einen derartig
> offensichtlichen Schwachsinn ernsthaft zu äußern.

Das steht so ziemlich wörtlich im C Standard. Egal wie sehr du den 
hasst.

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

c-hater schrieb:
> Realistisch betrachtachtet ist es vielmehr so: natürlich passiert hier
> ggf. ein Overflow

Overflow in Hardware ist Technik, Modulo-Arithmetik ist Mathematik. 
Verschiedene Ebenen. Das muss sich also nicht widersprechen.

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

c-hater schrieb:
> mit den in praktisch jeder
> heute noch relevanten Hardware existierenden Hardwareflags

Ganz so selbstverständlich sind diese klassischen Flags im 
Statusregister nicht. MIPS, PowerPC und RISC-V arbeiten anders.

: Bearbeitet durch User
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

c-hater schrieb:
> Das ist noch viel tödlicher und wird ebenfalls von dem C-Dreck nicht
> abgefangen, weil er nichtmal hier die Flags der CPU/MCU prüft, die das
> eindeutig anzeigen.

Assembler prüft auch keine CPU-Flags, solange Du sie als Programmierer 
nicht explizit testest. Auch hier kann ich Werte addieren oder 
multiplizieren, wo die Ergebnisse eindeutig den vorgesehenen 
Wertebereich verlassen. Gut, Du kannst hier CPU-Flags testen. Wenn Du es 
aber nicht machst, kommt hier derselbe Unsinn raus.

Von daher ist Assembler keinen Deut besser.

Aber:

Ein "gutes" ASM-Programm macht erst die Operation und testet 
anschließend die Flags, um herauszufinden, ob das Ergebnis anders als 
vorgesehen zu interpretieren ist, ein gutes C-Programm prüft das halt 
vorher und weiß dann schon vor der Operation, wie das Ergebnis zu 
interpretieren wäre. Und eventuell führt es dann erst gar nicht die 
Operation aus, sondern macht es dann direkt besser, statt den Trial- and 
Error-Weg zu wählen.

Auch von daher ist Assembler keinen Deut besser.

: Bearbeitet durch Moderator
von MaWin (Gast)


Lesenswert?

Frank M. schrieb:
> ein gutes C-Programm prüft das halt vorher

Das ist nur leider in C nicht immer ganz trivial umzusetzen, ohne dass 
man gleich den nächsten UB-Fall unbewusst auslöst.

Moderne Sprachen haben deshalb explizite Unterstützung für 
Überlauferkennung, Saturierung und Wraparound.
Dass C das nicht hat, ist ein großes Manko.
Wie man dann zu dem Schluss kommen kann, Asm wäre dort besser, kann ich 
allerdings auch nicht nachvollziehen. :)

von (prx) A. K. (prx)


Lesenswert?

MaWin schrieb:
> Wie man dann zu dem Schluss kommen kann, Asm wäre dort besser, kann ich
> allerdings auch nicht nachvollziehen. :)

Konsequente Nutzung von Assembler vermeidet Wertebereichsprobleme bei 
Übersetzung bestehender Programme auf völlig anderen Maschinen. ;-)

: Bearbeitet durch User
von heute *relevanter* Digitaltechniker (Gast)


Lesenswert?

> Eben weil es keine Möglichkeit gibt, effizent mit den in praktisch jeder
> heute noch relevanten Hardware existierenden Hardwareflags zu
> interagieren.

FPGAs + VHDL/Verilog hast du aber schon mal von gehört?

Damit kann sich heute jeder nach Lust und Laune CPU-Arschitekturen 
implementieren, egal ob ohne/mit/mitmehreren Statusflags und Logik + 
Kontrolle + Effizienz darüber wie er will.
Das ganze obendrein noch ohne auf legacy-Designfehlentscheide der 
Vergangenheit Rücksicht nehmen zu müssen.

Also weg von deinem überpauschalisierenden Gejammer, wieder zurück zum 
Sachlichen Kern der Diskussion dieses Threads. Danke.

NB: schreib doch mal eine Einführung in heute verfügbare 
RISC-V-Assemblerprogrammierung, die Interessenten nicht auf den 
(C-)Holzweg verleiten.

von Josef G. (bome) (Gast)


Lesenswert?

Zwei gleichlange singed-Werte kann man vergleichen, indem man beide
Vorzeichenbits invertiert und dann den Vergleich mittels Carry
macht wie bei unsigned-Werten. So hab ich mir das überlegt.

Aber geht es auch kürzer mittels Overflow?

von chris_ (Gast)


Lesenswert?

heute relevanter Digitaltechniker (Gast)
>NB: schreib doch mal eine Einführung in heute verfügbare
>RISC-V-Assemblerprogrammierung, die Interessenten nicht auf den
>(C-)Holzweg verleiten.

Du kannst ja hier mal anfangen:
Beitrag "RISC-V Gnu Assembler"

von (prx) A. K. (prx)


Lesenswert?

Josef G. (bome) schrieb:
> Aber geht es auch kürzer mittels Overflow?

Sprungbedingungen für Vergleiche mit Vorzeichen sind der Hauptzweck des 
Overflow-Flags.

von c-hater (Gast)


Lesenswert?

Frank M. schrieb:

> Assembler prüft auch keine CPU-Flags, solange Du sie als Programmierer
> nicht explizit testest.

Natürlich nicht. Der Vorteil gegenüber C ist halt: ich KANN sie nutzen 
und zwar sehr einfach und auch einigermaßen effizient.

> Ein "gutes" ASM-Programm macht erst die Operation und testet
> anschließend die Flags, um herauszufinden, ob das Ergebnis anders als
> vorgesehen zu interpretieren ist, ein gutes C-Programm prüft das halt
> vorher und weiß dann schon vor der Operation, wie das Ergebnis zu
> interpretieren wäre.

Oops??? Neben allem sonstigen Schwachsinn, der über C-Features 
verbreitet wird, hat es jetzt auch noch die Möglichlichkeit, in die 
Zukunft zu linsen?

Wenn ich zwei Integers habe, diese aus einer äußeren Quelle mit Werten 
befülle und dann addiere, kann C VORAB feststellen, ob es dabei zu 
einem Überlauf kommen wird?

Du machst dich lächerlich.

von Klaus W. (mfgkw)


Lesenswert?

c-hater schrieb:
> kann C VORAB feststellen, ob es dabei zu
> einem Überlauf kommen wird?

Von selbst macht der Compiler das nicht, man kann es aber testen.

: Bearbeitet durch User
von MaWin (Gast)


Lesenswert?

Klaus W. schrieb:
> Von selbst macht der Compiler das nicht, man kann es aber testen.

Ja dann mache doch mal ein Beispiel für die Addition.

von Klaus W. (mfgkw)


Lesenswert?

ich habe es mal für einen Test hinterher geschrieben, vorher ginge 
analog (dann müsste man aber entweder das Ergebnis zwischenspeichern 
oder im Fehlerfall verlieren):
1
#include <stddef.h>
2
#include <stdio.h>
3
#include <stdint.h>
4
5
uint8_t f1()
6
{
7
  return 25;
8
}
9
10
uint8_t f2()
11
{
12
  return 250;
13
}
14
15
int main( int nargs, char **args )
16
{
17
  uint8_t summand1 = f1();
18
  uint8_t summand2 = f2();
19
20
  uint8_t ergebnis = summand1 + summand2;
21
  if( ergebnis<summand1 ) // oder summand2, egal
22
  {
23
    // das war ein Überlauf...
24
    fprintf( stderr, "oioioi, ein Überlauf...\n" );
25
  }
26
  else
27
  {
28
    // alles ok, ergebnis ist die Summe von summand1 und summand2...
29
    printf( "alles gut!\n" );
30
    // ...
31
  }
32
33
  return 0;
34
}

Für andere Typen analog...

(Eine andere Variante wäre, im nächstgrößeren Typ zu rechnen, dort zu 
testen, und im Erfolgsfall zurück zu konvertieren - kostet aber unnötig 
Rechenzeit.)

: Bearbeitet durch User
von MaWin (Gast)


Lesenswert?

Klaus W. schrieb:
> vorher ginge analog

Haha. Netter Versuch.
Wie würde das denn "analog" aussehen? Also konkret der Test, ohne die 
Addition zu machen.

von Klaus W. (mfgkw)


Lesenswert?

Wieso ohne Addition?
Damit man sie nicht zweimal machen muß eben zwischenspeichern.

Worauf willst du raus? Daß man in C mit Überlauf leben muß?
Bist du der Cousin vom c-hater?

von MaWin (Gast)


Lesenswert?

Klaus W. schrieb:
> Worauf willst du raus?

> ein gutes C-Programm prüft das halt
> vorher und weiß dann schon vor der Operation, wie das Ergebnis zu
> interpretieren wäre.

von c-hater (Gast)


Lesenswert?

Klaus W. schrieb:

>   uint8_t summand1 = f1();
>   uint8_t summand2 = f2();
>
>   uint8_t ergebnis = summand1 + summand2;
>   if( ergebnis<summand1 ) // oder summand2, egal
>   {
>     // das war ein Überlauf...
>     fprintf( stderr, "oioioi, ein Überlauf...\n" );
>   }

Das ist aber HINTERHER und nicht VORHER, wie Frank M. behauptet hat!

Und es ist ineffizient (im Vergleich zu einem direkten Test der Flags 
nach der Operation). Aber das war nicht der Punkt, hier könnte eventuell 
die Optimierung helfen. Müsste man sich mal anschauen, was der Compiler 
letztlich tatsächlich baut.

Der Punkt war die behauptete Fähigkeit, an der Kausalität vorbei 
hantieren zu können. Jedem, dem sie nicht in's Gehirn geschissen haben, 
ist klar, das das definitiv eine freche Lüge war. Und die konnte einfach 
nicht unwidersprochen bleiben.

von (prx) A. K. (prx)


Lesenswert?

c-hater schrieb:
> Müsste man sich mal anschauen, was der Compiler
> letztlich tatsächlich baut.

Er testet das C-Flag der Addition. ;-)
1
unsigned f(unsigned v1, unsigned v2)
2
{
3
  unsigned r = v1 + v2;
4
  if (r < v1) {
5
    return 0;
6
  }
7
  return r;
8
}
1
f:  adds  r0, r0, r1
2
    movcs r0, #0
3
    bx    lr
4
5
f:  addl    %esi, %edi
6
    movl    $0, %eax
7
    cmovnc  %edi, %eax
8
    ret

: Bearbeitet durch User
von Josef G. (bome) (Gast)


Lesenswert?

(prx) A. K. schrieb:
> Josef G. (bome) schrieb:
>> Aber geht es auch kürzer mittels Overflow?
>
> Sprungbedingungen für Vergleiche mit Vorzeichen
> sind der Hauptzweck des Overflow-Flags.

Mag schon sein, aber wie geht es denn jetzt?

Fiktiver Befehl: cmp r1,r2
wobei die Flags gesetzt werden wie bei Berechnung von r1 minus r2

Wenn kein Overflow, dann ist r1 größergleich r2 genau dann wenn das
resultierende Sign den Wert Null hat. Was ist, wenn sich ein
Overflow ergibt? Ist es dann immer genau umgekehrt?

von (prx) A. K. (prx)


Lesenswert?

Josef G. (bome) schrieb:
> Mag schon sein, aber wie geht es denn jetzt?

=> Befehlsbeschreibung AVR, 6800, 68000, 8086, ...

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

c-hater schrieb:
> Frank M. schrieb:
>
>> Assembler prüft auch keine CPU-Flags, solange Du sie als Programmierer
>> nicht explizit testest.
>
> Natürlich nicht. Der Vorteil gegenüber C ist halt: ich KANN sie nutzen
> und zwar sehr einfach und auch einigermaßen effizient.

Ich KANN sie auch in C nutzen, siehe obiges Beispiel Addition und 
Prüfung, ob r < v1. A.K. (prx) konnte sogar zeigen, dass der Compiler 
das Carry-Bit prüft.

>> Ein "gutes" ASM-Programm macht erst die Operation und testet
>> anschließend die Flags, um herauszufinden, ob das Ergebnis anders als
>> vorgesehen zu interpretieren ist, ein gutes C-Programm prüft das halt
>> vorher und weiß dann schon vor der Operation, wie das Ergebnis zu
>> interpretieren wäre.
>
> Oops??? Neben allem sonstigen Schwachsinn, der über C-Features
> verbreitet wird, hat es jetzt auch noch die Möglichlichkeit, in die
> Zukunft zu linsen?
> Wenn ich zwei Integers habe, diese aus einer äußeren Quelle mit Werten
> befülle und dann addiere, kann C VORAB feststellen, ob es dabei zu einem
> Überlauf kommen wird?
> Du machst dich lächerlich.

Einfaches Beispiel: Multiplikation von zwei Variablen, wobei ich das 
Ergebnis in einer unsigned-Variablen speichern will. Ich kann durchaus 
VORHER prüfen, ob genau einer der beiden Variablen vorzeichenbehaftet 
ist und deshalb bei der Multiplikation Unsinn rauskommt.

Du kannst Dir auch mal einen x-beliebigen Z80-Emulator in C mal 
anschauen - zum Beispiel STECCY. Auch der kann bei völlig 
unbekannten Operanden alle CPU-Flags wie C,Z,N usw. in C "berechnen". 
Das ist überhaupt kein Problem.

Außerdem habe ich geschrieben (was Du beim Zitieren offenbar bewusst 
unterschlagen hast):

> Und eventuell führt es dann erst gar nicht die Operation aus,
> sondern macht es dann direkt besser, statt den Trial- and Error-Weg
> zu wählen.

Betonung liegt auf "eventuell": Ich habe den Trial-And-Error-Weg auch 
für C nicht prinzipiell ausgeschlossen, siehe obiges Beispiel r < v1.

Das obige Beispiel mit der Multiplikation zeigt, dass man in bestimmten 
Fällen auch VORHER entscheiden kann, ob man die Operation ausführt oder 
nicht.

Okay, das kannst Du in Assembler natürlich auch ;-)

Aber das ändert nichts an meiner Aussage:

>   Assembler ist da keinen Deut besser als C

Beachte bitte: Ich habe NICHT geschrieben, dass in diesem Kontext C 
besser wäre. Offenbar hast Du aber genau DAS rausgelesen.

In anderen Belangen ist aber C deutlich besser als Assembler:

Ein AVR-Assembler-Programm läuft nicht auf einem STM32. Ein C-Programm 
kann man aber durchaus so codieren, dass es sowohl auf STM32, ATmega, 
ATtiny, PIC, ESP8266, MK20DX256VLH7, LPC1347, LPC4088 und anderen 
µC-Familien läuft. Als Assembler-Programmierer müsstest Du das Programm 
X-mal neu schreiben - wenn die Lebenszeit dazu überhaupt reicht.

Fazit: In Assembler programmieren ist Lebenszeitverschwendung.

Damit ist Assembler für mich von vornherein raus - egal wie oft Du 
betonst, wie toll CPU-Flags doch sind.

P.S.

Noch ein kleiner Tipp:

Formulierungen wie "Schwachsinn" oder "Du machst Dich lächerlich" tragen 
genau NULL zu einer Diskussion bei. Sie zeigen lediglich, dass Deine 
Argumente auf wackligen Füßen stehen, die Du dann mit vollkommen 
unzulänglichen Werkzeugen wie Rundumschlängen unterstreichen musst. Der 
Eindruck, den Du damit suggerieren willst, bewirkt aber genau das 
Gegenteil.

Frage: Habe ich irgendwo in meiner Antwort auf Deinen Beitrag versucht, 
persönlich zu werden? Ich kann mich nicht erinnern. Von daher bitte ich 
Dich höflich, sachlich zu bleiben - wie es sich für erwachsene Menschen 
gehört.

: Bearbeitet durch Moderator
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.