The \[System.Convert\]::ToSByte(value) method raises an OverflowException if value is greater than [sbyte]::MaxValue.
Return to theory (Converting from two's complement representation):
$mask = [byte] 0x80 # [math]::pow(2,7)
$b = [byte] 255
$s = [sbyte] ( -($b -band $mask) + ($b -band ( -bnot $mask )) )
'result: {0,4}, {1,4} ( = 0x{0:x2}, 0x{1:x2} )' -f $b, $s
Output:
result: 255, -1 (= 0xff, 0xff )
Of course, you could simplify the calculation as
$s = [sbyte] ( -($b -band 0x80) + ($b -band 0x7F) )
Edit to refute PetSerAl's doubts about [sbyte] -($b -band $mask) + ($b -band ( -bnot $mask )) formula correctness. PetSerAl's doubts are right: results in Powershell-ISE differ from those in Powershell! The formula should be (see labelled parentheses)
# ↓ ↓
[sbyte] ( -($b -band $mask) + ($b -band ( -bnot $mask )) )
# ↑ ↑
Proof:
function AsSignedByte { ### taken from PetSerAl's comment to the OQ
param([Byte]$Byte)
[sbyte]$( if($Byte -ge 128) { $Byte - 256 } else { $Byte })
}
$mask = [byte] 0x80 # [math]::pow(2,7)
$good = 0
For ($i = 0 ; $i -lt 256; $i++) {
$b = [byte] $i
$s = [sbyte] ( -($b -band $mask) + ($b -band ( -bnot $mask )) )
$ss = AsSignedByte $b
if ( ($s -ne $ss) -or
($s.GetTypeCode() -ne $ss.GetTypeCode()) -or
($s -isnot [sbyte])) {
'result: {0,4}, {1,4} ( = 0x{0:x2}, 0x{1:x2} )' -f $s, $ss
} else {
$good +=1
}
}
$good
Output:
PS D:\PShell> D:\PShell\SO\48085510.ps1
256
PS D:\PShell>
function AsSignedByte { param([Byte]$Byte) [sbyte]$(if($Byte -ge 128) { $Byte - 256 } else { $Byte }) }