**Introduction:**

In this module we are going to cover the base system of binary and hexadecimal numbers. In the decimal numbering system we are used to base 10. The place holders in base 10 are the ones place for numbers less than 10, then the 10’s place for numbers between 10 and 10² and so on. The other base systems work exactly the same way just with a different grouping. After we cover the different bases we are going to cover some bitwise logical operations.

**Binary:**

Binary is base two numbering. Lets examine the number 111 in binary. This is equivalent to 1 * 2² + 1 * 2 + 1 = 7. Lets contrast that to the base 10 system where 111 = 1 * 10² + 1 * 10 + 1. The only difference is replacing the 10 with a 2. The operations of addition and subtraction work in the same way as base 10. For example 101 + 110 = 1011 = 1 * 2³ + 1 * 2² + 0 * 2 + 1 = 13.

We can also convert decimal numbers to binary. Lets convert 124 to binary. Since 124 is divisible by 2 we may write it as 2 * 62. 62 = 2 * 31 and so we may rewrite again as 2 * 2 * 31. 31 = 30 + 1 so again rewrite to 2² * ( 30 + 1) = 2² * 30 + 2². Lets keep going and see what happens: 2² * 30 + 2² = 2² * 2 * 15 + 2² = 2³ * ( 14 + 1) + 2² = 2³ * 14 + 2³ + 2² = 2³ * 2 * 7 + 2³ + 2² = 2^{4} * (6 + 1) + 2^{3} + 2^{2} = 2^{4} * 6 + 2^{4} + 2^{3} + 2^{2} = 2^{4} * 2 * 3 + 2^{4} + 2^{3} + 2^{2} = 2^{5} * (2 + 1) + 2^{4} + 2^{3} + 2^{2} = 2^{5} * 2 + 2^{5} + 2^{4} + 2^{3} + 2^{2} = 2^{6} + 2^{5} + 2^{4} + 2^{3} + 2^{2}. Now we just convert to binary notation placing a 1 for every power: 1111100.

**Hexadecimal:**

Hexadecimal is the same notion just using 16 as a base instead of 2 or 10. To accommodate the additional numbers in each place letters were added: A = 10, B = 11, C = 12, D = 13, E = 14, F = 15. When we see a hexadecimal number it will usually have the prefix 0x in front of it.

If we want to convert the number 0x23a into decimal we follow the same process as above. 2 * 16^{2} + 3 * 16 + 10 = 512 + 48 + 10 = 570. Converting from decimal to hex is a little more involved.

To convert from decimal to hex we use the same process we did with binary. We want to pull all the powers of 16 out of the decimal number and group them accordingly. So lets go through and example. Given the decimal number 1013 we have 1013 = 16 * 63 + 5 = 16 * (48 + 15) + 5 = 16 * 16 * 3 + 16 * 15 + 5 = 3 * 16² + 15 * 16 + 5. Now converting to hex notation the result is 0x3f5.

**Bitwise Operators**

Now we are going to go over the bitwise logical operators for x86 assembly. I am using the bitwise label instead of just logical operator because I want to emphasize the bit portion. We will see how it works in an example for each operation.

*AND:*

The *and* operation is 1 if both arguments are 1, otherwise the bit is 0. Lets look at an example:

` 100`**1** 0000 **1**110 = 0x90E
010**1** 1111 **1**001 = 0x5f9
----------------------
0001 0000 1000 = 0x108

We keep the bits in bold because the entries match in both binary digits and zero out everything else.

*OR:*

The *or *operation results in 1 if either operand has a 1 bit in that position, otherwise the bit is 0. Lets use the same operands and see the result:

```
1001 0000 1110 = 0x90E
0101 1111 1001 = 0x5F9
----------------------
1101 1111 1111 = 0xDFF
```

We only have one matching pair of 0 entries so every other bit results in a 1.

*XOR:*

The *xor* operation results in a 1 only if one of the operand bits is 1, otherwise the result is 0. Looking at our example numbers again:

```
1001 0000 1110 = 0x90E
0101 1111 1001 = 0x5f9
----------------------
1100 1111 0111 = 0xCF7
```

*NOT:*

The not operation inverts the bits on the argument:

```
1001 0000 1110 = 0x90E
----------------------
0110 1111 0001 = 0xAF1
```

**Assembly Example:**

Lets look at a common way this is used in assembly. In 32-bit assembly we will come across the instruction

` and esp, 0xfffffff0 `

The purpose of this instruction is to align the top of the stack on a 16 byte boundary, that is make the memory address of the top of the stack divisible by 16. This is done for performance reasons.

Lets take a look at the mechanics of the operation with the assumption that the address stored in esp is 0xbf487e38. To do this by hand we need to first convert the hex values into binary and then perform the and operation.

```
0xfffffff0 = 1111 1111 1111 1111 1111 1111 1111 0000
0xbf487e38 = 1011 1111 0100 1000 1001 1110 0011 1000
----------------------------------------------------
1011 1111 0100 1000 1001 1110 0011 0000 = 0xbf487e30
```

The result is zeroing out the least significant bit of the address making it divisble by 16. Note that we are also aligning by increasing the stack space rather than decreasing. See if you can remember why that’s true even though we are decreasing the address of esp.

Another common way that we see bitwise operators used is to zero out a register using xor. Since the register will always match itself taking the xor of a register with itself always results in zeroing it out.

**Conclusion:**

Here are some practice exercises to see if you have a good understanding of the numbering systems and how to convert between them.

- Is 0x8FB450 divisible by 16? Don’t convert the number out of hex to figure out the answer. Hint: Is 137290 divisible by 10?
- Is 1001001001 divisible by 2? Again don’t convert to figure out the answer. Same hint as in 1.
- Convert 11010010 into hexadecimal notation.
- Convert 0x12A8B into binary notation. Convert to decimal notation without using binary.
- Find the value of each logical operation for the pair 0x774A and 0x83FC.
- What is the value of 183 AND 32? Hint: You may have to add some padding to make the widths match.

Use Google and find a calculator online to compare your answers to what they should be. Better yet write a program to check your answers if you’re feeling ambitious. Some programming languages deal with bitwise operations more easily than others, if you write a program see if you can find the easiest language to implement it in.