Before we can discuss memory, we must first learn hexadecimal counting.
We count with ten different digits, and a number represents coefficients multiplied by different powers of 10. For example, $543$ is equal to $5$ hundreds ($= 10^2$) plus $4$ tens ($= 10^1$) plus $3$ ones ($= 10^0$).
When counting, once we reach 9, we carry a 1 and add that to the coefficient of the next higher power of ten.Nothing requires us to have 10 digits, and its almost the worst possible base other than perhaps base $7$, $11$ or $19$. One base that is more convenient for computers is base 16, so we now have sixteen different digits:
0 1 2 3 4 5 6 7 8 9 a b c d e f
Now, you could set up addition and multiplication tables in base 16, so $9 + 3 = c$, $f + 1 = 10$, $ff + 1 = 100$, $9 \cdot 4 = 1c$, and $d^2 = a9$, but this isn't necessary here.
Instead, all you need to do is understand how to count in hexadecimal.
First, we will represent hexadecimal numbers by prefixing them by 0x, so 0x32 is a hexadecimal number and not thirty-two. Instead, 0x32 means $3 \times 16 + 2 = 50$.
Next, the number that comes before 0x32 is 0x31 ($= 49$), and the number that comes after is 0x33 ($= 51$).
Similarly, the number that comes after 0x3d49 is 0x3d4a, and the number after that is 0x3d4b.
The number after 0x3d4f is 0x3d50, the number after 0x3d9f is 0x3da0, and the number after 0x32adfff is 0x32ae000.
Addresses tend to be stored in multiples of 2, 4 or 8, so starting at 0xff8a3d0 and counting by twos:
0xff8a3d0
0xff8a3d2
0xff8a3d4
0xff8a3d6
0xff8a3d8
0xff8a3da
0xff8a3dc
0xff8a3de
0xff8a3e0
0xff8a3e2
0xff8a3e4
Starting at the same number but counting by four:
0xff8a3d0
0xff8a3d4
0xff8a3d8
0xff8a3dc
0xff8a3e0
0xff8a3e4
0xff8a3e8
0xff8a3ec
0xff8a3f0
Starting at the same number but counting by eight:
0xff8a3d0
0xff8a3d8
0xff8a3e0
0xff8a3e8
0xff8a3f0
0xff8a3f8
0xff8a400
0xff8a408
0xff8a410
For humor, however, here are the words to a song written by Paul McCarthy rewritten for hexadecimal:
Two and two are four
Four and four are eight
Eight and eight are ten (0x10)
Ten and ten are twenty (0x20)
Hex worm, hex worm
Measuring the memory
You and your arithmetic
You'll probably go far
Twenty and twenty are forty
Forty and forty are eighty
Eighty and eighty are one hundred (0x100)
One hundred and a hundred are two hundred (0x20)
Hex worm, hex worm
Measuring the memory
Seems to me you'd stop and see
How binary they are
A 32-bit computer has $2^{32} = 2^{4 \times 8} = (2^4)^8 = 16^8$ possible different addresses. Each byte has a different address, and thus the maximum number of bytes that can have different addresses are $2^{32}$ or approximately four billion (hence four gigabytes). Thus, any address of a 32-bit computer can be written with exactly eight hexadecimal numbers.
0x00000000 First byte in memory
0x00000001
0x00000002
0x00000003
0x00000004
0x00000005
0x00000006
0x00000007
0x00000008
0x00000009
0x0000000a
0x0000000b
0x0000000c
0x0000000d
0x0000000e
0x0000000f
0x00000010
.
.
.
.
0xffffffef
0xfffffff0
0xfffffff1
0xfffffff2
0xfffffff3
0xfffffff4
0xfffffff5
0xfffffff6
0xfffffff7
0xfffffff8
0xfffffff9
0xfffffffa
0xfffffffb
0xfffffffc
0xfffffffd
0xfffffffe
0xffffffff Last byte in memory
On a 64-bit system, addresses can be up to 64 bits long, or 16 hexadecimal characters; however, currently no one on the planet has sufficient memory to allow each address to be used—this would 18 quintillion bytes, or almost 17 million terabytes of memory.
At the other end, microcontrollers may have address buses as small as 16 bits; such microcontrollers can only access 64 kilobytes of memory. One long-running microprocessor that used only 16 bit addresses is the Motorola 6800. First introduced in 1974, it was last produced in 2006.
We will be referring to memory locations in future lessons, but for the most part, everything discussed here should be sufficient.
As you are likely aware, memory is divided into bytes, and each byte has its own address. Each byte is 8 bits, and thus, there are $2^8$ different values a byte can store. Note that $2^8 = 2^{4 \times 2} = (2^4)^2 = 16^2$, so to represent all possible values of a byte, you need only two hexadecimal characters:
Binary Hex Decimal
00000000 0x00 0
00000001 0x01 1
00000010 0x02 2
00000011 0x03 3
00000100 0x04 4
00000101 0x05 5
00000110 0x06 6
00000111 0x07 7
00001000 0x08 8
00001001 0x09 9
00001010 0x0a 10
00001011 0x0b 11
00001100 0x0c 12
00001101 0x0d 13
00001110 0x0e 14
00001111 0x0f 15
00010000 0x10 16
00010001 0x11 17
00010010 0x12 18
00010011 0x13 19
00010100 0x14 20
00010101 0x15 21
. . .
. . .
. . .
01111001 0x79 121
01111010 0x7a 122
01111011 0x7b 123
01111100 0x7c 124
01111101 0x7d 125
01111110 0x7e 126
01111111 0x7f 127
10000000 0x80 128
10000001 0x81 129
10000010 0x82 130
10000011 0x83 131
10000100 0x84 132
10000101 0x85 133
10000110 0x86 134
. . .
. . .
. . .
11101001 0xe9 233
11101010 0xea 234
11101011 0xeb 235
11101100 0xec 236
11101101 0xed 237
11101110 0xee 238
11100111 0xef 239
11110000 0xf0 240
11110001 0xf1 241
11110010 0xf2 242
11110011 0xf3 243
11110100 0xf4 244
11110101 0xf5 245
11110110 0xf6 246
11110111 0xf7 247
11111000 0xf8 248
11111001 0xf9 249
11111010 0xfa 250
11111011 0xfb 251
11111100 0xfc 252
11111101 0xfd 253
11111110 0xfe 254
11111111 0xff 255