https://learn.sparkfun.com/tutorials/hexadecimal
http://stackoverflow.com/questions/14113051/how-to-calculate-size-of-memory-by-given-a-range-of-address
The hexadecimal system is commonly used by programmers to describe locations in memory because:
1) it can represent every byte (i.e., eight bits) as two consecutive hexadecimal digits instead of the eight digits that would be required by binary (i.e., base 2) numbers
BINARY
_ _ _ _ _ _ _ _ = 8 bits = 1 byte.
2 2 2 2 2 2 2 2 = 2^8 = 256 representations (memory addresses)
HEX
_ _ where each bit has 16 representations (0-9, a-f) so
16 16 = 16 ^ 2 = 256 representations (memory addresses)
2) and the three digits that would be required with decimal numbers.
example
_ _ _ _ _ _ _ _ ( 8 bits )
0 0 0 0 0 0 0 0 ( 1 )
0 0 0 0 0 0 1 1 ( 2^1 + 2^0 = 3 )
0 0 0 0 1 0 1 0 ( 2^3 + 2^1 = 8 + 2 = 10 )
1 1 1 1 1 1 1 1 ( 2^7 + 2^6 + 2^5 + 2^4 + 2^3 + 2^2 + 2^1 + 2^0 = 128 + 64 + 32 + 16 + 8 + 4 + 2 + 1 = 255
where each number represent a memory location.
Hence, 8 bits we can represent from from 0 – 255, or 256 different memory locations.
However, the 8 bit representation is difficult visually.
The hex system can represent 256 memory addresses with just 2 hex digits.
0 0 ( 0 )
0 3 ( 3 )
0 10 ( 10 )
F A ( 15 * 16^1 + 10 * 16^0 = 240 + 10 = 250 )
F F ( 15 * 16^1 + 15 * 16^0 = 255 )
In addition, it is much easier for humans to read hexadecimal numbers than binary numbers, and it is not much more difficult for computer professionals to read hexadecimal numbers than decimal numbers.
Converting from Decimal to Hex
Say we want to convert 61453 to hex.
61352/16 = 3840 R13 (13 in hex is D)
3840 /16 = 240 R0 (0 in hex is 0)
240 /16 = 15 R0 (0 in hex is 0)
15 /16 = 0 R15 (15 in hex is F)
Hence the resulting conversion to hex is 0xF00D
Converting from Hex to Decimal
0xF00D
F * 16^3 + 0 * 16^2 + 0 * 16^1 + D * 16^0
15 * 4096 + 0 * 256 + 0 * 16 + 13 * 1 = 61440 + 0 + 0 + 13 = 61453
Binary to Hex
We use hex in electrical and computer engineering because it’s incredibly easy to convert to and from binary – the 1’s and 0’s language of computers.
each digit of a hexadecimal number “maps” to four bits (a bit being an individual binary digit) of a binary value.
a hex decimal is: 0-15, which is 16 digits. 16 representations.
In binary, we need 4 bits to make 16 representations:
0000 = 0
1111 = 15
Hence that is how ONE hex bit “maps” to FOUR binary bits.
Going further a byte – eight binary digits – can be represented by two hexadecimal digits.
This makes hex a really great, concise way to represent a byte or group of bytes.
From binary to hex
binary: 0b101111010100001
sort them into group of 4s:
0101 1110 1010 0001
5 E A 1
From hex to binary
Take a hex digit and turn it into four binary digits:
0 x B E E F
B is 11
11 in binary is 1 0 1 1
E is 14
14 in binary is 1 1 1 0
F is 15
15 in binary is 1 1 1 1
Hence 0 x BEEF in binary is
1011 1110 1110 1111
Easily representing values of bytes
Hex is often easier for us to work with because the values are shorter and more memorable than a long string of 1’s and 0’s.
Let’s say:
CTRL_REG2_G is the name of the register, with address 0010 0001
it’s much easier to remember 0x21 than 0b010001
For that reason, we’re much more likely to use hex values in our code than their binary equivalents.
Working with programming languages in IDE
Often in IDEs, when you are debugging, you’ll see hex addresses assigned to your variables.
For example, say you create an array:
1 |
int * entry = new int[8]; |
If you print out the addresses of each integer, you
1 2 3 4 5 6 7 |
cout << entry << endl; cout << (entry + 1) << endl; cout << (entry + 2) << endl; for ( int i = 0; i < 8;i i++) { cout << (entry +i) << endl; } |
you’ll see the list of addresses for each integer
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
entry[0]: 0 address 0x1004000a0 entry[1]: 1 address 0x1004000a4 entry[2]: 2 address 0x1004000a8 entry[3]: 3 address 0x1004000ac entry[4]: 4 address 0x1004000b0 entry[5]: 5 address 0x1004000b4 entry[6]: 6 address 0x1004000b8 entry[7]: 7 address 0x1004000bc |
Given that we created an array of 8 integer elements,
each int can represent up to 4 bytes (or 4 * 8 bits = 2^32 bits) of data.
This means each integer can have 2^32 representations.
For example,
-2,147,483,648 to 2,147,483,647 as a signed int (signed means negative and positive)
or 0 to 4294967296 as an unsigned int.
We see that the 1st int’s starting address is at 0x1004000a0.
the 2nd int’s starting address is at 0x1004000a4.
So how does an int sit at 0x1004000a0 to 0x1004000a4-1, and to mean 4 bytes?
Most CPU has the 1 byte address architecture. This means that each address contains 1 byte or 8 bits.
Hence, at 0x1004000a0, there is a register that can store 8 bits (or 1 byte) of information.
In other words, at 0x1004000a0, we can contain anywhere from 00000000 to 11111111.
at 0x1004000a1, we can contain another byte of data.
at 0x1004000a2, we can contain another…
Hence from 0x1004000a0 to 0x1004000a3, we have a total of 4, 1 byte registers, that we can store data.
It can store any representations from:
00000000 00000000 00000000 00000000
…
…
11111111 11111111 11111111 11111111
Therefore if we have 4 registers, that means we can store 2^(4 * 8bits) different representations of data.
Since an int can represent 4294967296 different datas, it needs 4 bytes or 32 bits to do it.
That is why an int’s address starts at 0x1004000a0, and ends at 0x1004000a4 – 1.