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.
|