Created
July 7, 2025 17:08
-
-
Save Bill-Stewart/40baae695a13ff6324d8e1946ff9c862 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#requires -version 3 | |
<# | |
.SYNOPSIS | |
Outputs the bits that are set in a numeric value. | |
.DESCRIPTION | |
Outputs the positions of individual bits that are set in a numeric value. The value must fit in the range 0 through 18446744073709551615 (hexadecimal FFFFFFFFFFFFFFF); that is, the value can be a maximum of 64 bits in length. A Negative value will be converted and/or truncated to a 32-bit signed value. | |
.PARAMETER Value | |
Specifies the value. | |
.OUTPUTS | |
The output contains the following information: | |
* The value in decimal (including the signed decimal value if 32 bit) | |
* The value in hexadecimal | |
* A list of the bits set in the value (in hex and decimal) | |
Hexadecimal values are output in byte pairs. | |
.EXAMPLE | |
PS C:\> Get-Flags -2147483642 | |
Dec: 2147483654 (signed: -2147483642) | |
Hex: 8000 0006 | |
BitPosition-Hex BitPosition-Dec | |
--------------- --------------- | |
8000 0000 2147483648 | |
0000 0004 4 | |
0000 0002 2 | |
The output shows that the negative value -2147483642 is 2147483654 as an unsigned 32-bit decimal value, or 80000006 in hexadecimal. This value has bits set in the following positions: 80000000 (decimal 2147483648), 4, and 2. | |
#> | |
[CmdletBinding()] | |
param( | |
[Parameter(Position = 0,Mandatory)] | |
[String] | |
$Value | |
) | |
# Outputs a string as a 64-bit unsigned value; negative value will be | |
# output/truncated as a 32-bit unsigned value | |
function ConvertTo-Unsigned { | |
param( | |
[String] | |
$value | |
) | |
if ( $value.IndexOf(".") -eq -1 ) { | |
$value = $value.Trim() | |
if ( $value[0] -eq "-" ) { | |
try { | |
[BitConverter]::ToUInt32([BitConverter]::GetBytes($value -as [Int32]),0) | |
} | |
catch { | |
} | |
} | |
else { | |
$value -as [UInt64] | |
} | |
} | |
} | |
# Outputs a 32-bit unsigned value as signed | |
function ConvertTo-Signed { | |
param( | |
[UInt32] | |
$value | |
) | |
try { | |
[BitConverter]::ToInt32([BitConverter]::GetBytes($value),0) | |
} | |
catch { | |
} | |
} | |
# Outputs unsigned integer as hex string with specifed width in nibbles and | |
# spaces between byte pairs | |
function Get-HexString { | |
param( | |
[UInt64] | |
$value, | |
[Int] | |
[ValidateSet(8,16)] | |
$nibbles = 8 | |
) | |
("{0:X$nibbles}" -f $value) -replace '....(?!$)','$0 ' | |
} | |
$uInt = ConvertTo-Unsigned $Value | |
if ( $null -eq $uInt ) { | |
Write-Error "Unable to convert '$Value' to an unsigned integer." -Category InvalidArgument | |
return | |
} | |
# Is value 64-bit (16 nibbles) or 16-bit (8 nibbles)? | |
$nibbles = if ( $uInt -gt [UInt32]::MaxValue ) { 16 } else { 8 } | |
# Most-significant bit position for 32-bit value = 2^31 | |
$highBit32 = [BitConverter]::ToUInt32([BitConverter]::GetBytes(0x80000000),0) | |
# 32-bit value is signed if it's not 2^31 and sign bit is set | |
$signed = ($nibbles -eq 8) -and ($uInt -ne $highBit32) -and (($uInt -band $highBit32) -ne 0) | |
# Build and output header to host | |
$header = "Dec: $uInt" | |
if ( $signed ) { $header += " (signed: {0})" -f (ConvertTo-Signed $uInt) } | |
$header += "`nHex: {0}" -f (Get-HexString $uInt $nibbles) | |
Write-Host $header | |
# Most-significant bit position for 64-bit value = 2^63 | |
$highBit64 = [BitConverter]::ToUInt64([BitConverter]::GetBytes(0x8000000000000000),0) | |
# Output each set bit position, starting at 2^63 | |
for ( [UInt64] $i = $highBit64; $i -gt 0; $i /= 2 ) { | |
if ( ($uInt -band $i) -ne 0 ) { | |
[PSCustomObject] @{ | |
"BitPosition-Hex" = Get-HexString $i $nibbles | |
"BitPosition-Dec" = $i | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment