A major stumbling block many beginners encounter when attempting to learn assembly language is the common use of the binary and hexadecimal numbering systems.
Review of the Decimal System
You've been using the decimal numbering system for so long that you probably take it for granted.
In a decimal positional numbering system, each digit appearing to the left of the decimal point represents a value between 0 and 9 times an increasing power of 10
Binary Number System
Binary numbers are what defines the core of a computer. Abit within a computer is either on or off. A bit has either electricity turned on or off.
It is important to understand that in binary, each column has a value two times the column to its right and there are only two digits in the base which happen to be 0 and 1.
In decimal, base 10, say we have the number 15 which means (1x10)+(5x1) therefore 5 is the number times 1 and 1 is that number times 10.
Binary works in a similar fashion however we are now referring to base 2 That same number in binary is 1111. To illustrate
1 | 1 | 1 | 1 |
8s | 4s | 2s | 1s |
(8x1)+(4x1)+(2x1)+(1x1)
Binary numbers are important because using them instead of the decimal system simplifies the design of computers and related technologies.
Hexadecimal Number System
This exciting number system is called hexadecimal. The reason why we use this number system is that in x86 Assembly it is much easier to express binary number representations in hexadecimal than it is in any other numbering system.
Hexadecimal is similar to every other number system except in hexadecimal, each column has a value of 16 times the value of the column to its right. The fun part about hexadecimal is that not only do we have 0-9 we have A-F and therefore 16 different symbols.
Let's look at a simple table to see how hexadecimal compares to decimal.
Decimal | Octal | Hex | Binary |
0 | 0 | 0 | 0 |
1 | 1 | 1 | 1 |
2 | 2 | 2 | 10 |
3 | 3 | 3 | 11 |
4 | 4 | 4 | 100 |
5 | 5 | 5 | 101 |
6 | 6 | 6 | 110 |
7 | 7 | 7 | 111 |
8 | 10 | 8 | 1000 |
9 | 11 | 9 | 1001 |
10 | 12 | A | 1010 |
11 | 13 | B | 1011 |
12 | 14 | C | 1100 |
13 | 15 | D | 1101 |
14 | 16 | E | 1110 |
15 | 17 | F | 1111 |
16 | 20 | 10 | 10000 |
17 | 21 | 11 | 10001 |
18 | 22 | 12 | 10010 |
19 | 23 | 13 | 10011 |
20 | 24 | 14 | 10100 |
21 | 25 | 15 | 10101 |
22 | 26 | 16 | 10110 |
23 | 27 | 17 | 10111 |
24 | 30 | 18 | 11000 |
25 | 31 | 19 | 11001 |
26 | 32 | 1A | 11010 |
27 | 33 | 1B | 11011 |
28 | 34 | 1C | 11100 |
29 | 35 | 1D | 11101 |
30 | 36 | 1E | 11110 |
31 | 37 | 1F | 11111 |
32 | 40 | 20 | 100000 |
33 | 41 | 21 | 100001 |
... | ... | ... | ... |
Ok, I see the smoke coming out of your ears but it is ok! In decimal, everything is dealt with in the power of 10. Let's take the number 42 and examine it in decimal:
2 x 10^0 = 2
4 x 10^1 = 40
Remeber 10 to the 0 power is 1 and 10 to thr 1st power is 10. therefore, 2+40 =42
Here comes the fun stuff
If we understand that decimal is a base 10 number system, we can create a simple formula where b represents the base, In this case, b = 10
(2 b ^ 0) + (4 b ^ 1)
(2 10 ^ 0) + (4 10 ^ 1) = 42
I hexadecimal, everything is dealt with in the power of 26. Therefore 42 in decimal is 2A in hexadecimal:
10 * 16 ^ 0 = 10
2 * 16 ^ 1 = 32
Keep in mind 10 decimal is equal to A hexadecimal and 2 decimal is equal to 2 hexadecimal. In our formula above when we deal with A, B, C, D, E or F we need to convert them to their decimal equivalent.
Let's take another example of F5 hexadecimal. This would be as follows:
5 x 16^0 = 5
15 x 16^1=240
5 + 240 = 245 decimal => F5 hexadecimal
It is fundamental that you understand what is going on here in order to proceed any further.
Credits:
x86-64 Assembly Language Programming with Ubuntu by Ed Jorgensen, Ph.D. May 2022
0xinfection's reversing for everyone: https://0xinfection.github.io/reversing/