Hmm.
Reversing the bytes in a UInt64 / Int64.
I knew that Format can do Int64 to UInt64.
But it seems it cannot do UInt64 to Int64. So NumPut/NumGet is needed.
If you do bitshift-right on a negative number, it fills in all the initial bits with 1s. And so if you read that number as a positive number, it will be much bigger than it should be. But if you use & with a mask, you can ignore those initial bits.
Anyhow, a magic number is needed at one point: -72057594037927936, the Int64 dec equivalent of UInt64 hex 0xFF00000000000000.
One way of calculating this number, that I didn't use in the script, is, instead of:
UInt64: 0xFFFFFFFFFFFFFFFF - 0x00FFFFFFFFFFFFFF = 0xFF00000000000000
we do:
Int64: -1 - 0x00FFFFFFFFFFFFFF = -0x0100000000000000 = -72057594037927936
[EDIT:] You can omit the magic number. See 'with magic number' and 'without magic number' below.
Code: Select all
;==================================================
q:: ;Int64 to UInt64, and, UInt64 to Int64
;Int64 to UInt64:
MsgBox, % Format("{:i}", -1) ;-1
MsgBox, % Format("{:u}", -1) ;18446744073709551615
MsgBox, % Format("0x{:X}", -1) ;0xFFFFFFFFFFFFFFFF
;UInt64 to Int64 (fail):
;MsgBox, % Format("{:i}", "0xFFFFFFFFFFFFFFFF") ;incorrect: 9223372036854775807
;MsgBox, % Format("{:u}", "0xFFFFFFFFFFFFFFFF") ;incorrect: 9223372036854775807
;MsgBox, % Format("0x{:X}", "0xFFFFFFFFFFFFFFFF") ;incorrect: 0x7FFFFFFFFFFFFFFF
;UInt64 to Int64:
vNum := (0xFFFFFFFF<<32) | 0xFFFFFFFF
MsgBox, % vNum ;-1
MsgBox, % Format("{:i}", vNum) ;-1
MsgBox, % Format("{:u}", vNum) ;18446744073709551615
MsgBox, % Format("0x{:X}", vNum) ;0xFFFFFFFFFFFFFFFF
;UInt64 to Int64:
VarSetCapacity(vData, 8, 0)
NumPut("0xFFFFFFFFFFFFFFFF", &vData, 0, "UInt64")
vNum := NumGet(&vData, 0, "Int64")
MsgBox, % Format("{:i}", vNum) ;-1
MsgBox, % Format("{:u}", vNum) ;18446744073709551615
MsgBox, % Format("0x{:X}", vNum) ;0xFFFFFFFFFFFFFFFF
return
;==================================================
w:: ;convert UInt64 to Int64 via NumGet (recommended)
vHex := "0xFF00000000000000"
;vHex := "0xFFEEDDCCBBAA9988"
VarSetCapacity(vData, 8, 0)
NumPut(vHex, &vData, 0, "UInt64")
vNum := NumGet(&vData, 0, "Int64")
MsgBox, % vNum ;-72057594037927936
MsgBox, % Format("0x{:016X}", vNum) ;0xFF00000000000000
return
e:: ;convert UInt64 to Int64 via RegExReplace and bit-or (split number in two)
vHex := "0xFF00000000000000"
;vHex := "0xFFEEDDCCBBAA9988"
vTemp := RegExReplace(vHex, "i)(0x)?([0-9A-Z]{8})([0-9A-Z]{8})", "0x$2 0x$3")
MsgBox, % vTemp
oTemp := StrSplit(vTemp, " ")
;vNum := (0xFF000000<<32) | 0x00000000
vNum := (oTemp.1<<32) | oTemp.2
MsgBox, % vNum ;-72057594037927936
MsgBox, % Format("0x{:016X}", vNum) ;0xFF00000000000000
return
;==================================================
r:: ;reverse bytes in UInt64
vHex := "0xFFEEDDCCBBAA9988"
;vHex := "0xFFEEDDCCBBAA99FF"
Loop 4
{
;UInt64 (hex) to Int64 (dec):
VarSetCapacity(vData, 8, 0)
NumPut(vHex, &vData, 0, "UInt64")
vNum := NumGet(&vData, 0, "Int64")
;MsgBox, % vNum ;-4822678189205112
;MsgBox, % Format("0x{:016X}", vNum) ;0xFFEEDDCCBBAA9988
;MsgBox, % Format("0x{:016X}", -72057594037927936&vNum) ;0xFF00000000000000
;MsgBox, % Format("0x{:016X}", ((-72057594037927936&vNum)>>56)&0xFF) ;0x00000000000000FF
;Int64 reverse bytes (with magic number):
;vNum := ((-72057594037927936&vNum)>>56)&0xFF | (0xFF000000000000&vNum)>>40 | (0xFF0000000000&vNum)>>24 | (0xFF00000000&vNum)>>8 | (0xFF000000&vNum)<<8 | (0xFF0000&vNum)<<24 | (0xFF00&vNum)<<40 | (0xFF&vNum)<<56
;Int64 reverse bytes (without magic number):
vNum := (vNum>>56)&0xFF | (0xFF000000000000&vNum)>>40 | (0xFF0000000000&vNum)>>24 | (0xFF00000000&vNum)>>8 | (0xFF000000&vNum)<<8 | (0xFF0000&vNum)<<24 | (0xFF00&vNum)<<40 | (0xFF&vNum)<<56
;Int64 (dec) to UInt64 (hex):
vHex := Format("0x{:016X}", vNum)
MsgBox, % vHex
}
return
Thanks for the DllCall version:
MsgBox, % Format("0x{:16X}", DllCall("ucrtbase\_byteswap_uint64", "UInt64","0xFFEEDDCCBBAA9988", "UInt64"))