Hex and 64 bits strange behavior

Hi all,

Let say you have a MemoryBlock with “B1E9B2D06EBD” as content (from
offset 0, but it doesn’t matter).

Dim One32 As Int32=1
Dim One64 As Int64=1
Dim MyMemoryBlock As New MemoryBlock
Dim HexValue, NewHexValue As String

MyMemoryBlock.Int32Value(0)=&hB2D06EBD

HexValue=Hex(MyMemoryBlock.Int32Value(0))

NewHexValue=Hex(MyMemoryBlock.Int32Value(0)+1)
TextArea1.Text=HexValue+" -> "+NewHexValue+EndOfLine

NewHexValue=Hex(MyMemoryBlock.Int32Value(0)+One32)
TextArea1.Text=HexValue+" -> "+NewHexValue+EndOfLine

NewHexValue=Hex(MyMemoryBlock.Int32Value(0)+One64)
TextArea1.Text=HexValue+" -> "+NewHexValue

Compiling in 32Bit mode, NewHexValue returns “BB2D06EBE” as expected,
but with One64 it returns “FFFFFFFFB2D06EBE”.
Compiling in 64Bit mode, NewHewValue returns “FFFFFFFFB2D06EBE” with 1
and One64, and “B2D06EBE” with One32.

Is this a bug? If no, how do you explain this?

First, in the future, please use the “code” tags here to format code. It makes it easier for us.

The value you’re storing is negative so the values you’re getting back are negative. Try UInt32 and UInt64 instead.

Thanks, Kem.
What value is negative? AFAIK, 1 is not negative.
That said, the new code:

[code]Dim One32 As UInt32=1
Dim One64 As UInt64=1
Dim MyMemoryBlock As New MemoryBlock
Dim HexValue, NewHexValue As String

MyMemoryBlock.Int32Value(0)=&hB2D06EBD

HexValue=Hex(MyMemoryBlock.Int32Value(0))

NewHexValue=Hex(MyMemoryBlock.Int32Value(0)+1)
TextArea1.Text=HexValue+" -> "+NewHexValue+EndOfLine

NewHexValue=Hex(MyMemoryBlock.Int32Value(0)+One32)
TextArea1.Text=HexValue+" -> "+NewHexValue+EndOfLine

NewHexValue=Hex(MyMemoryBlock.Int32Value(0)+One64)
TextArea1.Text=HexValue+" -> "+NewHexValue[/code]

Returns, in 64 bits:
“FFFFFFFFB2D06EBE”
“FFFFFFFFB2D06EBE”
“FFFFFFFFB2D06EBE”

And in 32 bits:
“B2D06EBE”
“B2D06EBE”
“FFFFFFFFB2D06EBE”

that are not expected results, as Memoryblock.Int32Value should only return 4 bytes.

MB.Int32Value in this case is returning a negative value. Use mb.UInt32Value.

Kem is right. This is doing the right thing. In 32 bit compiles the literal 1 is 32 bit. So adding 32 bit value (memoryblock.Int32Value) and a 32 bit value (1) yields a 32 bit value. That is converted to a 32 bit hex value. In a 64 bit compile the literal 1 is 64 bit. So adding 32 bit value (memoryblock.Int32Value) and a 64 bit value (1) yields a 64 bit value. That is converted to a 64 bit hex value and in order to make the memoryblock.int32value a proper 64 bit value it is “sign extended” . Since the high, or sign, bit of &hB2D06EBD is set to 1 that is replicated across the "upper bits to make the value a 64 bit signed integer. Then two 64 bit values are added and then hexed.

Using Uint32 would avoid the sign extension.

Many thanks to you, Kem (for the solution) and Jason (for explanation).
The solution works very well, 32 and 64 bits IDE or Compilation.

Jason, extending a 32bit hex value to 64bit, I would have expected filling additional bits with 0, but the higher for a sign value.
This would lead to a correct value of the 32Bit value, wheras replicating the higher bit of the 32Bit value leads to a wrong one (in 64Bit) if this bit is 1.
Is this a normal behavior or a bug in conversion between 32Bit Hex values and 64Bit Hex ones?

I believe I have to practice and test on such a problem in order to understand the mechanism…

Again, thanks a lot for your help.

You’re welcome Jean-Luc.

This would be very bad and incorrect behaviour. When you fetch the Int64 value from something that is 32 bits sign extension has to happen otherwise things would unexpectedly change sign.
For instance, if you did:

dim i32 as int32 = -1
dim i64 as int64

i64 = i32

and did not do sign extension then i32 would be -1 and i64 would be some other positive value and that would be 100% wrong
The same holds true for your code (which could be written as):

Dim One64 As Int64=1
Dim MyMemoryBlock As New MemoryBlock(4)
dim intermediate as int64 = MyMemoryBlock.Int32Value(0)+One64
NewHexValue=Hex(intermediate)

the addition of Int32Value and One64 proceeds as:

  1. find the common type that int32 value and one64 can be converted to to make the addition work
  2. the common type is “Int64”
  3. create a temporary that is of type int64
  4. convert int32value to int64 and assign to the temporary from step2 ← this is where sign extension happens - so that the new int64 has the same value as the int32
  5. now add the temporary and one64 giving a new int64 value temporary
  6. assign the int64 to the resulting variable called “Intermediate”