Skip to the content of the web site.

Hexadecimal numbers

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

Applying this to memory

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.

Bytes

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