This is something that came to me as I was working to do some bitwise operations for a project that had a lot of pInvoke stuff and required that I do some shifting of bits. Being that I wasn’t all that familiar with this (I’m more familiar with BOR, BAND and XOR), I wanted to learn more about the before and after of the binary representation of the data.
What is a bitwise operation you ask? Well, it is
a bitwise operation operates on one or more bit patterns or binary numerals at the level of their individual bits. It is a fast, primitive action directly supported by the processor, and is used to manipulate values for comparisons and calculations. –From Wikipedia Article on Bitwise Operations
I decided that it would be nice to have a function that would allow you to provide the parameters needed for a bitwise operation, but rather than just outputting a value as a result of the operation, it would instead show you more information about the results such as showing the values in binary and hex form. But that wasn’t all I wanted. I saw the about_Comparison_Operators help file and liked the examples that they showed when doing an operation.
Putting this all together led me to a function I wrote called Invoke-BitwiseOperation which accepts a –First and –Second parameter which is for the two values, a –BitwiseOperator parameter that accepts the following values: BAND,BOR,BXOR,BNOT,SHL,SHR and finally there is the –Graphical parameter which gives you the output like you see in the help files.
I start out by using a helper function called ConvertToBinary which takes an integer, converts it to a binary form and then uses a RegEx pattern to split out the binary data into chunks of 8.
Function ConvertToBinary { Param( [parameter(ValueFromPipeline=$True)] $Item ) Process { $String = [Convert]::ToString($Item,2) $Reverse = -join (-join $string[$String.length..0] -split '(?<=\G.{8})').PadRight(8,'0') -join $Reverse[$Reverse.length..0] -split '(?<=\G.{8})' } } (8956 | ConvertToBinary) -join ' '
I opted to not join the output prior so I could do some more stuff with the collection of values later on in my code.
If ($BitWiseOperator -eq 'BNOT') { $Result = [Math]::Abs((Invoke-Expression "-$($BitWiseOperator) $($First)")) } Else { If ($PSBoundParameters.ContainsKey('First') -AND $PSBoundParameters.ContainsKey('Second')){ $Result = Invoke-Expression "$($First) -$($BitWiseOperator) $($Second)" } Else { Write-Warning "You must specify both a First and Second parameter!" BREAK } } $First_Bin = $First | ConvertToBinary $First_Hex = "0x{0:x}" -f $First If ($PSBoundParameters.ContainsKey('Second') -AND $BitWiseOperator -notmatch 'SHL|SHR') { $Second_Bin = $Second | ConvertToBinary $Second_Hex = "0x{0:x}" -f $Second } $Result_Bin = $Result | ConvertToBinary $Result_Hex = "0x{0:x}" -f $Result
This portion looks at what kind of Bitwise operator that I specified and takes an action based on that, such as when using BNOT. I also perform the conversion of the values to binary and also convert the data to hex for later use.
If ($PSBoundParameters.ContainsKey('Graphical')) { $Padding = '00000000' $FirstList = New-Object System.Collections.ArrayList $SecondList = New-Object System.Collections.ArrayList $ResultList = New-Object System.Collections.ArrayList $FirstHex = "0x{0:x}" -f $First $SecondHex = "0x{0:x}" -f $Second $ResultHex = "0x{0:x}" -f $Result $First_Bin | ForEach { [void]$FirstList.Add($_) } $Second_Bin | ForEach { [void]$SecondList.Add($_) } $Result_Bin | ForEach { [void]$ResultList.Add($_) } $Count = $FirstList, $SecondList, $ResultList | ForEach { [pscustomobject]@{ Count = $_.count } } | Sort Count -Descending | Select -First 1 -ExpandProperty Count $FirstList, $SecondList, $ResultList | ForEach { $ToPad = $Count - $_.Count If ($ToPad -gt 0) { For ($i=1; $i -le $ToPad; $i++) { $_.Insert(0,$Padding) } } } $Line = '-' * (($ResultList -join ' ').Length) "$($FirstList -join ' ') ($First, $($FirstHex)" If ($BitWiseOperator -notmatch 'BNOT|SHL|SHR') { "$($SecondList -join ' ') ($Second, $($SecondHex)" } "$line $BitWiseOperator" "$($ResultList -join ' ') ($result, $($ResultHex)" } Else { [pscustomobject]@{ First = $First First_Bin = $First_Bin First_Hex = $First_Hex BitWiseOperator = $BitWiseOperator Second = $Second Second_Bin = $Second_Bin Second_Hex = $Second_Hex Result = $Result Result_Bin = $Result_Bin Result_Hex = $Result_Hex } }
The final portion of the script takes a turn based on if the –Graphical parameter is used or not. If used, some more data processing occurs so it can display the data like what you saw in the help file. Otherwise, it just outputs an object with the converted values. Some examples are shown below.
Invoke-BitWiseOperation -First 32 -Second 16 -BitWiseOperator SHL –Graphical
Invoke-BitWiseOperation -First 7 -BitWiseOperator BNOT
Download Invoke-BitwiseOperation
https://gallery.technet.microsoft.com/scriptcenter/Invoke-BitwiseOperation-bc2f3c80
Reblogged this on Augmented ITC Blog.
How can I interpretate ConvertToBinary function?
PS > [convert]::ToString(8956,2)
10001011111100
PS > (8956 | ConvertToBinary) -join ‘ ‘
10001011 00111100
PS > [convert]::ToInt32(1000101100111100,2)
35644
PS > [convert]::ToInt32(10001011111100,2)
8956
I had some wackiness happening with that function and have fixed how I was creating the binary value. It should be a lot more accurate now.
PS > -bnot 7
-8
Good catch! I’ve fixed that bug and a couple of other bugs in my code.