VeeDub Posted June 3, 2006 Share Posted June 3, 2006 Hi, BitShift is not working the way I expect. Would appreciate someone reviewing the following example. $EAX = 0xd7c0462b $Y = BitShift($EAX,0x10) MsgBox(0,"Y",hex($Y)) Y = FFFFD7C0 I expected Y = 0000D7C0 Thanks VW Link to comment Share on other sites More sharing options...
Valik Posted June 3, 2006 Share Posted June 3, 2006 The results are consistent with C++ and are correct according to MSDN:The right shift operator causes the bit pattern in the first operand to be shifted right the number of bits specified by the second operand. Bits vacated by the shift operation are zero-filled for unsigned quantities. For signed quantities, the sign bit is propagated into the vacated bit positions. The shift is a logical shift if the left operand is an unsigned quantity; otherwise, it is an arithmetic shift.AutoIt uses signed integers internally. Link to comment Share on other sites More sharing options...
VeeDub Posted June 3, 2006 Author Share Posted June 3, 2006 The results are consistent with C++ and are correct according to MSDN:AutoIt uses signed integers internally.Hi Valik,Thanks for your response, as that explains the values that AutoIt is returning. I think it would be helpful if your explanation is added to the AutoIt help for the BitShift function (and any other function where the internal use of signed integers can affect the results that AutoIt returns). While there is logic to AutoIt's behaviour, it is also potentially a trap for the unwary. Undocumented, this behaviour could appear to be a bug.ThanksVW Link to comment Share on other sites More sharing options...
VeeDub Posted June 3, 2006 Author Share Posted June 3, 2006 (edited) For anybody else who gets caught out with bitshifting large values in the future and comes across this thread in their research here's a function that performs BitShift in the "correct" or conventional fashion regardless of whether the number is a signed integer or not. I don't claim that it's elegant, but it gets the job done.The function relies on binary input to provide the correct result (and doesn't perform any error-checking in this regard) i.e. you need to provide the right input or you will get garbage output.A positive $shift value shifts right and a negative value shifts left.Func ShiftBits($bin,$shift) If $shift > 0 Then ; Shifting to the Right $left = "" for $i = 1 to $shift $left = $left & "0" Next $right = $bin $bin = $left & $right If StringLen($bin)>32 Then $bin = StringLeft($bin,32) EndIf Else ; Shifting to the Left $right = "" For $i = 1 to $shift*-1 $right = $right & "0" Next $left = StringMid($bin,($shift*-1)+1,StringLen($bin)+$shift) $bin = $left & $right If StringLen($bin)>32 Then $bin = StringLeft($bin,32) EndIf EndIf Return $bin EndFuncIf you want to test this, there are a few DecToBin functions on the forum, the one that I have been using is by Bartokv and can be found in this thread Edited June 3, 2006 by VeeDub Link to comment Share on other sites More sharing options...
Valik Posted June 3, 2006 Share Posted June 3, 2006 (edited) This function works correctly in a couple quick tests I did: <code removed, see post below by me> Edited June 4, 2006 by Valik Link to comment Share on other sites More sharing options...
VeeDub Posted June 4, 2006 Author Share Posted June 4, 2006 Your function certainly is more compact than mine, and I think possibly it should be added to the beta. I tried testing it with my original example and wasn't getting the results that I expected. Should I be converting the base on input? Link to comment Share on other sites More sharing options...
Nomad Posted June 4, 2006 Share Posted June 4, 2006 Or just providing the option for integers to be signed or unsigned with AutoItSetOption or something. Link to comment Share on other sites More sharing options...
Valik Posted June 4, 2006 Share Posted June 4, 2006 (edited) Your function certainly is more compact than mine, and I think possibly it should be added to the beta. I tried testing it with my original example and wasn't getting the results that I expected. Should I be converting the base on input? What do you mean? The function I wrote works correctly with your original example. So does this function which I like better: Func _BitShiftUnsigned($value, $shift) ; Check for the sign bit. Local $bSignBit If BitAND($value, 0x80000000) Then ; Sign bit found, unset it. $value = BitXOR($value, 0x80000000) $bSignBit = True EndIf ; Do a signed shift with the sign bit unset. $value = BitShift($value, $shift) ; Check to see if the former sign bit needs set. If $shift > 0 And $shift < 32 And $bSignBit Then $value = BitOR($value, 2 ^ (31 - $shift)) Return $value EndFunc Both of the versions should treat any signed integer as an unsigned integer when shifting. I confirmed the results using sign and unsigned integers in C++. Or just providing the option for integers to be signed or unsigned with AutoItSetOption or something. This is a non-trivial change no matter how it is implemented. The best way would be to provide an UInt() cast function similar to the Int() cast. However, implementing this is not easy. Edit: Fixed bug in the code. Edited June 4, 2006 by Valik Link to comment Share on other sites More sharing options...
VeeDub Posted June 4, 2006 Author Share Posted June 4, 2006 If I do the following: $EAX = 0xd7c0462b $Y = _BitShiftUnsigned($EAX,0x10) $EAX = hex($Y) The result is: 0000D7C0 Which is what I expect. However if I do: $EAX = 0xd7c0462b $Y = _BitShiftUnsigned($EAX,0x18) $EAX = hex($Y) The result is: 00800057 I expected: 000000D7 If I do: $EAX = 0xd7c0462b $Y = _BitShiftUnsigned($EAX,0x8) $EAX = hex($Y) The result is: 0057C0C6 I expected: 00D7C046 Link to comment Share on other sites More sharing options...
Valik Posted June 4, 2006 Share Posted June 4, 2006 If I do the following: $EAX = 0xd7c0462b $Y = _BitShiftUnsigned($EAX,0x10) $EAX = hex($Y) The result is: 0000D7C0 Which is what I expect. However if I do: $EAX = 0xd7c0462b $Y = _BitShiftUnsigned($EAX,0x18) $EAX = hex($Y) The result is: 00800057 I expected: 000000D7 If I do: $EAX = 0xd7c0462b $Y = _BitShiftUnsigned($EAX,0x8) $EAX = hex($Y) The result is: 0057C0C6 I expected: 00D7C046That would be a mistake on my part. This function version is corrected (I think): Func _BitShiftUnsigned($value, $shift) ; Check for the sign bit. Local $bSignBit If BitAND($value, 0x80000000) Then ; Sign bit found, unset it. $value = BitXOR($value, 0x80000000) $bSignBit = True EndIf ; Do a signed shift with the sign bit unset. $value = BitShift($value, $shift) ; Check to see if the former sign bit needs set. If $shift > 0 And $shift < 32 And $bSignBit Then $value = BitOR($value, 2 ^ (31 - $shift)) Return $value EndFunc Link to comment Share on other sites More sharing options...
VeeDub Posted June 4, 2006 Author Share Posted June 4, 2006 The latest version works fine for me. It's far better than my code too, so I will use it instead. I think you should look to get this version incorporated in a future release, possibly replacing the existing function, because frankly I think this version is more useful for the average user. If there are issues with replacing the current bitshift function, then as I mentioned earlier I believe the help ought to be amended to make people aware of the need to check the results if signed integers are being used. Cheers, VW Link to comment Share on other sites More sharing options...
jpm Posted June 6, 2006 Share Posted June 6, 2006 The latest version works fine for me. It's far better than my code too, so I will use it instead.I think you should look to get this version incorporated in a future release, possibly replacing the existing function, because frankly I think this version is more useful for the average user. If there are issues with replacing the current bitshift function, then as I mentioned earlier I believe the help ought to be amended to make people aware of the need to check the results if signed integers are being used.Cheers,VWConsidering the "difficulty" I add an optional third parameter which can be equal to "U" which allows to consider the integer as unsigned.Will be in 3.1.1.127 Link to comment Share on other sites More sharing options...
Cyberworld Posted August 5, 2006 Share Posted August 5, 2006 (edited) Considering the "difficulty" I add an optional third parameter which can be equal to "U" which allows to consider the integer as unsigned.Will be in 3.1.1.127 jpm, Was this parameter intended for the BitShift function? Did you forget about it or can this parameter be found somewhere else?? Edited August 5, 2006 by Cyberworld Link to comment Share on other sites More sharing options...
Valik Posted August 5, 2006 Share Posted August 5, 2006 It was not added and won't be added. In the future AutoIt may handle unsigned numbers better. Link to comment Share on other sites More sharing options...
Cyberworld Posted August 5, 2006 Share Posted August 5, 2006 (edited) OK, then I use the function you posted above BTW: Does this affect all Bit functions (-Xor,-And, -Not)? I'm trying to calculate a crc checksum but something goes wrong... Edited August 5, 2006 by Cyberworld Link to comment Share on other sites More sharing options...
Valik Posted August 5, 2006 Share Posted August 5, 2006 It should not affect anything except shifting. Link to comment Share on other sites More sharing options...
Cyberworld Posted August 5, 2006 Share Posted August 5, 2006 OK, I have to try to find out what I have done wrong... Link to comment Share on other sites More sharing options...
Cyberworld Posted August 6, 2006 Share Posted August 6, 2006 Compare this VB script with my AU3... The table creation part works and the table it produces are 100%(So there are no problem with the bit operators). Then it must be something in my code below I have made wrong. The question is what do I miss The CRC32 Calculation (VB) Dim crc32Result As Long crc32Result = &HFFFFFFFF Dim i As Integer Dim iLookup As Integer [For Each [Byte] in [Buffer]] iLookup = (crc32Result And &HFF) Xor [Byte] crc32Result = ((crc32Result And &HFFFFFF00) \ &H100) _ And 16777215 ' nasty shift right 8 with vb :/ crc32Result = crc32Result Xor crc32Table(iLookup) [Next] Crc32 = Not (crc32Result) ;The CRC32 Calculation (AU3) $crc32Result = 0xFFFFFFFF $data = "CHECKSUM" ;CRC32 = 185C43D6=Expected checksum. (I get 6522DF69) For $i = 1 to 8 $byte = StringMid($data, $i, 1) $ilookup = BitAND($crc32result, 0xFF) $ilookup = BitXOR($ilookup, $byte) $crc32result = _BitShiftUnsigned($crc32result, 8) $crc32result = BitXOR($crc32result, $crc32table[$ilookup]) Next $crc32 = BitNOT($crc32result) Link to comment Share on other sites More sharing options...
Yves1Fix Posted January 9, 2007 Share Posted January 9, 2007 You have to use the Asc() fonction : $byte = Asc(StringMid($data, $i, 1)) instead of StringMid($data, $i, 1) and now $crc32 = 185C43D6 like you want Yves Link to comment Share on other sites More sharing options...
Cyberworld Posted January 10, 2007 Share Posted January 10, 2007 Oh, This was an old post that came to life again I found out about that solution too, but I did not use the finished code in my program, since it was far to slow to calculate CRC's on little larger files (1mb+). So I rewrote that part in C and included it from a plugin(.dll) instead... But thanks anyway... 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