bit masking

10
============================================== Bitwise Operations, bit masking - AND, OR, NOT ============================================== - Ian! D. Allen - [email protected] - www.idallen.com References: ECOA2e p.122 http://atrevida.comprenica.com/atrtut03.html Bitwise operations ------------------ Bitwise operators treat every bit in a word as a Boolean (two-value) variable, apply a column-wise Boolean operator, and generate a result. Unlike binary math, there is no carry or borrow - every column is independent. Examples of 4-bit bitwise AND and OR (written in C or C++ as "&" and "|"): 0110 = 6h 0110 = 6h AND 1010 = Ah OR 1010 = Ah ---- ---- EQUALS 0010 = 2h EQUALS 1110 = Eh In C language: int foo = 0x6 & 0xA; /* bitwise AND gives: foo <-- 2h */ int foo = 0x6 | 0xA; /* bitwise OR gives: foo <-- Eh */ Examples of 4-bit binary bitwise "NOT" (C language uses a tilde operator "~"): NOT 0110 equals 1001 -or- ~6h equals 9h NOT 1010 equals 0101 -or- ~Ah equals 5h NOT 0000 equals 1111 -or- ~0h equals Fh NOT 1111 equals 0000 -or- ~Fh equals 0h You will recoginze the above values from the 4-bit "hex bit flip" table. The NOT operator flips every bit. Note that the word length (number of bits) is critical

Upload: shikhar-thakur

Post on 09-Nov-2015

213 views

Category:

Documents


0 download

DESCRIPTION

Bit Masking

TRANSCRIPT

  • ==============================================Bitwise Operations, bit masking - AND, OR, NOT==============================================- Ian! D. Allen - [email protected] - www.idallen.com

    References: ECOA2e p.122 http://atrevida.comprenica.com/atrtut03.html

    Bitwise operations------------------

    Bitwise operators treat every bit in a word as a Boolean (two-value)variable, apply a column-wise Boolean operator, and generate a result.Unlike binary math, there is no carry or borrow - every column isindependent.

    Examples of 4-bit bitwise AND and OR (written in C or C++ as "&" and "|"):

    0110 = 6h 0110 = 6h AND 1010 = Ah OR 1010 = Ah ---- ---- EQUALS 0010 = 2h EQUALS 1110 = Eh

    In C language:

    int foo = 0x6 & 0xA; /* bitwise AND gives: foo

  • when performinga NOT operation, since *every bit* in the word flips, even the bits youdon't see:

    In C language:

    char x = ~0; /* result is 0xFF */ short x = ~0; /* result is 0xFFFF */ int x = ~0; /* result is 0xFFFFFFFF for 32-bit int */ int x = ~0; /* result is 0xFFFFFFFFFFFFFFFF for 64-bit */

    char x = ~0xF; /* result is 0xF0 */ short x = ~0xF; /* result is 0xFFF0 */ int x = ~0xF; /* result is 0xFFFFFFF0 for 32-bit int */ int x = ~0xF; /* result is 0xFFFFFFFFFFFFFFF0 for 64-bit */

    int x = ~0x1; /* result is 0xFFFFFFFE for 32-bit int */ int x = ~0xFFFF; /* result is 0xFFFF0000 for 32-bit int */ int x = ~0xFFFF0000; /* result is 0x0000FFFF for 32-bit int */

    Note that in C language the bit flip of character 0xF is 0xF0 and not 0x0,since character 0xF is really stored as 0x0F (8 bits) and all 8 bits flip.If you store 0xF in a 32-bit "int", all 32 bits flip, so ~0xF = 0xFFFFFFF0.

    Bit Masking - turning off bits------------------------------

    Bit masking is using the bits in one word to "mask off" or select part ofthe range of bits in another word, using the bitwise Boolean AND operator.The 1 bits in the "mask" select which bits we want to keep in the otherword, and the zero bits in the mask turn all the other correspondingbits to zeroes.

  • In other words, the 1 bits in the mask "copy" the corresponding bitsfrom the other word.

    In other words, the 1 bits are the "holes" in the mask that let thecorresponding bits in the other word flow through to the result.

    *** EXAMPLE 1: A mask to keep just the bottom nybble (4 bits) of a byte. Create a mask that lets only the bottom 4 bits flow through:

    10101010 = AAh AND 00001111 = 0Fh

  • if( (word & 0x4) != 0 ) ...

    This type of bit-logic is used frequently in computer science. Each bit in some word may be assigned some meaning, and you need to mask that bit to tell whether or not it is set in the word.

    The next example applies the Boolean AND technique to find out if afloating-point number has the sign bit set:

    *** EXAMPLE 4: A mask to keep just the sign bit of an IEEE 754 single-precision floating-point number:

    Create a mask that lets only the top bit flow through:

    BFC00000h

  • negative\n";

    Only "x is negative" prints.

    *** EXAMPLE 5: Select just the CTRL (control) bits of an ASCII character.

    ASCII "control" characters are the 32 values from 0-31 decimal (00 to 1F hex). It takes 5 bits to hold these characters (2**5 = 32). Control characters are named by the ASCII letters with which they are associated. A CTRL-A is just the lower 5 bits of the ASCII letter 'A' (or 'a'). A bit mask that selects just the lower 5 bits in an 8-bit byte is: 00011111 = 1Fh

    Create a mask that lets only the bottom 5 bits flow through:

    01000001 = 41h = ASCII upper-case letter 'A' AND 00011111 = 1Fh

  • 5 bits */

    ORing in bits - turning on bits-------------------------------

    The opposite of masking (turning off bits) is "ORing in" bits, wherewe use the bitwise Boolean OR to "turn on" one or more bits in a word.We select a value that, when ORed with some other value, "turns on"selected bits and leaves the other bits unchanged.

    *** EXAMPLE 6: Turn any ASCII letter into lower case.

    In ASCII, the difference between an upper-case letter and a lower-case letter is the value of the bit 00100000 (20h), which is turned on in the lower-case letter. If we "turn on" that bit, the upper-case letter becomes lower-case. (If the letter was already lower-case, the 20h bit is already on; turning it on makes no difference.)

    To make any ASCII letter lower-case, we must "turn on" the 20h bit. This is called ORing-in a bit, since we use the bitwise Boolean OR operator:

    01000001 = 41h = ASCII upper-case letter 'A' OR 00100000 = 20h

  • Note that *adding* is not always the same as *ORing in*. It is true thatif you *add* 20h to an upper-case ASCII letter, it has the same effectas *ORin in* the 20h bit and the letter becomes lower-case, e.g. for'A' = 41h, adding 20h gives 61h which is 'a':

    'A' + 20h --> 'a' /* addition works in this special case */ 41h + 20h --> 61h

    The same is not true if the letter is *already* lower-case, e.g. for'a' = 61h, adding 20h gives 81h which isn't even an ASCII character(since there are only 128 ASCII characters from 00h to 7Fh):

    'a' + 20h --> 81h *** wrong - want 'a' not non-ASCII 81h *** 61h + 20h --> 81h

    ORing the 20h bit works properly even if the letter is already lower case.ORing never causes a carry; addition may cause a carry.

    *** EXAMPLE 7: Turn any ASCII letter into upper case.

    This is the reverse of the above process that makes a lower-case letter by turning "on" the 20h bit. If we "turn off" the 20h bit in a letter, the letter becomes upper-case. (If the letter was already upper-case, the 20h bit is already off; turning it off makes no difference.)

    To turn off that 20h bit, we want to create a bit mask that allows all the other bits to remain on but that sets that one 20h bit to zero, i.e. we want a mask that is the opposite (bitwise NOT) of 20h. The mask must be "0" where 20h is "1". We appply the

  • bitwise NOT to 20h to do this: Take 00100000 = 20h -> apply NOT (bit flip) -> 11011111 = DFh.

    Let's try the mask on a sample ASCII lower-case letter 'a'. (ASCII 'a' has value 61h = 01100001.) Any letter would work.

    01100001 = 61h = ASCII lower-case letter 'a' AND 11011111 = DFh

  • char lowerz = 'z'; char upperz = lowerz & ~' '; /* space = 20h, ~space = DFh, 'z' -> 'Z' */

    char uppera = 'A'; char lowera = uppera | ' '; /* ASCII space = 20h, 'A' -> 'a' */

    Note that *subtracting* is not always the same as *masking*. It is truethat if you *subtract* 20h from a lower-case ASCII letter, it has the sameeffect as *masking* off the 20h bit and the letter becomes upper-case,e.g. for 'a' = 61h, subtracting 20h gives 41h which is 'A':

    'A' - 20h --> 'a' /* subtraction works in this special case */ 61h - 20h --> 41h

    The same is not true if the letter is *already* upper-case, e.g. for'A' = 41h, subtracting 20h gives 21h which is '!':

    'A' - 20h --> '!' *** wrong - want 'A' not "!' *** 41h - 20h --> 21h

    Masking the 20h bit works properly even if the letter is already upper case.Masking never causes a borrow; subtraction may cause a borrow.

    Word length and NOT-------------------

    Remember that the length of the word being operated on makes a differenceto the bitwise NOT operator. *ALL* the bits in the word flip, not justthe ones you think you see:

    char x = ~0x8; /* result is 0xF7 */ short x = ~0x8; /* result is 0xFFF7 */ int x = ~0x8; /* result is 0xFFFFFFF7 for 32-bit int */

  • int x = ~0x8; /* result is 0xFFFFFFFFFFFFFFF7 for 64-bit int */

    You can't directly code the hex "bit flip" table in C language, since thebit-flip table applies to 4-bit hex digits and the shortest data type inC language is an 8-bit char. Storing 0x8 as a char in C means storingthe 8-bit value 0x08. If you bit-flip eight-bit character data 0x8,you are actually bit-flipping all eight bits of 0x08 and the result is0xF7 not 0x7.