Skip to content

Four Bits at a Time

Hex gives each half of a byte a single symbol, so the writing still shows you the switches.

  • Foundations

11110000 in binary is F0 in hexadecimal. Both mean 240. Hex gives each group of four bits one digit, making a long row of switches easier to read.

A bit is one binary digit: 0 or 1, like a switch that is off or on. A byte is eight bits. In binary, the positions count 1, 2, 4, 8 and so on from right to left; add the values of the positions containing a 1 to get the number.

11111111 — quick, how many ones? You had to count. Binary tells the whole truth, but eight switches is more than you can take in at a glance, and programmers look at these all day. They wanted a shorthand that still showed the bits. That shorthand is hexadecimal.

Decimal hides the bits

Why not read the byte in ordinary tens? Because decimal does not line up with switches.

11111111 is 255. The decimal number does not directly show which switches are on. Turn off the rightmost bit, worth 1, and you get 11111110, or 254. The decimal barely moves, while the bit pattern changed in a clear, specific place.

We want a shorthand where the writing still shows the switches. Grouping the bits in fours gives us one.

Group the bits in fours

Split a byte down the middle into two halves of four bits. Four bits has its own name. It is a nibble, which is half a byte.

How high does one nibble count? Turn all four on:

The examples use pseudocode to show the calculation, not commands to type into a Spectrum. SHOW displays a value, and BIN says the following digits are binary.

Code
SHOW BIN 1111
Output
15

A nibble runs 0 to 15, which is sixteen values. That is the whole idea of hex: give each nibble a single symbol, so four bits become one character.

Sixteen needs sixteen symbols

Here is the snag. We have ten digits, 0 to 9. Sixteen values need sixteen symbols, so hex borrows the first six letters for the values past nine. A is ten, B is eleven, and so on up to F for fifteen.

Bits Decimal Hex
0000 0 0
0101 5 5
1001 9 9
1010 10 A
1100 12 C
1111 15 F

So A to F are not letters here. They are digits, the ones we ran out of symbols for. F means a full nibble, all four on.

Group a shorter pattern

For a shorter pattern, start grouping from the right. BIN 101101 becomes 0010 1101 when we add leading zeros on the left. Those groups are 2 and D, so the result is HEX 2D, or 2 × 16 + 13 = 45. It is the same pattern we built from 32 + 8 + 4 + 1.

Padding on the right would change the number: 10110100 is 180, not 45. Leading zeros preserve a value; extra zeros on the right move its place values.

A byte is two hex digits

Two nibbles make a byte, so we can write any byte using two hex digits. Keep a leading zero when needed: five becomes 05. In our pseudocode, HEX marks a hexadecimal value, just as BIN marks a binary one:

Code
SHOW BIN 11111111
SHOW HEX FF
Output
255
255

Both lines came to the same number, because they are the same number written two ways. F on the left is the high nibble, worth fifteen sixteens. F on the right is the low nibble, worth fifteen ones: 15 × 16 + 15 = 255.

Now watch what hex shows that decimal hid. Turn the low nibble off and leave the high one on:

Code
SHOW BIN 11110000
SHOW HEX F0
Output
240
240
Read the eight bits from left to right, from position 7 to position 0. The high nibble, 1111, becomes F (fifteen); the low nibble, 0000, becomes 0. The left hex digit counts in sixteens, so F0 is 15 × 16 + 0 = 240.

In decimal, 255 became 240. That jump hides what happened. In hex it went FF to F0, and the change is right there in the second digit. The low nibble emptied.

That is hex’s whole appeal. Each digit is one nibble, so you read the bits straight off.

When a digit runs out

Ordinary counting in hex carries into the next place:

Code
SHOW HEX 0F + 1
SHOW HEX FF + 1
Output
16
256

Those results are HEX 10 and HEX 100. The first fits in two hex digits; the second needs three. A chosen unsigned byte still holds only 00 through FF. This is a calculation with numbers, not a promise that an eight-bit storage operation keeps all the digits. A target lesson must state its range rule.

Do HEX 10 and decimal 10 mean the same value? Which fits in an unsigned byte: HEX FF or HEX 100?

HEX 10 means 16, while decimal 10 means ten. HEX FF is 255 and fits; HEX 100 is 256 and does not. Writing HEX 0100 adds a leading zero but leaves that value at 256. The base and the chosen width answer different questions.

Why programmers reach for it

  • It lines up with bits. One hex digit is exactly four switches.
  • It is short. A byte is two characters instead of eight.
  • It is common. Memory addresses, colour values and the bytes of machine code are often written in hex, because hex shows the bits.

Not every language writes it the way we have. Most use a marker in front of the digits instead of a word, and $F0 and 0xF0 are the two you will meet most.

When it’s wrong, see why

  • A hex digit above F. There is not one. Hex runs 0–9 then A–F and stops. A “G” is not a hex digit.
  • Reading hex 10 as ten. It is 1 × 16 + 0 = sixteen. In a two-digit hex number, the left digit counts in sixteens. That is exactly why the base gets marked, by a word like HEX or a sign like $.
  • Mixing up the halves. The left hex digit is the high nibble, the right is the low one. The left digit counts in sixteens; the right counts in ones.

What you’ve learnt

  • Hex is base sixteen: one symbol per nibble, so four bits become one character.
  • Counting runs 0–9 then A–F, and the letters are the digits past nine.
  • We can write a byte in two hex digits, 00 to FF. FF is 255, with all eight bits on.
  • Hex earns its keep because it shows the bits where decimal hides them.

See the pattern do a job

A byte becomes pixels shows a complete Spectrum program that uses one bit per pixel. Its % marks binary and its $ marks hex; read the local explanation without learning assembly first. Running or changing that program is optional.

For a numerical use of the same bits, Two bytes together builds a larger unsigned value and separates an address range from installed memory.

What’s next

A byte runs out at 255, and a game needs bigger numbers than that before the first level is over. In Unit 3 we put two bytes side by side, and hex turns out to have been ready for it.