ken82m Posted June 5, 2023 Share Posted June 5, 2023 (edited) I tried the Binary() function for starters but since AU3 stores binary as hex I'm lost as to how to extract specific bits out of it. Here's an example of what I'm trying to do: 1) Original Hex: 303425637013293133FDA4D5 2) Convert to Binary: 001100000011010000100101011000110111000000010011001010010011000100110011111111011010010011010101 3) Extract Bits 39 - 58 from binary: 00000100110010100100 4) Convert extracted bits to decimal: 19620 While I don't see that long binary string in step 2 I'll assume it's available internally in the script after Binary() so it's step 3 where I'm stuck. I did try BinaryMid() but that just returned nothing with the parameters 39, 17 wrapped around the Binary() function. And yes I did include 0x in front of my Hex number. Any help is appreciated. Thanks, Kenny Edited June 5, 2023 by ken82m "I believe that when we leave a place, part of it goes with us and part of us remains... Go anywhere, when it is quiet, and just listen.. After a while, you will hear the echoes of all our conversations, every thought and word we've exchanged.... Long after we are gone our voices will linger in these walls for as long as this place remains." Link to comment Share on other sites More sharing options...
Dan_555 Posted June 5, 2023 Share Posted June 5, 2023 Hi, you can extract the necessary Bit functions from this post. If you have the Autoit's Binary String, you can use the BinaryLen() and BinaryMid() functions to extract the needed characters. Use IsBinary to check if the string format is in the correct format. Some of my script sourcecode Link to comment Share on other sites More sharing options...
Andreik Posted June 5, 2023 Share Posted June 5, 2023 Maybe this helps you. I suspect that MSB for bits 39-58 are not correct by I stayed with your version. If the order of your most significant bit is reversed just reverse $BinNumber before extracting bits with StringMid(). $HexNumber = '303425637013293133FDA4D5' $BinNumer = HexToBin($HexNumber) $Bits39_58 = StringMid($BinNumer, 39, 20) ; 58 - 39 + 1 = 20 $Decimal = Bin2Dec($Bits39_58) ConsoleWrite($Decimal & @CRLF) Func HexToBin($dHex) If StringLeft($dHex, 2) = '0x' Then $dHex = StringTrimLeft($dHex, 2) Local $aSplit = StringSplit($dHex, '') Local $sBin, $aBits = StringSplit('0000|0001|0010|0011|0100|0101|0110|0111|1000|1001|1010|1011|1100|1101|1110|1111', '|', 2) For $Index = 1 To $aSplit[0] $sBin &= $aBits[Dec($aSplit[$Index])] Next Return $sBin EndFunc Func Bin2Dec($sBin) Local $iDecimal = 0 For $Index = 1 To StringLen($sBin) $iDecimal += Number(StringMid($sBin, $Index , 1)) * (2 ^ (StringLen($sBin) - $Index)) Next Return $iDecimal EndFunc When the words fail... music speaks. Link to comment Share on other sites More sharing options...
TheXman Posted June 5, 2023 Share Posted June 5, 2023 (edited) Why on earth would you need to do this? expandcollapse popup#AutoIt3Wrapper_AU3Check_Parameters=-w 3 -w 4 -w 5 -w 6 -d #include <Constants.au3> example() Func example() Const $BIN_VALUE = Binary("0x303425637013293133FDA4D5") Local $sBase2Value = _BinaryBits($BIN_VALUE, False), _ $sBits39to58 = StringMid($sBase2Value, 39, 20) Local $iInt32Value = _StringToInt32($sBits39to58, 2) ConsoleWrite("Base16 value: " & $BIN_VALUE & @CRLF) ConsoleWrite("Base2 value: " & _BinaryBits($BIN_VALUE) & @CRLF) ConsoleWrite("Bits 39-58 " & $sBits39to58 & @CRLF) ConsoleWrite("Int32 value of bits 39-58: " & $iInt32Value & @CRLF) EndFunc ; #FUNCTION# ==================================================================================================================== ; Name ..........: _BinaryBits ; Description ...: Convert data to its base2 value (with or without a space between every 4 bits) ; Syntax ........: _BinaryBits($vData[, $bAddSeparator = True]) ; Parameters ....: $vData - a string or number value. ; $bAddSeparator - [optional] a boolean value. Default is True. ; Return values .: A string representing the base2 value ; Author ........: TheXman ; =============================================================================================================================== Func _BinaryBits($vData, $bAddSeparator = True) Local $sBits = "" Local $xBinaryData = Binary($vData), _ $xByte = Binary("") Local $iBinaryDataLength = BinaryLen($xBinaryData) ;Process binary data from left-most byte to right-most byte For $i = 1 To $iBinaryDataLength ;Get byte $xByte = BinaryMid($xBinaryData, $i, 1) ;Spin thru each bit of byte (msb to lsb) For $j = 7 To 0 Step -1 ;If separator requested and this is 5th bit, then add a nibble separator If $bAddSeparator And $j = 3 Then $sBits &= " " ;If bit is set, then prepend 1 else prepend 0 $sBits &= (BitAND($xByte, 2 ^ $j) ? "1" : "0") Next ;If this isn't the last byte to be processed, then add a byte separator If $i < $iBinaryDataLength And $bAddSeparator Then $sBits &= " " Next Return $sBits EndFunc ; #FUNCTION# ==================================================================================================================== ; Name ..........: _StringToInt32 ; Description ...: Convert a string, in the specified number base, to an int32. ; Syntax ........: _StringToInt64($sString, $iBase) ; Parameters ....: $sString A string representation of a integer value (in a base from 2 to 36). ; $iBase An integer value from 2 to 36. ; Return values .: Success An int32 value of the string. ; Failure 0 and sets @error to a non-zero value. ; @error 1 = Invalid number base ; 2 = DllCall failed. @extended = DllCall @error ; Author ........: TheXman ; =============================================================================================================================== Func _StringToInt32($sString, $iBase) Local $aResult[0] If $iBase < 2 Or $iBase > 36 Then Return SetError(1, 0, "") $aResult = DllCall('msvcrt.dll', 'int64:cdecl', '_wcstoui64', _ 'wstr' , $sString, _ 'wstr*' , Null, _ 'int' , $iBase) If @error Then Return SetError(2, @error, 0) Return Number($aResult[0], $NUMBER_32BIT) EndFunc Output: Base16 value: 0x303425637013293133FDA4D5 Base2 value: 0011 0000 0011 0100 0010 0101 0110 0011 0111 0000 0001 0011 0010 1001 0011 0001 0011 0011 1111 1101 1010 0100 1101 0101 Bits 39-58 00000100110010100100 Int32 value of bits 39-58: 19620 Edited June 5, 2023 by TheXman RTFC 1 CryptoNG UDF: Cryptography API: Next Gen jq UDF: Powerful and Flexible JSON Processor | jqPlayground: An Interactive JSON Processor Xml2Json UDF: Transform XML to JSON | HttpApi UDF: HTTP Server API | Roku Remote: Example Script About Me How To Ask Good Questions On Technical And Scientific Forums (Detailed) | How to Ask Good Technical Questions (Brief) "Any fool can know. The point is to understand." -Albert Einstein "If you think you're a big fish, it's probably because you only swim in small ponds." ~TheXman Link to comment Share on other sites More sharing options...
ken82m Posted June 5, 2023 Author Share Posted June 5, 2023 4 minutes ago, TheXman said: Why on earth would you need to do this? expandcollapse popup#AutoIt3Wrapper_AU3Check_Parameters=-w 3 -w 4 -w 5 -w 6 -d #include <Constants.au3> example() Func example() Const $BIN_VALUE = Binary("0x303425637013293133FDA4D5") Local $sBase2Value = _BinaryBits($BIN_VALUE, False), _ $sBits39to58 = StringMid($sBase2Value, 39, 20) Local $iInt32Value = _StringToInt32($sBits39to58, 2) ConsoleWrite("Binary value: " & $BIN_VALUE & @CRLF) ConsoleWrite("Base2 value: " & $sBase2Value & @CRLF) ConsoleWrite("Bits 39-58 " & $sBits39to58 & @CRLF) ConsoleWrite("Int32 value of bits 39-58: " & $iInt32Value & @CRLF) EndFunc ; #FUNCTION# ==================================================================================================================== ; Name ..........: _BinaryBits ; Description ...: Convert data to its base2 value (with or without a space between every 4 bits) ; Syntax ........: _BinaryBits($vData[, $bAddSeparator = True]) ; Parameters ....: $vData - a string or number value. ; $bAddSeparator - [optional] a boolean value. Default is True. ; Return values .: A string representing the base2 value ; Author ........: TheXman ; =============================================================================================================================== Func _BinaryBits($vData, $bAddSeparator = True) Local $sBits = "" Local $xBinaryData = Binary($vData), _ $xByte = Binary("") Local $iBinaryDataLength = BinaryLen($xBinaryData) ;Process binary data from left-most byte to right-most byte For $i = 1 To $iBinaryDataLength ;Get byte $xByte = BinaryMid($xBinaryData, $i, 1) ;Spin thru each bit of byte (msb to lsb) For $j = 7 To 0 Step -1 ;If separator requested and this is 5th bit, then add a nibble separator If $bAddSeparator And $j = 3 Then $sBits &= " " ;If bit is set, then prepend 1 else prepend 0 $sBits &= (BitAND($xByte, 2 ^ $j) ? "1" : "0") Next ;If this isn't the last byte to be processed, then add a byte separator If $i < $iBinaryDataLength And $bAddSeparator Then $sBits &= " " Next Return $sBits EndFunc ; #FUNCTION# ==================================================================================================================== ; Name ..........: _StringToInt32 ; Description ...: Convert a string, in the specified number base, to an int32. ; Syntax ........: _StringToInt64($sString, $iBase) ; Parameters ....: $sString A string representation of a integer value (in a base from 2 to 36). ; $iBase An integer value from 2 to 36. ; Return values .: Success An int32 value of the string. ; Failure 0 and sets @error to a non-zero value. ; @error 1 = Invalid number base ; 2 = DllCall failed. @extended = DllCall @error ; Author ........: TheXman ; =============================================================================================================================== Func _StringToInt32($sString, $iBase) Local $aResult[0] If $iBase < 2 Or $iBase > 36 Then Return SetError(1, 0, "") $aResult = DllCall('msvcrt.dll', 'int64:cdecl', '_wcstoui64', _ 'wstr' , $sString, _ 'wstr*' , Null, _ 'int' , $iBase) If @error Then Return SetError(2, @error, 0) Return Number($aResult[0], $NUMBER_32BIT) EndFunc Output: Binary value: 0x303425637013293133FDA4D5 Base2 value: 001100000011010000100101011000110111000000010011001010010011000100110011111111011010010011010101 Bits 39-58 00000100110010100100 Int32 value of bits 39-58: 19620 Uggg don't get me started. Some stupid vendor we're unfortunately willing to accommodate has this weird damn structure that's a combination of data that produces that hex number. And when it gets transmitted back to them in volume it requires that piece of it converted back to decimal (which can vary) as part of the return data. It was a big enough pain putting this together with a piece of software. But then having to unravel this again which is a big enough pain to create to extract that specific section as part of the file that goes back to them. And of course I have to make all this junk work. Alternatively I could write these to a database as we create them with that decimal value in another column which probably makes more sense. But honestly nobody here gives a damn about any of these values so I'd rather not have yet another database to administer. If I can just have a script these users can feed an input file to (which contains a lot of unnecessary fields) process that and produce the final output going back stand alone I can live with that. I've though about a few other options but I can see users constantly screwing something up constantly lol. Thank you all for your help. I've done plenty in AutoIT but I have never had to deal with actual binary directly in AU3. TheXman 1 "I believe that when we leave a place, part of it goes with us and part of us remains... Go anywhere, when it is quiet, and just listen.. After a while, you will hear the echoes of all our conversations, every thought and word we've exchanged.... Long after we are gone our voices will linger in these walls for as long as this place remains." Link to comment Share on other sites More sharing options...
RTFC Posted June 6, 2023 Share Posted June 6, 2023 (edited) A different approach: #NoTrayIcon #include ".\Eigen4AutoIt.au3" _Eigen_StartUp("int") $HexNumber = '303425637013293133FDA4D5' $firstbit = 39 ; base-1 index $lastbit = 58 $totalbits = 1+$lastbit-$firstbit If $totalbits>32 Then Exit ; value too large to fit into one int32 ; store hex string as conseucutive int32s $ints=Ceiling(StringLen($HexNumber)/8) $vector=_Eigen_CreateVector(_Max(32,$ints)) ; ensure enough space for result For $rc=0 To $ints-1 _Eigen_WriteMatrixValue($vector,$rc,0,Number("0x" & StringMid($HexNumber,1+$rc*8,8))) Next ; unpack all bits, store desired bits, and repack $matA=_Eigen_Unpack($vector) _Eigen_SetZero($vector) ; prezero results buffer _Eigen_Copy_Ablock_ToBblock($matA,$vector,$firstbit-1,0,$totalbits,1,32-$totalbits,0) _Eigen_Pack($vector,$matA) ConsoleWrite("Selected Bits value = " & _Eigen_ReadMatrixValue($matA,0,0) & @CRLF) _Eigen_CleanUp() If the last int32 is can be incomplete, just pad it with extra zeroes before storing it in the vector: #include <String.au3> $HexNumber&=_StringRepeat("0",8-Mod(StringLen($HexNumber),8)) Edited June 6, 2023 by RTFC My Contributions and Wrappers Spoiler BitMaskSudokuSolver BuildPartitionTable CodeCrypter CodeScanner DigitalDisplay Eigen4AutoIt FAT Suite HighMem MetaCodeFileLibrary OSgrid Pool RdRand SecondDesktop SimulatedAnnealing Xbase I/O Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now