Warum kann PB kein unsigned long bzw. int ?
-
- Beiträge: 75
- Registriert: 17.01.2018 08:52
- Computerausstattung: Windows 11 64 bit, i7, 16GB RAM
- Wohnort: Wesertal in Nordhessen
Warum kann PB kein unsigned long bzw. int ?
Moin,
ich habe keine Lust, im englischen Forum rumzusuchen, vielleicht weiss es jemand aus dem Forum:
Why the hell kann PB kein unsigned bei Datentypen, die >= Long sind ???
Kann man unsigned simulieren ?
Gute Nacht.
ich habe keine Lust, im englischen Forum rumzusuchen, vielleicht weiss es jemand aus dem Forum:
Why the hell kann PB kein unsigned bei Datentypen, die >= Long sind ???
Kann man unsigned simulieren ?
Gute Nacht.
formerly known as bizzl
- tft
- Beiträge: 605
- Registriert: 08.09.2004 20:18
- Computerausstattung: GTX Titan , i9 9900K , 32 GB Ram , 500 GB SSD , 3 ASUS FullHD Monitore and more
- Wohnort: Dachsen
- Kontaktdaten:
Re: Warum kann PB kein unsigned long bzw. int ?
mmmmmmmmm .........
Wenn du grössere ganze Zahlen als 9.223.372.036.854.775.807 (.q) brauchst ......... läuft glaub ich etwas falsch. Dir stehen immerhin 63 Bit zur Verfügung.
Gruss TFT
Wenn du grössere ganze Zahlen als 9.223.372.036.854.775.807 (.q) brauchst ......... läuft glaub ich etwas falsch. Dir stehen immerhin 63 Bit zur Verfügung.
Gruss TFT
TFT seid 1989 , Turgut Frank Temucin , Dachsen/Berlin/Antalya
Aktuelles Projekte : Driving School Evergarden
YouTube : Pure Basic to go
FaceBook : Temuçin SourceMAgic Games
DISCORD : SourceMagic
W10 , i9 9900K ,32 GB Ram , GTX Titan , 3 Monitore FHD
ARDUINO Freak
Aktuelles Projekte : Driving School Evergarden
YouTube : Pure Basic to go
FaceBook : Temuçin SourceMAgic Games
DISCORD : SourceMagic
W10 , i9 9900K ,32 GB Ram , GTX Titan , 3 Monitore FHD
ARDUINO Freak
Re: Warum kann PB kein unsigned long bzw. int ?
Wurde nicht mit aufgenommen und fehlt manchmal ...
Mathematisch ist es bei Addition und Subtration das Vorzeichen nicht relevant. Nur die Ausgabe und die Vergleiche müssen angepasst werden.
Für die Vergleiche als Unsigned habe ich schon mal dies als ASM umgesetzt
Link: Unsigned Compare
Erweiterung für Bit Funktionen findest du hier
Link: Bitshift and Rotation
Mathematisch ist es bei Addition und Subtration das Vorzeichen nicht relevant. Nur die Ausgabe und die Vergleiche müssen angepasst werden.
Code: Alles auswählen
a.l = $80000000
Debug Str(a)
Debug StrU(a, #PB_Long)
a + 1
Debug Str(a)
Debug StrU(a, #PB_Long)
Link: Unsigned Compare
Erweiterung für Bit Funktionen findest du hier
Link: Bitshift and Rotation
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Re: Warum kann PB kein unsigned long bzw. int ?
Hallo berie!
Das Problem ist das ein Vergleich oder eine Berechnungen mit gemischten Wertebereichen (unsigned long vs long) zu unerwarteten Problemen führt.
Lese dazu einmal diesen Beitrag:
https://www.purebasic.fr/english/viewto ... f=3&t=6896
Unter C würde man z.B. bei diesem simplen Beispiel eigentlich rein logisch etwas anderes erwarten.
PureBasic führt viele interne Konvertierungen durch und da stören diese Unterschiede.
Das ganze Thema ist echt komplex und teilweise verwirrend.
Diese Erklärung trifft für x86 (32bit) zu und ist auf x64 erweiterbar.
Daher gibt es auch ein .w und einen .u Typ, aber keinen unsigned long Typ.
Bei .w und .u wird anscheinend (wenn ich das richtig verstanden habe) der Speicherbereich bei Vergleiche auf ein INT erhöht und nur mit signed (Vorzeichen) verglichen.
Und zum Schluss:
Wenn du nicht auf die 4 Byte beschränkt bist, dann nehme einfach z.B. ein QUAD-Typ.
Das Problem ist das ein Vergleich oder eine Berechnungen mit gemischten Wertebereichen (unsigned long vs long) zu unerwarteten Problemen führt.
Lese dazu einmal diesen Beitrag:
https://www.purebasic.fr/english/viewto ... f=3&t=6896
Unter C würde man z.B. bei diesem simplen Beispiel eigentlich rein logisch etwas anderes erwarten.
Code: Alles auswählen
#include <stdlib.h>
#include <stdio.h>
int main()
{
unsigned int one = 1;
int minus_one = -1;
if(one < minus_one)
printf("Wahr!");
return 0;
}
Das ganze Thema ist echt komplex und teilweise verwirrend.
Diese Erklärung trifft für x86 (32bit) zu und ist auf x64 erweiterbar.
Das Schlüsselwort ist: "Integer-Promotion-Rules"Ein Short hat eine Bitbreite von 16.
Wertebereich von -32768 bis+32767
Der int hat 32 Bits also bei einem signed int -2147483648 bis +2147483647
-1 wird in signed 16 Bit als 0xFFFF dargestellt.
-1 mit 32 Bit ist 0xFFFFFFFF
+12 ist in 16 Bit 0x000C
+12 in 32 Bit ist 0x00000000C
Die Abfrage:
if (0xFFFF < 0x000C) würde FALSE ergeben, wenn die Werte ohne Vorzeichen behandele würden,
denn 65535 ist NICHT kleiner als 12
TRUE wenn die Vorzeichen beachtet würden, weil -1 nunmal kleiner ist als +12.
Das Ergebnis des Compilers ist richtig, er liefert TRUE, hat also anscheinend das Vorzeichen richtig beachtet.
Würde er ohne Vorzeichen arbeiten wäre das Ergebnis FALSE weil 65535 NICHT kleiner ist als 12
Also ist das Ergebnis einwandfrei bei 16 Bit Operationen.
Nun der Fall für 32 Bit:
if (0xFFFFFFFF < 0x000000C) würde FALSE ergeben, wenn die Werte ohne Vorzeichen behandele würden.
TRUE wenn die Vorzeichen beachte würden.
Das Ergebnis des Compilers ist aber FALSCH, er behandelt das Vorzeichen anscheinend nicht
und deshalb ist 4294967296 nicht kleiner als 12 und damit liefert er FALSE, was halt FALSCH ist.
...Weiter gedacht...
'<' ist ein normaler Operator wie auch '+', '-', etc. Das bedeutet, dass für ihn auch die Integer-Promotion-Rules gelten. Im wesentlichen ist das:
1) Die Typen der Operanden werden auf die selbe Größe gebracht. Der Größte "gibt den Takt vor", mindestens aber int.
2) Haben die Typen bereits die selbe Größe, aber eine unterschiedliche Signedness, wird in unsigned gerechnet.
Bei den int-Operanden sorgt 2) für das unerwartete Ergebnis.
Bei den short-Operanden spielt 2) keine Rolle mehr, nachdem 1) angewendet wurde.
Daher gibt es auch ein .w und einen .u Typ, aber keinen unsigned long Typ.
Bei .w und .u wird anscheinend (wenn ich das richtig verstanden habe) der Speicherbereich bei Vergleiche auf ein INT erhöht und nur mit signed (Vorzeichen) verglichen.
Und zum Schluss:
Wenn du nicht auf die 4 Byte beschränkt bist, dann nehme einfach z.B. ein QUAD-Typ.
Code: Alles auswählen
Define var1.u = $FFFF ;Unsigned (max. positiver Wert)
Define var2.w = $FFFF >> 1 ;Signed (max. positiver Wert)
Define var3.q = $FFFFFFFF ;max. Wert eines vorzeichenlosen LONG passt problemlos in ein QUAD.
Define var4.l = $FFFFFFFF >> 1 ;Signed (max. positiver Wert)
Debug "VAR1: "+var1
Debug "VAR2: "+var2
Debug "VAR3: "+var3
Debug "VAR4: "+var4
Zuletzt geändert von ccode_new am 22.11.2020 22:50, insgesamt 1-mal geändert.
Betriebssysteme: div. Windows, Linux, Unix - Systeme
no Keyboard, press any key
no mouse, you need a cat
no Keyboard, press any key
no mouse, you need a cat
Re: Warum kann PB kein unsigned long bzw. int ?
@mk-soft:
Weil ich mir dein Beitrag gerade durchlese zu den Unsigned Compare:
Freak hatte dich doch damals darauf aufmerksam gemacht, dass man nicht-volatile Register in jedem Fall schützen muss, wenn man sie ändert. (Das musste ich selbst auch schmerzlich einsehen, als ich "falschen" ASM code in einem Callback von PB verwendet hatte). In deinem Fall ist das bei der r15 Register, den du da einfach beschreibst, welcher aber nicht flüchtig ist.
Könntest du ja ggf. mal updaten.
Btw. könnte auch ein CMOVcc den einen Sprung vermeiden, zumal du ja das Label ja sogar statisch benannt hast, was auch gefährlich sein könnte, wenn das jemand schon nutzt. Hier mal meine Idee:
Weil ich mir dein Beitrag gerade durchlese zu den Unsigned Compare:
Freak hatte dich doch damals darauf aufmerksam gemacht, dass man nicht-volatile Register in jedem Fall schützen muss, wenn man sie ändert. (Das musste ich selbst auch schmerzlich einsehen, als ich "falschen" ASM code in einem Callback von PB verwendet hatte). In deinem Fall ist das bei der r15 Register, den du da einfach beschreibst, welcher aber nicht flüchtig ist.
Könntest du ja ggf. mal updaten.
Btw. könnte auch ein CMOVcc den einen Sprung vermeiden, zumal du ja das Label ja sogar statisch benannt hast, was auch gefährlich sein könnte, wenn das jemand schon nutzt. Hier mal meine Idee:
Code: Alles auswählen
Procedure Above(a.q, b.q)
! MOV rax, 0
! MOV rcx, 1
! MOV rdx, qword [p.v_a]
! CMP rdx, qword [p.v_b]
! CMOVA rax, rcx
ProcedureReturn
EndProcedure
Debug Above($9000000000000000, $8000000000000000)
Debug Above($7000000000000000, $C000000000000000)
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Re: Warum kann PB kein unsigned long bzw. int ?
@stargate
mit dem Register r15 hast du recht, ich habe es aber mir leicht gemacht und genau so umgesetzt wie es der Compiler erstellt und nur den Sprungbefehl angepasst. Der Compiler verwendet auch das gleiche Register r15.
Mit dem Labels hast du recht, sollte aber in den wenigsten fällen zu Problemen führen.
mit dem Register r15 hast du recht, ich habe es aber mir leicht gemacht und genau so umgesetzt wie es der Compiler erstellt und nur den Sprungbefehl angepasst. Der Compiler verwendet auch das gleiche Register r15.
Mit dem Labels hast du recht, sollte aber in den wenigsten fällen zu Problemen führen.
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
- tft
- Beiträge: 605
- Registriert: 08.09.2004 20:18
- Computerausstattung: GTX Titan , i9 9900K , 32 GB Ram , 500 GB SSD , 3 ASUS FullHD Monitore and more
- Wohnort: Dachsen
- Kontaktdaten:
Re: Warum kann PB kein unsigned long bzw. int ?
Hallo,
ein sehr aufschlussreiche Diskussion. Allerdings erschliesst sich mir der Sinn nicht.
Beim Rechnen mit Zahlen kann es immer mal zu Ergebnissen kommen. Die <0 sind.
Daher muss die Variable doch damit umgehen können. Das reduziert den Zahlenbereich
beim Rechen nun-mal um die hälfte. Da es keine Grösseren Wert als .q (8 Byte = 64 Bit)
gibt. Müssen Rechnungen so gestaltet sein. Das diese Grenzen nicht überschritten werden.
Ich habe auf 8 Bit Rechnern gelernt. Da gabs dann das überlauf flag. Und das Register mit dem Rest.
Das Register für das Ergebniss war Doppelt so gross und in High und Low geteilt.
Ich bin kein Informatiker , und mein wissen über das rechnen mit Zahlen ist nur auf Hauptschul Niveo.
Wo genau bracht man solche Zahlen im Altag , 64 Bit ohne Vorzeichen als Ergebnis?
Und wenn man Grössere Zahlen benötigt. Mussten die Berechnungen immer in mehreren schritten erfolgen.
Die Frage ist rein Informativ und dient nur meinem Verstehen.
Gruss TFT
ein sehr aufschlussreiche Diskussion. Allerdings erschliesst sich mir der Sinn nicht.
Beim Rechnen mit Zahlen kann es immer mal zu Ergebnissen kommen. Die <0 sind.
Daher muss die Variable doch damit umgehen können. Das reduziert den Zahlenbereich
beim Rechen nun-mal um die hälfte. Da es keine Grösseren Wert als .q (8 Byte = 64 Bit)
gibt. Müssen Rechnungen so gestaltet sein. Das diese Grenzen nicht überschritten werden.
Ich habe auf 8 Bit Rechnern gelernt. Da gabs dann das überlauf flag. Und das Register mit dem Rest.
Das Register für das Ergebniss war Doppelt so gross und in High und Low geteilt.
Ich bin kein Informatiker , und mein wissen über das rechnen mit Zahlen ist nur auf Hauptschul Niveo.
Wo genau bracht man solche Zahlen im Altag , 64 Bit ohne Vorzeichen als Ergebnis?
Und wenn man Grössere Zahlen benötigt. Mussten die Berechnungen immer in mehreren schritten erfolgen.
Die Frage ist rein Informativ und dient nur meinem Verstehen.
Gruss TFT
TFT seid 1989 , Turgut Frank Temucin , Dachsen/Berlin/Antalya
Aktuelles Projekte : Driving School Evergarden
YouTube : Pure Basic to go
FaceBook : Temuçin SourceMAgic Games
DISCORD : SourceMagic
W10 , i9 9900K ,32 GB Ram , GTX Titan , 3 Monitore FHD
ARDUINO Freak
Aktuelles Projekte : Driving School Evergarden
YouTube : Pure Basic to go
FaceBook : Temuçin SourceMAgic Games
DISCORD : SourceMagic
W10 , i9 9900K ,32 GB Ram , GTX Titan , 3 Monitore FHD
ARDUINO Freak
- NicTheQuick
- Ein Admin
- Beiträge: 8679
- Registriert: 29.08.2004 20:20
- Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti - Wohnort: Saarbrücken
- Kontaktdaten:
Re: Warum kann PB kein unsigned long bzw. int ?
@tft:
Wenn du wüsstest wie viele Sicherheitslücken es gab und gibt, weil Programmierer genau so gedacht haben, dann würdest du dich wundern.
Tatsächlich zeugt es von gutem Programmierstil, wenn man z.B. Zählvariablen, die bei 0 beginnen und irgendwo aufhören, auch als unsigned definiert. Das Problem ist hier oftmals wo die obere Grenze herkommt. Es gab schon Sicherheitslücken, da wurde diese Grenze aus einer manipulierten Datei gelesen und bewusst so hoch gesetzt, dass sie negativ interpretiert wurde. Dadurch wurde die Schleife dann gar nicht ausgeführt, was fatal war. Da dann Daten nicht aus der Datei gelesen wurden, die aber eigentlich gelesen werden sollten. Wäre die gelesene Zahl aus der Datei als unsigned interpretiert worden, hätte es kein Problem gegeben.
Oder ein anderes Problem ist, wenn du zwei große Zahlen multiplizieren willst und sie dann plötzlich negativ sind. Weitere Berechnungen können dadurch zu Fehlern würden. Oder wenn du dann Modulo rechnen willst. Bei kryptografischen Verfahren ist das ein wichtiger Bestandteil.
Auch virtuelle Speicheradressen können so groß sein, dass sie negativ sind, wenn man sie signed betrachtet. Aber Speicheradressen (Pointer) können niemals negativ sein. Das ergibt keinen Sinn.
Du findest auch jede Menge Artikel über derartige Probleme. Die meisten leider auf Englisch:
Wenn du wüsstest wie viele Sicherheitslücken es gab und gibt, weil Programmierer genau so gedacht haben, dann würdest du dich wundern.
Tatsächlich zeugt es von gutem Programmierstil, wenn man z.B. Zählvariablen, die bei 0 beginnen und irgendwo aufhören, auch als unsigned definiert. Das Problem ist hier oftmals wo die obere Grenze herkommt. Es gab schon Sicherheitslücken, da wurde diese Grenze aus einer manipulierten Datei gelesen und bewusst so hoch gesetzt, dass sie negativ interpretiert wurde. Dadurch wurde die Schleife dann gar nicht ausgeführt, was fatal war. Da dann Daten nicht aus der Datei gelesen wurden, die aber eigentlich gelesen werden sollten. Wäre die gelesene Zahl aus der Datei als unsigned interpretiert worden, hätte es kein Problem gegeben.
Oder ein anderes Problem ist, wenn du zwei große Zahlen multiplizieren willst und sie dann plötzlich negativ sind. Weitere Berechnungen können dadurch zu Fehlern würden. Oder wenn du dann Modulo rechnen willst. Bei kryptografischen Verfahren ist das ein wichtiger Bestandteil.
Auch virtuelle Speicheradressen können so groß sein, dass sie negativ sind, wenn man sie signed betrachtet. Aber Speicheradressen (Pointer) können niemals negativ sein. Das ergibt keinen Sinn.
Du findest auch jede Menge Artikel über derartige Probleme. Die meisten leider auf Englisch:
- tft
- Beiträge: 605
- Registriert: 08.09.2004 20:18
- Computerausstattung: GTX Titan , i9 9900K , 32 GB Ram , 500 GB SSD , 3 ASUS FullHD Monitore and more
- Wohnort: Dachsen
- Kontaktdaten:
Re: Warum kann PB kein unsigned long bzw. int ?
Danke für die Ausführung.
TFT seid 1989 , Turgut Frank Temucin , Dachsen/Berlin/Antalya
Aktuelles Projekte : Driving School Evergarden
YouTube : Pure Basic to go
FaceBook : Temuçin SourceMAgic Games
DISCORD : SourceMagic
W10 , i9 9900K ,32 GB Ram , GTX Titan , 3 Monitore FHD
ARDUINO Freak
Aktuelles Projekte : Driving School Evergarden
YouTube : Pure Basic to go
FaceBook : Temuçin SourceMAgic Games
DISCORD : SourceMagic
W10 , i9 9900K ,32 GB Ram , GTX Titan , 3 Monitore FHD
ARDUINO Freak
-
- Beiträge: 75
- Registriert: 17.01.2018 08:52
- Computerausstattung: Windows 11 64 bit, i7, 16GB RAM
- Wohnort: Wesertal in Nordhessen
Re: Warum kann PB kein unsigned long bzw. int ?
Vielen Dank für eure Antworten !
Ich werde mich da mal reinarbeiten.
Ich werde mich da mal reinarbeiten.
formerly known as bizzl