Home

Z80  Info  V

Number System Representations

Base 10
The Z80 address space is limited to 16-bits which numerically is 2 to the power of 16, or 65536 locations. Using our familiar decimal number system, the first location is 0 and the last is 65535.

In base 10, the decimal number system, we run numbers 0 to 9 in the ones column and then 0 to 9 in the tens column. Next is 0 to 9 in the hundreds column, and this goes on indefinitely to the left.
The decimal system is based on having either 10 toes or 10 fingers, whichever is easier for you to count.

We count our physical digits as 1 to 10. If we were to use 0 as a placeholder, then counting from 0 to 9 gives us 10 possibilities or permutations for numbers. It's those permutations that are responsible for the base 10 or decimal system.

Starting from the right, the decimal number 123 is composed of:
3 x 1 = 3
2 x 10 = 20
1 x 100 = 100

The total of 3 + 20 + 100 is simply 123.

If we were to count towards decimal 123, we would start with zeros in all the columns and increment by 1. When we used up all the numbers in the right-most column, we would place a 0 in it and advance the next column by 1. This is a system you know well. We're reviewing it because the concept is the same with hexadecimal but there are new players.

Hundreds Tens Ones   Decimal
0 0 0 000
0 0 1 001
0 0 2 002
. . . .
0 0 8 008
0 0 9 009
0 1 0 010
0 1 1 011
0 1 2 012
. . . .
0 1 8 018
0 1 9 019
0 2 0 020
. . . .
. . . .
0 9 8 098
0 9 9 099
1 0 0 100
1 0 1 101
. . . .

Short Decimal counting video

Base 2
Consider if we were all born with only one finger or thumb on each hand, then we might have embraced the binary number system that has only two numbers - 1 and 2.

With two permutations, we would need numbers 0 and 1. 0 is the first placeholder and 1 is the second placeholder in the ones column. Yes, a ones column just like the decimal system.
If we want to increase the count like we do with decimal, then we need to move the numbers to the left.
If the first column has a max value of 1 then we need to move one column to the left to increase its value.
2 comes after 1 so we'll make the next column the twos column. Its count runs from 2 to 3 (remember binary columns only have 2 places) and then we need to start a new column - fours.
As you make your way through the counting list below you can see there are numerous permutations of zeros and ones as we count higher. In order to fill all those permutations, we need a new "number" to represent the sum of the bits on any line greater than 9. That is why you see the question marks below.

Video: Counting from 1 to 15 in binary

 

Base 16
With the alphabet being as familiar to us as numbers, the hexadecimal value that occurs after 9 is A or 10 in decimal. The most common representation for A to quickly know it's hexadecimal is to use 0x0A with the 0x meaning hex.

You will see numerous ways of representing hex such as "0x" or "$" or "h". Some Z80 assemblers that take your assembly language and convert it to machine language are particular and can become confused by mistaking your hex designator for an assembly label, example "FECh". So when in doubt, use "$". Do yourself a favour now and get in the habit of never leaving off the number system designator when you code.

 

Binary
Eights Fours Twos Ones   Hexadecimal Decimal
0 0 0 0 00 0
0 0 0 1 01 1
0 0 1 0 02 2
0 0 1 1 03 3
0 1 0 0 04 4
0 1 0 1 05 5
0 1 1 0 06 6
0 1 1 1 07 7
1 0 0 0 08 8
1 0 0 1 09 9
1 0 1 0 ? 10
1 0 1 1 ? 11
1 1 0 0 ? 12
1 1 0 1 ? 13
1 1 1 0 ? 14
1 1 1 1 ? 15



So now we can replace the question marks with A, B, C, D, E, and F. The smallest binary number is 0000 and the largest binary number is 1111. We can represent binary 0000 in hex with 0 and we can represent binary 1111 with F.  BTW, when you're only dealing with 4 bits, it's called a nibble.
The Z80 uses an 8-bit data bus so bus-wise only 8-bits can be moved at a time. We've shown 4 bits above, let's flesh out our table to 8 bits.

 

Binary
128 64 32 16   8 4 2 1   Hex Dec
0 0 0 0   0 0 0 0 00 0
0 0 0 0   0 0 0 1 01 1
0 0 0 0   0 0 1 0 02 2
. . . .   . . . . . .
0 0 0 0   0 1 1 1 07 7
0 0 0 0   1 0 0 0 08 8
0 0 0 0   1 0 0 1 09 9
0 0 0 0   1 0 1 0 0A 10
0 0 0 0   1 0 1 1 0B 11
0 0 0 0   1 1 0 0 0C 12
0 0 0 0   1 1 0 1 0D 13
0 0 0 0   1 1 1 0 0E 14
0 0 0 0   1 1 1 1 0F 15
0 0 0 1   0 0 0 0 10 16
0 0 0 1   0 0 0 1 11 17
0 0 0 1   0 0 1 0 12 18
. . . .   . . . . . .
0 0 0 1   1 1 1 1 1F 31
0 0 1 0   0 0 0 0 20 32
0 0 1 0   0 0 0 1 21 33
. . . .   . . . . . .
0 1 1 1   1 1 1 1 7F 127
1 0 0 0   0 0 0 0 80 128
1 0 0 0   0 0 0 1 81 129
. . . .   . . . . . .
1 1 1 1   1 1 1 0 FE 254
1 1 1 1   1 1 1 1 FF 255

Video: Binary counting: (skip ahead 23 seconds)


So, the first decimal value is represented as 000 or 0 for short, and the first hexadecimal value is represented as 0x00.
The last decimal value is 255 and the last hex value is 0xFF.

BTW, when you're dealing with 8 bits, it's called a byte and is composed of two nibbles. That brings us to an important question: is there an easier way to convert the 8 bits to a byte? Yes, weigh each nibble separately as if they started with binary 0000 and ended with binary 1111.

You can see some examples in the table below.

 

8 4 2 1   8 4 2 1   Hex
0 0 0 0   0 0 0 0 00
. . . .   . . . . .
0 1 1 1   1 0 0 0 78
. . . .   . . . . .
1 1 0 0   1 0 1 1 CB
. . . .   . . . . .
1 1 1 1   1 1 1 1 FF

We could refer to the first table entry as "zero zero hex" and the last table entry as "fox fox hex".

How are the hex values used?

If you see the hex value 0xFF, it's probably a data value.
If you see the hex value 0xFFFF, it's probably an address value.

Here's a couple of examples with binary. Like the table above, we stuck some spaces in between each of the 4 nibbles to make them easier to read:

8 4 2 1   8 4 2 1   8 4 2 1   8 4 2 1  
32k 16k 8k 4k   2k 1k 512 256   128 64 32 16   8 4 2 1 Hex Dec
0 0 0 0   0 0 0 0   0 0 0 0   0 0 0 0 0x0000 0
1 1 1 1   1 1 1 1   1 1 1 1   1 1 1 1 0xFFFF 65535

Nomenclature
BTW, when you're dealing with 16 bits it's usually called a word or 16-bit word.

Ok, so we made it through understanding the basics of decimal, binary and hexadecimal (hex) representation.

Z80 registers are 8 bits wide holding values from 0x00 to 0xFF. When combined together in pairs, they can hold values from 0x0000 to 0xFFFF by concatenation.  However, many operations can only act on 8 bits at a time

Register pairs for this purpose are BC, DE, and HL (high low). There is also the most important register but it likes to solo when it comes to data - Register A which is also known as the Accumulator.
It is paired but with the Flags register, hence the register name AF. Flags include Zero, Carry, Half-Carry, etc. More on them later.
 

Writing and Reading
Reading Z80 assembly code is easier when performed right to left. For instance, to place 5 in the accumulator/register A, we would type the following:
LD A, 5

When we read it out loud, the instruction on the left is said first, followed by the operands starting from the right. Weird but true.
It reads "Load 5 into register A"

There are restrictions of course on how data is loaded. If you want to put an ASCII character like "M" into the A register, you would use LD A, "M"
If you wanted to put the  hex number "F" you would use "LD A, Fh" or "LD A, $F". Note that some assemblers are fussy and want you to precede any hex value that uses A through F with a zero first. An example would be "LD A, 0Fh" or "LD A, $0F". If you stick to the hex designator "$", you usually won't have that problem.
 

 

TOP

 

Home