Questions about this topic? Sign up to ask in the talk tab.

Difference between revisions of "Bitwise math"

From NetSec
Jump to: navigation, search
(Circular Shift or Bit Rotation)
(Negative Numbers)
Line 98: Line 98:
 
== Negative Numbers ==
 
== Negative Numbers ==
  
There are several ways to represent a negative number:
+
{{:Bitwise math/Negative Numbers}}
* Sign and Magnitude
+
* Two's Complement
+
 
+
  
 
=== Sign and Magnitude ===
 
=== Sign and Magnitude ===
  
The first bit is considered the sign bit, which if set, translates the number to it's negative counterpart.  While this is very straightforward, it requires a a new operation to be supported by the hardware (subtraction), and generates two representations for the 0 value (10000000 and 00000000). As a result, the sign bit is usually used on the largest endian number (called the two's compliment implementation), so that there can be a negative value one value higher or lower than the highest positive value, for example:
+
{{:Bitwise math/Negative Numbers/Sign and Magnitude}}
:* '''1000 = -8, while 0111 = 7'''
+
  
 
=== Two's Complement ===
 
=== Two's Complement ===
  
A two's complement is basically a NOT operation performed on the nibble. Any binary number is converted between positive and negative by computing its two's complement. The leftmost bit is called the sign bit. There are two ways. (taking nibbles as an example) -1 could be 1001. This is not useful, as now there are two ways to represent 0, 1000 for -0 and 0000 for ordinary 0. Also the addition and subtraction has to be changed for this. This is all not nice.
+
{{:Bitwise math/Negative Numbers/Two's Compliment}}
This is why people invented two's complement, two's complement is basically using 1111 for -1 and 1000 for -8.
+
 
+
The first operation performed is a NOT operation on the nibble, -1 has to be done. To determine the two complements the positive representation of the number is required. If it's negative, complement it and add one. Thus, to determine the two complements, positive representation of the number is required. If the original value is negative, determine the compliment and do +1. If its positive, the easy way to do it, is to tack zeroes on in the right number of bits. If negative tack 1's instead.
+
 
+
Just using one byte. It has 256 possible values
+
Doing something like:
+
 
+
{| class="wikitable"  width="40%" style="text-align:center"
+
|+
+
|-
+
| -42
+
| -42 + 256
+
| -42 + 255 + 1
+
|  255 - 42  + 1
+
|  213 + 1
+
|  214
+
|}
+
 
+
The binary representation of both numbers /without/ a signing bit is the same.
+
 
+
Computers use this stuff to represent signing amongst other things. When doing arithmetic stuff gets messy. This gets even more messy when doing arithmetic shifts and rotates with carry on a CPU, since that's what modern day CPU's use.
+
 
+
Taking the example of -42. First, its positive representation is taken. So 42 in binary is: 00101010 (32+8+2). All of those placeholders have 1's and the rest have 0's.
+
 
+
Next step, as mentioned is to perform a NOT operation. So NOT(00101010) WILL BE 11010101. Replace 1 by 0 and vice-versa. Final step is to add 1 to the number obtained in above step.
+
Thus:
+
 
+
{| class="wikitable"  width="40%" style="text-align:center"
+
|+
+
|-
+
!11010101
+
| +
+
!00000001
+
|=
+
!11010110
+
|}
+
 
+
What can also be done, is go at the bits one by one, starting at the right, and copy all the zeroes, until a 1 is obtained. Copy that 1 too, then flip all the remaining bits. So 42 is obtained again, which is 00101010. Then move from right-to-left, and get 11010110.
+
  
 
== Overflows ==
 
== Overflows ==

Revision as of 05:17, 19 July 2012

Bitwise math is the foundation of all binary math and most mathematic operations performed in assembly. Many of the bitwise mathematics primitive operators can be found in a variety of compiled languages and interpreted languages as well.

Introduction to Binary

Bitwise math/Introduction to Binary

Basic Addition

Bitwise math/Introduction to Binary/Basic Addition

Binary to Hexadecimal

The past exercises have featured working with 4 bits at once (4 values ranging from 0-1, e.g. 0001). This is known as a nybble in hexadecimal. A byte is made of two nybbles (8 bits make a byte).

In hexadecimal, there is a 1’s placeholder and a 16’s placeholder. Hexadecimal is 0 through 9 and A through F. A nybble can hold 16 unique values but the highest value is 15 because one of the values is 0. A nybble is a single hex digit. So, A = 10, B = 11, so on and so forth, F = 15.

In hex, AF is obtained as a byte.

AF = 175 in decimal because A is in the 16’s placeholder

  • A = 10, 10*16=160,

Plus F which is in the 1’s placeholder,

  • F = 15, 15*1=15

Therefore 160(A)+15(F) = 175.

NOT, AND, OR and XOR

Bitwise math/NOT, AND, OR and XOR

NOT

Bitwise math/NOT, AND, OR and XOR/NOT

AND

Bitwise math/NOT, AND, OR and XOR/AND

AND rules

Bitwise math/NOT, AND, OR and XOR/AND/AND rules

AND properties

Bitwise math/NOT, AND, OR and XOR/AND/AND properties

AND example

Bitwise math/NOT, AND, OR and XOR/AND/AND example

AND logic table

Bitwise math/NOT, AND, OR and XOR/AND/AND logic table

OR

Bitwise math/NOT, AND, OR and XOR/OR

OR rules

Bitwise math/NOT, AND, OR and XOR/OR/OR rules

OR properties

Bitwise math/NOT, AND, OR and XOR/OR/OR properties

OR example

Bitwise math/NOT, AND, OR and XOR/OR/OR example

OR logic table

Bitwise math/NOT, AND, OR and XOR/OR/OR logic table

XOR

Bitwise math/NOT, AND, OR and XOR/XOR

XOR rules

Bitwise math/NOT, AND, OR and XOR/XOR/XOR rules

XOR properties

Bitwise math/NOT, AND, OR and XOR/XOR/XOR properties

XOR example

Bitwise math/NOT, AND, OR and XOR/XOR/XOR example

XOR logic table

Bitwise math/NOT, AND, OR and XOR/XOR/XOR logic table

Shift and rotate

Each of these operations can occur either to the right or to the left. Examples will use nibbles as operands (4 bits or 0.5 bytes).

Logical Shifts

For logical shifts, the bytes are assumed to be in big endian.

Using A or 1010 as an example:

Example: A shifted left by 1 = 4
Operation Hexadecimal Binary comment


Left Shift

A

1

1010

0001

shifted to the left once, the 1 at the beginning gets shifted off, thus the binary value becomes 0100, or 4 in hexadecimal.
= 4 0100 The end value 0 is always used to replace the residual numbers.


Example: A shifted left by 2 = 8
Operation Hexadecimal Binary comment


Left Shift

A

2

1010

0001

The first `10' is shifted off and the remaining two placeholders get zeroed out.
= 8 1000 The end value 0 is always used to replace the residual numbers.




Example: A shifted right by 1 = 5
Operation Hexadecimal Binary comment


Right Shift

A

1

1010

0101

a single shift to the right is division by two for even numbers.
= 5 0101 The end value 0 is always used to replace the residual numbers.


If 'A' is shifted to the right twice it goes from 1010 to 0010

Operation Hexadecimal Binary comment


Right Shift

A

2

1010

0001

shifted to the right twice, the one at the beginning gets shifted to the 2nd digit and the one in the 2nd digit place gets shifted off, thus the binary value becomes 0010, or 2 in hexadecimal.
= 2 0010 The end value 0 is always used to replace the residual numbers.

At this point, understanding should be emerging into real hacking and cryptography. If understanding is not attained regarding this knowledge, further extension topics will prove difficult. Thus, it is considered a baseline knowledge.

Exercises:

1) Solve for B left shift one


Operation Hexadecimal Binary


Left Shift One

B

1

"(B in Binary)"

0001

= "??" "???"

2) Solve for F right shift three

Operation Hexadecimal Binary


Right Shift three

F

3

"(F in Binary)"

0011

= "??" "???"

Answers:


1) 0110 or 6.

Operation Hexadecimal Binary


Left Shift One

B

1

1011

0001

= "6" "0110"


2) 0001 or 1.


Operation Hexadecimal Binary


Right Shift three

F

3

1110

0011

= 0001 1

Logical Shifts

For logical shifts, the bytes are assumed to be in big endian.

Using A or 1010 as an example:

Example: A shifted left by 1 = 4
Operation Hexadecimal Binary comment


Left Shift

A

1

1010

0001

shifted to the left once, the 1 at the beginning gets shifted off, thus the binary value becomes 0100, or 4 in hexadecimal.
= 4 0100 The end value 0 is always used to replace the residual numbers.


Example: A shifted left by 2 = 8
Operation Hexadecimal Binary comment


Left Shift

A

2

1010

0001

The first `10' is shifted off and the remaining two placeholders get zeroed out.
= 8 1000 The end value 0 is always used to replace the residual numbers.




Example: A shifted right by 1 = 5
Operation Hexadecimal Binary comment


Right Shift

A

1

1010

0101

a single shift to the right is division by two for even numbers.
= 5 0101 The end value 0 is always used to replace the residual numbers.


If 'A' is shifted to the right twice it goes from 1010 to 0010

Operation Hexadecimal Binary comment


Right Shift

A

2

1010

0001

shifted to the right twice, the one at the beginning gets shifted to the 2nd digit and the one in the 2nd digit place gets shifted off, thus the binary value becomes 0010, or 2 in hexadecimal.
= 2 0010 The end value 0 is always used to replace the residual numbers.

At this point, understanding should be emerging into real hacking and cryptography. If understanding is not attained regarding this knowledge, further extension topics will prove difficult. Thus, it is considered a baseline knowledge.

Exercises:

Bitwise math/Exercises:

Circular Shift or Bit Rotation

Bitwise math/Circular Shift or Bit Rotation

Negative Numbers

Bitwise math/Negative Numbers

Sign and Magnitude

Bitwise math/Negative Numbers/Sign and Magnitude

Two's Complement

Bitwise math/Negative Numbers/Two's Compliment

Overflows

Now, overflow occurs in a "signed" integer when it increments too far. Using a nibble for an example,

-8 4 2 1

The highest positive value is 7, 0111, the lowest negative value is -8, 1000. On a processor, the increment instruction(inc) changes this. If -8 is incremented, -7 is obtained, since it is incremented. Basically when moving to 7 and incremented, the next step in binary is 1000 and it lands on -8.

In an arithmetic shift, this is typically what processors do since signed numbers are worked with most of the times. Now of course, there are ways to use unsigned numbers, but this will be left for later. Most languages use an arithmetic shift, which is also called a 'signed shift'. This is because the number is "signed", that is, it has a + or - attatched to its value. Thus, when reading the hex, the way this works isn't going to change so terribly.

Example: 6 incremented left by 1, becomes -8 (1100)'
Operation Hexadecimal Binary comment


Left Shift

6

1

0110

0001

shifted to the left once, the largest digit gets a 1. In this case, this gives the whole value a -8, not an eight.
= "-8" 1100 The highest value "loops" back around to the lowest, like a clock/modular arithmetic.

The difference here is if that first bit is -8 and not an 8. A positive number has just been turned into a negative number. 6 left shift 1 = -4

Binary number 1100 = -8 + 4 = decimal number -4
Negative Eights -(1x2^3) Fours (1x2^2) Twos (1x2^1) Ones (1x2^0)
-8 4 2 1
1 1 0 0

It's now -4.

If shifted to the right, a single shift will /always/ change the sign. If shifted to the left on any /unsigned/ binary number (shift by n), it is the same as multiplying it by 2^n. If shifted to the right on a two's complement signed number it is the same as dividing it by 2^n and always rounds down.

Example:

-8 right shift 1 or 1000 right shift 1 becomes 4. In other words, any signed number right shifted becomes positive immediately. Regardless of whether it was positive or not, it will always be positive once a right shift has been applied.

As stated before, x right shift n on a signed number is the same as x/(2^n). The problem that this could cause is that it always rounds down. So, if it always rounds down from 2^n (i.e. a fraction is obtained) it will round down until the fraction is gone.

The flow on problem from this is that if it rounds down and n is signed, the processor can run into a divide by zero error.

Rotate With Carry

Moving on now to rotate with carry. Rotate with carry occurs on a computer when a number is too large to fit into a single register. For example: On 32 bit systems the largest value an unsigned variable can hold is 2^32 - 1. An 8 bit system is being used just for sanity:

2^8 - 1 = 255

That would be the largest value that can be held. If wanting to hold 256, it would need two pieces of processor memory to do this so rotate with carry. There's a bit on the CPU called CF or carry flag. It is just a little bit, 1 or 0. So on an 8 bit system a 16 bit number would want to be rotated.

16 bit number 1011 1000 1010 0011

Now, the registers only contain 8 bits, so:

  • register 1 = 1011 1000
  • register 2 = 1010 0011

To connect these during the shift operation rather the rotate operation, there is a small bit called the carry flag (CF) on a CPU, that will store the value as the bits are shifted between the two registers. It will take the first "1" from register 2 into the CF bit then move all of register2 1 bit to the left, and so on and so forth.

Bitwise math is part of a series on programming.
<center>
</center>