Maybe a bug when print a masked signed value via debug

Just starting out? Need help? Post your questions and find answers here.
User avatar
Kurzer
Enthusiast
Enthusiast
Posts: 664
Joined: Sun Jun 11, 2006 12:07 am
Location: Near Hamburg

Maybe a bug when print a masked signed value via debug

Post by Kurzer »

Hello,

I have written it in a similar form in another thread, but now I narrowed down the problem a little bit.
For me it looks at one point like a bug in the debug output on x86 systems, but let me explain.

Purebasic supports only a few unsigned data types. This ones that it support are in my eyes only crutches, this are the datatypes. a (Ascii),. u (Unicode) and. c (Char). These are no data types whose names refer to the use of numbers.

If you use a signed data type such as e. g. b (byte), compares like the following ones are difficult or error-prone:

Code: Select all

Define Wert.b = $ff
If $03 > Wert Then ... Do stuff
EndIf
Since $ff corresponds to -1 for a signed data type, $03 is greater than $ff (-1) and the compare result is incorrect. To avoid this, I always used to mask the variable with "& $ff" in a comparison.

Code: Select all

Define Wert.b = $ff
If $03 > Wert & $FF Then ...
It works so far.

In a current project (and after I switched to a 64 bit OS) I noticed some inconsistencies here. Therefore I wrote the following test code to check my "masking".

Code: Select all

; Compile this in x86 mode and then in x64 mode

EnableExplicit

Define b.b
Define w.w
Define l.l
Define q.q

b = $ff
w = $ffff
l = $ffffffff
q = $ffffffffffffffff

Debug "Byte: " + Str(b)
Debug "Byte: " + Str(b & $ff)
Debug b & $ff
Debug "----------------------"
Debug "Word: " + Str(w)
Debug "Word: " + Str(w & $ffff)
Debug w & $ffff
Debug "----------------------"
Debug "Long: " + Str(l)
Debug "Long: " + Str(l & $ffffffff)
Debug l & $ffffffff
Debug "----------------------"
Debug "Quad: " + Str(q)
Debug "Quad: " + Str(q & $ffffffffffffffff)
Debug q & $ffffffffffffffff
The code outputs a "large" byte, word, long and quad value as a pure number with sign, then once as a masked, unsigned number (via Str () function) and once again as a masked, unsigned number directly via debug.

If you compile it in 64 bit mode, you get the following result:

Code: Select all

[21:35:38] [Debug] Byte: -1
[21:35:38] [Debug] Byte: 255
[21:35:38] [Debug] 255
[21:35:38] [Debug] ----------------------
[21:35:38] [Debug] Word: -1
[21:35:38] [Debug] Word: 65535
[21:35:38] [Debug] 65535
[21:35:38] [Debug] ----------------------
[21:35:38] [Debug] Long: -1
[21:35:38] [Debug] Long: 4294967295
[21:35:38] [Debug] 4294967295
[21:35:38] [Debug] ----------------------
[21:35:38] [Debug] Quad: -1
[21:35:38] [Debug] Quad: -1
[21:35:38] [Debug] -1
If you compile it in 32 bit mode, you get this result:

Code: Select all

[21:35:38] [Debug] Byte: -1
[21:35:38] [Debug] Byte: 255
[21:35:38] [Debug] 255
[21:35:38] [Debug] ----------------------
[21:35:38] [Debug] Word: -1
[21:35:38] [Debug] Word: 65535
[21:35:38] [Debug] 65535
[21:35:38] [Debug] ----------------------
[21:35:38] [Debug] Long: -1
[21:35:38] [Debug] Long: 4294967295
[21:35:38] [Debug] -1
[21:35:38] [Debug] ----------------------
[21:35:38] [Debug] Quad: -1
[21:35:38] [Debug] Quad: -1
[21:35:38] [Debug] -1
Note the third debug value at "Long:"
In this case, the masking of a long value already seems to fail with the 32 bit compiler. But only if you use this value directly for a comparison.

Fred wrote that all numbers are treated as a quad within PB. This would coincide with the phenomenon that masking works when transferred to a PB function.

I didn't notice the problem until I had my project compiled as a 32 bit exe file. In my eyes, that's a bug in the debug output, what do you think?

Since I have to deal with large numbers later, I also need a fast solution for comparing unsigned quads. This obviously does not work either with 32 bit or 64 bit, since there is no larger data type. I quickly put together a workaround tonight. But I find my solution via procedure very bad and to slow.

Code: Select all

EnableExplicit

Procedure IsGreaterQ(qNumber1.q, qNumber2.q)
	If qNumber1 >> 32 & $ffffffff > qNumber2 >> 32 & $ffffffff : ProcedureReturn #True :EndIf
	If qNumber1 >> 32 & $ffffffff < qNumber2 >> 32 & $ffffffff : ProcedureReturn #False :EndIf
	If qNumber1 >> 32 & $ffffffff = qNumber2 >> 32 & $ffffffff And qNumber1 & $ffffffff > qNumber2 & $ffffffff
		ProcedureReturn #True
	Else	
		ProcedureReturn #False
	EndIf
EndProcedure

If IsGreaterQ($04, $ffffffffffffffff)
	Debug "greater"
Else	
	Debug "not greater"
EndIf

If IsGreaterQ($ffffffffffffffff, $fffffffffffffffe)
	Debug "greater"
Else	
	Debug "not greater"
EndIf
Has anyone ever worked out a FAST solution for this damn sign/unsign problem?

PS: WTF? It is also inconsistent during debugging/tracing.
Here I step through the code in x86 mode. The quick display shows me clearly "If 48 > 4294967294" but the comparsion will be executed wrong. 48 is not grater than 4294967294. Also masking does not help at this point.
How to write reasonable programs, if the tool is not able to make a simple comparison of two 4-byte digits? 20 years PureBasic and still no unsigned data types. So far I've rarely been disgusted, but in my current project this really pisses me off. Sorry for the hard words, but I hate to mess up my code with so many workarounds.

Image

Image
PB 6.02 x64, OS: Win 7 Pro x64 & Win 11 x64, Desktopscaling: 125%, CPU: I7 6500, RAM: 16 GB, GPU: Intel Graphics HD 520, User age in 2023: 56y
"Happiness is a pet." | "Never run a changing system!"
User avatar
Tristano
Enthusiast
Enthusiast
Posts: 190
Joined: Thu Nov 26, 2015 6:52 pm
Location: Italy
Contact:

Re: Maybe a bug when print a masked signed value via debug

Post by Tristano »

The debugger indeed displays inconsistent output between x86 and x64 versions (tested with PB 5.73), but only when attempting to carry out the bitwise operation within the Debug command, i.e.:

Code: Select all

Debug l & $ffffffff
If instead you create a new variable to hold the manipulated result, the output is consistent in both architectures:

Code: Select all

Define l2.l
l2 = l & $ffffffff
Debug l2
I'm not sure whether this is a bug or just a limitation in the way the Debug command works.

The Debug command is known to be problematic when handling inline operations, e.g. escaped strings can fail, and only literal strings are truly safe to use with the command.

To be on the safe side, it's always better to rely on the various Str*() commands with Debug, where StrU() supports unsigned numbers and also accepts an optional parameter to specify the type size, and there are size-specific variants of these commands.

Working with unsigned types in PB can be painful, and unfortunately the documentation doesn't deal much with the topic. You'll find various solutions to the problem in this forum, but the issue really only comes up when interfacing to libraries in other languages.

In any case, unsigned numbers are problematic in general, not only in PB, and if you think that the situation is better in other languages, e.g. in C or C++, read the excellent article Danger – unsigned types used here! by David Crocker:

https://critical.eschertech.com/2010/04 ... used-here/

Modern languages shun unsigned number, and tend to implement them mostly for the purpose of FFI, to allow binding to C/C++ libraries, but discourage their usage in native code.
The PureBASIC Archives: FOSS Resources:
Post Reply