To determine the value of each bit in a byte.

How to check the value of a specific bit in a number expressed in hexadecimal format?
For example, if the number is represented in hexadecimal as “0x60”, in binary it would be “01100000”. How can we determine the value of, let’s say, the 2nd or 7th bit? Are there any built-in functions for this in MikroTik?
I tried to do the following:

:local value 0x60;

:local bit0Value ( $value & 0x1 > 0 );
:put "The value of the 0 bit.: $bit0Value";

:local bit1Value ( $value & 0x2 > 0 );
:put "The value of the 1 bit.: $bit1Value";

:local bit2Value ( $value & 0x3 > 0 );
:put "The value of the 2 bit.: $bit2Value";

:local bit3Value ( $value & 0x4 > 0 );
:put "The value of the 3 bit.: $bit3Value";

:local bit4Value ( $value & 0x5 > 0 );
:put "The value of the 4 bit.: $bit4Value";

:local bit5Value ( $value & 0x6 > 0 );
:put "The value of the 5 bit.: $bit5Value";

:local bit6Value ( $value & 0x7 > 0 );
:put "The value of the 6 bit.: $bit6Value";

:local bit7Value ( $value & 0x8 > 0 );
:put "The value of the 7 bit.: $bit7Value";

The results do not match.

Your hex values used for testing are wrong.

/system/script> run test
The value of the 0 bit.: false
The value of the 1 bit.: false
The value of the 2 bit.: false
The value of the 3 bit.: false
The value of the 4 bit.: false
The value of the 5 bit.: true
The value of the 6 bit.: true
The value of the 7 bit.: false

0x60 = 0110 0000, so 2 bits will return true.

And you need to test with moving bit, so
0x1, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80

:local value 0x60;
:local bit0Value ( $value & 0x1 > 0 );
:put "The value of the 0 bit.: $bit0Value";

:local bit1Value ( $value & 0x2 > 0 );
:put "The value of the 1 bit.: $bit1Value";

:local bit2Value ( $value & 0x4 > 0 );
:put "The value of the 2 bit.: $bit2Value";

:local bit3Value ( $value & 0x8 > 0 );
:put "The value of the 3 bit.: $bit3Value";

:local bit4Value ( $value & 0x10 > 0 );
:put "The value of the 4 bit.: $bit4Value";

:local bit5Value ( $value & 0x20 > 0 );
:put "The value of the 5 bit.: $bit5Value";

:local bit6Value ( $value & 0x40> 0 );
:put "The value of the 6 bit.: $bit6Value";

:local bit7Value ( $value & 0x80 > 0 );
:put "The value of the 7 bit.: $bit7Value";

I tried to do this and got the wrong result. But apparently my function of converting hex to bit was wrong, because I got it 10010110
I also tried version 0x1, 0x02, 0x04, 0x08, 0x16, 0x32, 0x64, 0x128. Apparently I do not quite understand how to properly convert to another type of display.
Tell me more. Does Mikrotik have a built-in function that would immediately print out the converted number from hex to bit?

True, it appears you have some homework on the basics of conversion between binary and hex :laughing:
(damn, that’s almost 40 years ago I learned that …)

Tip: Windows calculator in programmer mode can help.
Or a stupid piece of paper. Write it down. Then you will see how it goes.

I learned about this for about a week))) I haven’t fully mastered it yet))) And look at the request that I added above. While correcting the answer, you have already written your own.

http://forum.mikrotik.com/t/rextended-fragments-of-snippets/151033/18

Offered by our house cat Rex.

Shift n bits -1 right (bitwise >>) to get bit at position from right to left and check with bitwise & 1.
Examples:

To check: 01100000

> :local value 0x60
> :put (($value >> 1) & 1)
> 0

To check: 01100000

> :local value 0x60
> :put (($value >> 6) & 1)
> 1

Now I’m starting to understand your PDU reading code.

Mostly is not mine :slight_smile:, it’s taken from http://forum.mikrotik.com/t/script-for-sending-incoming-sms-to-mail-with-full-parsing/140125/1 but I understand enough to adapt it for my purpose.

I hope you understand that I recently started doing this))) And I would like to clarify. Should the shift start from 0 or from 1?

0, because 1 (bit position) - 1 = 0
You don’t need to shift with 0, just check with ($value & 1)

01100000

> :local value 0x60
> :put ($value & 1)
> 0

I felt nominated, here’s a little gift…

based on:
http://forum.mikrotik.com/t/rextended-fragments-of-snippets/151033/18

Obtain a bit value from a byte (expected input from 0x00 to 0xFF, and the wanted bits. If the bits number is not specified, convert all byte to bit.
0x can be omitted

:global getMyBitFromHex do={
    :local conv   $1
    :if (!($conv~"(^0x|^)[0-9a-fA-F]{2}\$")) do={:return "00000000"}
    :if ([:typeof [:find $conv "0x" -1]] = "nil") do={:set conv "0x$conv"}
    :local number [:tonum $conv]
    :local wanted [:tostr "$2"]
    :if ($wanted = "") do={:set wanted "87654321"}
    :local values [:toarray "x,0,0,0,0,0,0,0,0"]
    :local power 1
    :local output ""
    :for position from=1 to=8 step=1 do={
        :if ($number & $power) do={:set ($values->$position) 1}
        :set power ($power * 2)
        :if ([:len [:find $wanted $position]] > 0) do={
            :set output "$($values->$position)$output"
        }
    }
    :return $output
}

As wanted bit(s) can be specified one or more position.
Position is from 8 to 1.

> :put [$getMyBitFromHex “0xA8”]
10101000

> :put [$getMyBitFromHex “0xA8” 8]
1

> :put [$getMyBitFromHex “0xA8” 765]
010 <<== is 2

> :put [$getMyBitFromHex “0xA8” 4321]
1000 <<== is 8
no matter the specified bits order, or if is specified a wrong position or same time the same position.

And another gift,

you provide the wanted bit set to 1 on the byte, and on out you have the wanted hex value

:global getMyHexFromBit do={

    :local numbyte2hex do={
        :local input [:tonum $1]
        :local hexchars "0123456789ABCDEF"
        :local convert [:pick $hexchars (($input >> 4) & 0xF)]
        :set convert ($convert.[:pick $hexchars ($input & 0xF)])
        :return $convert
    }

    :local wanted [:tostr "$1"]
    :if ($wanted = "") do={:set wanted "87654321"}
    :local power  1
    :local output 0
    :for position from=1 to=8 step=1 do={
        :if ([:len [:find $wanted $position]] > 0) do={
            :set output ($output + $power)
        }
        :set power ($power * 2)
    }
    :return [$numbyte2hex $output]
}

> :put [$getMyHexFromBit 864]
A8

> :put [$getMyHexFromBit 246]
2A

> :put [$getMyHexFromBit 2]
02

> :put [$getMyHexFromBit 4]
08
no matter the specified bits order, or if is specified a wrong position or same time the same position.

Not quite on topic, but related.
Why can I print like this:

:put ( "\41" )

And get A.
And this is not how it works:

:local num 41
:put ( "\\$num"  )

And how can this be done?

(wrong assumptions from the author of previous post, read my next posts)

Thank you. I understand that this can only be done using the ":parse" command?

Otherwise I wouldn’t have written it that way…

There is no function that converts a hex to a character,
otherwise I wouldn’t have written my own functions… also including this…
You’d better take a look…
http://forum.mikrotik.com/t/how-to-convert-a-hex-value-to-a-char/97913/9

One moment, do not do confusion…
\xx is supposed to be a hexadecimal number, not a decimal number, do not call the var “num”, call it “hex”
you continuosly confuse the number base…

0x41 is 65, so that way can not be used to print decimal “41” as character.
41 on hex is 0x29 and the correct character is the )

If you really want convert HEXADECIMAL number 0x41 to a character “A”:

:local hex "41"
:put [[:parse ":return \"\\$hex\""]]

If you really want convert DECIMAL number 41 to a character “)”:

:local num 41

:local numbyte2hex do={
    :local input [:tonum $1]
    :local hexchars "0123456789ABCDEF"
    :local convert [:pick $hexchars (($input >> 4) & 0xF)]
    :set convert ($convert.[:pick $hexchars ($input & 0xF)])
    :return $convert
}

:put [[:parse ":return \"\\$[$numbyte2hex $num]\""]]

Ah, things haven't changed after a week off :laughing:

Just something similar to the best of my knowledge and tried to do. That's why the question arose why the symbol does not print.

:local nums 65
:local res ""
:local res1 ""

:for i from=7 to=4 do={
    :set res ($res.(($nums >> $i) & 1) )
}
:set res [ :pick "0123456789ABCDEF"  ( ( [ :tonum $res ] ) & 0xF) ]

:for i from=3 to=0 do={
    :set res1 ($res1.(($nums >> $i) & 1) )
}
:set res1 [ :pick "0123456789ABCDEF"  ( ( [ :tonum $res1 ] ) & 0xF) ]

:set res ($res.$res1)
:put [[:parse ":return \"\\$res\""]]

Only yesterday I didn’t succeed for one moment (printing), and today I tried to sort through all the characters from this table https://upload.wikimedia.org/wikipedia/commons/1/1b/ASCII-Table-wide.svg, but not all are printed.
And your way prints