A byte holds eight bits. A program can interpret those bits as a number, a pixel pattern or a character code.
When a program shows you the word SCORE, it needs an agreement about which
codes stand for those letters. The code and the shape drawn on screen are different things.
The agreement
An encoding is an agreement about how characters are represented. Here we use ASCII for the letters and digits, with each example’s code fitting in one byte. Other encodings can assign different meanings to the same bits.
Write CODE in front of one character to ask for its code in our chosen encoding:
SHOW CODE "A"65
Capital A is 65. Go the other way with CHARACTER:
SHOW CHARACTER 66B
Nothing about 65 is naturally an A. It means A under this agreement. The Spectrum uses these ASCII values for its ordinary letters and digits, but its full character set also includes its own graphics and tokens. Do not assume every machine or every part of its display uses the same table.
That is worth holding on to. A character code is a convention, not a fact about the universe.
The codes run in order
The agreement was not made at random. A is 65, B is 66, C is 67, on through the
alphabet in order.
That ordering is what lets a program sort names, or check whether a letter falls between two others under this encoding. Code order is not a promise of the alphabetical order a reader expects: case and the chosen encoding matter.
The trap: a digit is not its value
Digits have codes too, and here is where people come unstuck:
SHOW CODE "7"55
The character "7" is 55, not 7.
They are different things. The number 7 is a quantity you can add. The character "7" is a
shape on the screen that happens to look like a digit. Ask someone to type a number, treat
their answer as characters, and your sums come out as nonsense.
The ASCII digits run in order too, from "0" at 48 to "9" at 57. For one
valid digit, subtract the code of "0":
SHOW CODE "7" - CODE "0"7
Check that the input is exactly one character and its code is between the codes
for "0" and "9" before using that rule. Subtracting 48 from the code of "A"
gives 17, but that does not make A a digit.
A string such as "73" needs whole-number conversion, not just its first
character’s code. In Spectrum BASIC, CODE "73" gives 55, the code of its first
character, "7". Check what your language’s conversion function does.
Does CODE “7” give 7? Can subtracting CODE “0” turn any character into a valid digit?
CODE "7" gives 55 in our ASCII examples. Subtracting CODE "0" gives the
numeric value 7, but only after checking for one character in "0"–"9".
A non-digit or a longer string needs a different response.
ASCII upper and lower are one bit apart
Now look at what the agreement did with capitals. A is 65 and a is 97. The gap is 32.
It is the same gap for the 26 ASCII letter pairs, and 32 is not a round number by accident. Write both in binary:
SHOW BIN 1000001
SHOW BIN 110000165 97
1000001 and 1100001. Look along them. Every bit is the same except one, and 32 is the
place value of the bit that differs.
For an ASCII capital in "A"–"Z", setting this bit produces its lower-case partner:
SHOW CHARACTER (CODE "A" BITOR 32)a
BITOR 32 sets the bit. It does not toggle it: applying the same mask again
leaves the lower-case letter as it is. To convert ASCII "a"–"z" to capitals,
clear that bit with the eight-bit mask 11011111 (223).
Check the appropriate letter range first. This rule describes ASCII letters, not every encoding or every character that can appear in text.
What does BITOR 32 do to ASCII “7” and “@”? Does either result prove the input was a letter?
"7" has code 55 with that bit already set, so it stays "7". "@" has code 64,
so setting the bit gives code 96, a backtick. Neither operation turns the input
into a letter or checks whether it is one.
Meet BASIC’s stored greeting
explains strings and quoted text in a complete program. It uses PRINT rather
than our SHOW; its opening section explains how to enter it.
For a machine-specific comparison, the Vault’s PETSCII chart distinguishes the C64’s text codes from the codes written directly into screen memory. Choosing an encoding also means checking where a code will be used.
When it’s wrong, see why
- Your sums came out huge or strange. You are adding character codes rather than
numbers.
"7"is 55. - A comparison sorted oddly, with every capital before every lower-case letter. It did
exactly what you asked.
Zis 90 andais 97, so by code,Zdoes come first. - The same file looked wrong on another machine. The agreement is not universal. Check both the encoding and the table used for text or direct screen memory.
BITOR 32mangled something. Check the ASCII letter range first. Nonletters may change or stay the same; the mask does not validate them.
What you’ve learnt
- A program interprets stored bits using a character encoding.
- Which number is an agreement, commonly ASCII, and machines did not all agree.
- ASCII letters and digits occupy ordered ranges; code order depends on the encoding.
- The character
"7"is not the number 7. - Validate one digit before subtracting
CODE "0"to obtain its value. - The 26 ASCII letter pairs differ by one bit; check their range before setting or clearing it.
What’s next
Every number so far has been a whole one. In Unit 4 we handle the in-between: half a pixel, and two-thirds speed.
Sources
Sinclair Research, ZX Spectrum BASIC Programming, chapter 14, p. 91 and Appendix A, describes CODE, CHR$ and the Spectrum character table. Commodore Business Machines, Commodore 64 Programmer’s Reference Guide, Appendices B–C, pp. 376–381, separates screen display codes from text/CHR$ codes.