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?
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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-saturationhttps://de.wikipedia.org/wiki/S%C3%A4ttigungsarithmetik
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.
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.
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
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.
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.
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.
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).
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.
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.).
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.
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.
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.
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.
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.
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.
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. :)
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. ;-)
> 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.
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?
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"
Josef G. (bome) schrieb:> Aber geht es auch kürzer mittels Overflow?
Sprungbedingungen für Vergleiche mit Vorzeichen sind der Hauptzweck des
Overflow-Flags.
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.
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.
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_tf1()
6
{
7
return25;
8
}
9
10
uint8_tf2()
11
{
12
return250;
13
}
14
15
intmain(intnargs,char**args)
16
{
17
uint8_tsummand1=f1();
18
uint8_tsummand2=f2();
19
20
uint8_tergebnis=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
return0;
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.)
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?
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.
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.
(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?
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.