# Looking up a bit(s) in a DWORD hex value - Need Advice

## Recommended Posts

Hi everyone,

I'm trying to make a simple app that can look up a bit within a 32bin HEX value.

Can someone provide some advice or examples?

Example1;

Hex value: 3F8A9556

I want to look up bit 31

(it should return 0)

Example2

Hex value: 1D12AAA

I want to look up bits 27-30

(it should return 0000 or just 0)

Thanks guys!

Greg

##### Share on other sites

This is how I'd do it: basically, you need to do two things.

1-) Shift your value to the right enough times as to position your first wanted bit in index 0

2-) Create and bitAND a mask that unsets the bits you do not want.

It is a bit tricky because AutoIT doesn't have an unsigned-right-shift function. But you can get around that with a bit of thinking.

PS: I was bored and ended up doing it for ya. Here it is, with nice comments if anybody wants them.

I tested it a bit and it seems to work alright, but please check it yourself as well.

```Func _BitRange(\$v, \$start, \$end=-1)
; We only work for integers, sorry
If Not IsInt(\$v) Then Return SetError(1, 0, 0)

; Check for a valid range
If \$start < 0 Or \$start > 31 Then
Return SetError(2, 0, 0)
EndIf

; Default to retrieving a single bit
If \$end < 0 Then
\$end = \$start
; Another range check
ElseIf \$end < \$start Then
Return SetError(3, 0, 0)
EndIf

; First, we check if the most significant (sign) bit is of any importance.
If \$end = 31 Then
; If it is, we first handle the special case of retrieving all the bits.
If \$start = 0 Then Return \$v

; If fewer than 32 bits matter, we can use 1 of the meaningless ones as we wish.
; What allows this is the fact that signed shifts, as in AutoIT,
; set vacant bits to the current value of the sign bit.

; In this case, we can't ignore the most significant bit.
; Because of that, the mask works right-to-left:
; The sign bit is set, and propagates that value to (end-start) bits at its right

; We apply the mask first, then use a rotation to emulate our shift.
; This works because by applying the mask, we assured all non-wanted bits are 0s
EndIf

; Here, we need not care for bit 31 at all.
; Therefore, this mask works left-to-right: the sign bit *cleans* the bits to its right.

; Here, we *first* shift the value to the right as much as needed to
; put our first wanted bit at index 0
; Then, afterwards, we apply our mask, and we're done.
EndFunc```

##### Share on other sites

BinaryMid() ?

bah, reinventing the wheel is much funnier. Edited by danielkza

##### Share on other sites

Thanks a lot AdmiralAlkex and danielkza! I appreciate your guys help! I'm kind of a newb here, and have been trying to figure this out.

I'm going to try both options right away.

Greg

##### Share on other sites

I found danielkza and my approach return the same result, although the parameters differ being zero-based and 1-based respectively.

BinaryMid() works with bytes as opposed to bits - 32bit(4bytes)

The example with BinaryMid() uses the last byte, the last 8 bits.

```; 0x3F8A9556 = 00111111 10001010 10010101 01010110
ConsoleWrite("danielkza " & _BitRange(0x3F8A9556, 23, 31) & @CRLF) ; 0-based
; 0x1D12AAA = 00000001 11010001 00101010 10101010
ConsoleWrite("danielkza " & _BitRange(0x1D12AAA, 27, 30) & @CRLF) ; 0-based

; 0x3F8A9556 = 00111111 10001010 10010101 01010110
ConsoleWrite("Malkey    " & _BitValueFromHexMid(0x3F8A9556, 24, 9) & @CRLF) ; 1-based
; 0x1D12AAA = 00000001 11010001 00101010 10101010
ConsoleWrite("Malkey    " & _BitValueFromHexMid(0x1D12AAA, 27, 4) & @CRLF) ; 1-based

; 0x3F8A9556 = 00111111 10001010 10010101 01010110
; 0x0000003F = 00111111 = 63
ConsoleWrite("Fourth Byte " & Dec(Hex(BinaryMid(0x3F8A9556, 4, 1)))) ; 1-based
ConsoleWrite(" = danielkza " & _BitRange(0x3F8A9556, 24, 31)) ; 0-based
ConsoleWrite(" = Malkey     " & _BitValueFromHexMid(0x3F8A9556, 25, 8) & @CRLF) ; 1-based

;For a 32bit number, the right most bit is bit number 0,
; the left most bit is bit number 31.
Func _BitRange(\$v, \$start, \$end = -1)
; We only work for integers, sorry
If Not IsInt(\$v) Then Return SetError(1, 0, 0)

; Check for a valid range
If \$start < 0 Or \$start > 31 Then
Return SetError(2, 0, 0)
EndIf

; Default to retrieving a single bit
If \$end < 0 Then
\$end = \$start
; Another range check
ElseIf \$end < \$start Then
Return SetError(3, 0, 0)
EndIf

Local \$mask, \$range = \$end - \$start

; First, we check if the most significant (sign) bit is of any importance.
If \$end = 31 Then
; If it is, we first handle the special case of retrieving all the bits.
If \$start = 0 Then Return \$v

; If fewer than 32 bits matter, we can use 1 of the meaningless ones as we wish.
; What allows this is the fact that signed shifts, as in AutoIT,
; set vacant bits to the current value of the sign bit.

; In this case, we can't ignore the most significant bit.
; Because of that, the mask works right-to-left:
; The sign bit is set, and propagates that value to (end-start) bits at its right

; We apply the mask first, then use a rotation to emulate our shift.
; This works because by applying the mask, we assured all non-wanted bits are 0s
Return BitRotate(BitAND(\$v, \$mask), -31 + \$range, "D")
EndIf

; Here, we need not care for bit 31 at all.
; Therefore, this mask works left-to-right: the sign bit *cleans* the bits to its right.
\$mask = BitShift(0x7FFFFFFF, 30 - \$range)

; Here, we *first* shift the value to the right as much as needed to
; put our first wanted bit at index 0
; Then, afterwards, we apply our mask, and we're done.
EndFunc ;==>_BitRange

;For a 32bit number, the right most bit is bit number 1,
; the left most bit is bit number 32.
Func _BitValueFromHexMid(\$hex, \$iStart, \$iCount)
Local \$b = "", \$Output = 0
;Hex to Binary
For \$i = 1 To 32
\$b = BitAND(\$hex, 1) & \$b
\$hex = BitShift(\$hex, 1)
Next
\$Bin = StringMid(StringRegExpReplace(\$b, "(.{8})", "\1"), 33 - \$iCount - \$iStart + 1, \$iCount)
;Binary to Dec
Local \$num = StringSplit(\$Bin, "")
Local \$Output = \$num[\$num[0]]
For \$n = 1 To \$num[0] - 1
If \$num[\$num[0] - \$n] = "1" Then \$Output += (2 ^ (\$n))
Next
Return \$Output
EndFunc ;==>_BitValueFromHexMid```

## Create an account

Register a new account

×

• Wiki

• Back

• Git