It is currently Tue Mar 09, 2021 9:45 am

All times are UTC + 1 hour




Post new topic Reply to topic  [ 2 posts ] 
Author Message
 Post subject: Maybe a bug when print a masked signed value via debug
PostPosted: Thu Feb 01, 2018 10:38 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sun Jun 11, 2006 12:07 am
Posts: 587
Location: Near Hamburg
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:
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:
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:
; 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:
[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:
[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:
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 5.73 x64, OS: Windows 7 Pro x64, Desktopscaling: 125%, CPU: I7 6500, RAM: 16 GB, GPU: Intel Graphics HD 520, User age: 52y
"Happiness is a pet." | "Never run a changing system!"


Top
 Profile  
Reply with quote  
 Post subject: Re: Maybe a bug when print a masked signed value via debug
PostPosted: Fri Dec 18, 2020 2:52 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Thu Nov 26, 2015 6:52 pm
Posts: 191
Location: Italy
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:
Debug l & $ffffffff


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

Code:
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:


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 2 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 4 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye