Chapter 3BASIC: A Very Kind Lie

Switch on a Spectrum and, after a moment, it says © 1982 Sinclair Research Ltd at the bottom of the screen and waits. There’s no menu, no desktop, nothing to click. There’s just a cursor, and the expectation that you’ll type something.

What you type is BASIC.

The conversation

BASIC was the language most home computers of the early 1980s spoke when you switched them on. The Spectrum took it further than most: the language was so much the point of the machine that the keywords were printed on the keys. Press P at the start of a line and you don’t get the letter P, you get the whole word PRINT, in one go. The manual says the keywords are “entered from the keyboard rather than being spelled out”.

So you type a line, PRINT 2+2, and the Spectrum answers 4. You type another, and it answers again. It feels like a conversation, and that feeling is BASIC’s great gift. It let millions of people tell a computer what to do without knowing anything about addresses, bytes or processors.

Look at what you didn’t have to think about, even in that one line. Where in memory the 2s were kept. How a number is stored in a row of boxes that only hold 0 to 255. Which instructions the processor needed to add them up. How the answer was turned into the shapes of a 4 on the screen. BASIC did all of that, and didn’t mention it.

That’s the kind lie. When you use BASIC, it seems as if you’re talking to the computer. You type, it understands, it does what you asked.

Who you’re really talking to

Here’s a program that fills the screen with ink, one byte at a time. It counts through every byte of the part of memory the ULA turns into dots, from address 16384 to 22527, and puts 255 in each one, which switches all eight dots on.

10 FOR n=16384 TO 22527
20 POKE n,255
30 NEXT n

Three lines, and nothing in them is hard. Run it, and it takes about 46 seconds.

A Spectrum screen with its top third solid black and its middle third filled in horizontal stripes
The screen halfway through the fill. The order it fills in is a story for chapter 6.

Forty-six seconds is a long time to switch on 49,152 dots. In chapter 4 you’ll meet the same loop written in machine code, the processor’s own language: the same steps, one byte at a time, in the same order. It finishes in less than a tenth of a second, hundreds of times faster. The processor is the same. The memory is the same. The difference is everything BASIC does that you didn’t ask for.

Divide it out, and the difference has a size. Forty-six seconds over 6,144 trips round the loop is about seven and a half thousandths of a second for each trip. The processor’s clock ticks three and a half million times a second, so each trip costs about 26,000 ticks, to put one number in one box. Chapter 4’s version does the same job in about 44. For every tick the work needs, BASIC spends nearly six hundred.

Every time round that loop, BASIC goes back to your program and reads the next statement as if it had never seen it before. It finds the word POKE and works out what it means. It finds n, and goes looking through its list of variables to find out what n holds. It checks that the address is a sensible one and that the value fits in a byte. Only then does it put 255 in the box. Then it reads NEXT and does the same kind of thing all over again, and then it goes back to POKE, which it has forgotten all about.

That’s what an interpreter is: a program that reads your program, a piece at a time, and does what it says. It never turns your program into anything faster. It just reads it again, over and over, as long as it runs.

Searching, every time

You can measure the reading. Here’s a loop that counts to 1,000 and copies its counter into another variable each time round. On its own, it takes about 6.6 seconds. This version makes twenty other variables first.

10 LET a=1: LET b=1: LET c=1: LET d=1: LET e=1
20 LET f=1: LET g=1: LET h=1: LET i=1: LET j=1
30 LET k=1: LET l=1: LET m=1: LET o=1: LET p=1
40 LET q=1: LET r=1: LET s=1: LET u=1: LET v=1
100 FOR n=1 TO 1000
110 LET t=n
120 NEXT n

The loop hasn’t changed at all, but now it takes about 12 seconds, nearly twice as long. BASIC keeps its variables in one list, in the order they were made. Every time it meets a name, it starts at the top of the list and checks each variable in turn until it finds the right one. The loop’s n and t were made last, so they’re now at the bottom of a list of twenty-two.

Lines are found the same way. When BASIC meets GO TO 3020, it doesn’t know where line 3020 is. It starts at the first line of the program and checks each line’s number until it gets there. NEXT does the same when it goes back to the top of its loop.

So where a loop sits in a program changes how fast it runs. In this program, lines 10 to 2000 are two hundred REM lines, which do nothing at all, and the listing leaves out all but the first three. After them comes a loop that jumps 500 times.

10 REM
20 REM
30 REM
3000 FOR n=1 TO 500
3010 GO TO 3020
3020 NEXT n

It takes about 17.7 seconds. Put the same loop at the start of the program, with the two hundred REM lines after it, and it takes about 3.2 seconds. It’s the same work, five and a half times faster, because each jump now finds its line at the start of the search instead of at the end.

Nothing in the language tells you this. You only find out by knowing what BASIC does with your program while it runs.

A different bargain

BASIC wasn’t the only language a home computer could greet you with. In 1982, the year of the Spectrum, a company called Jupiter Cantab sold the Jupiter Ace, which spoke Forth instead. Its manual says Forth was chosen “because of its speed, its economical use of computer memory, and the way a few simple concepts give an elegant power to the whole language”. Inside is a Z80, like the Spectrum’s, running a little slower.

Here is the counting loop from earlier in this chapter, in the Ace’s Forth.

0 variable t
: count 1001 1 do i t ! loop ;
count
The top of a Jupiter Ace screen, white text on black: 0 variable t OK, then the definition of count, OK, then count OK
The same loop on a Jupiter Ace. The Ace answers OK to each line it accepts.

The first line makes a variable, t. The second defines a new word, count, which counts from 1 to 1000 and puts each number in t. The third runs it. It takes about 0.39 seconds. The same loop in the Spectrum’s BASIC took about 6.6: seventeen times as long, on a Spectrum whose processor is, if anything, a little faster.

The difference is what each language does with your words. When the Ace meets the definition of count, it looks up each word once and stores where to find it. When count runs, it doesn’t read your text again. BASIC, as you’ve seen, reads every statement afresh each time round the loop.

Forth’s speed came at a price, and you can see it in the listing: the numbers come before the thing done to them, so 1001 1 do means “from 1 up to 1000”. The Ace’s manual starts with adding 2 and 2, which you type as 2 2 +. “FORTH always works this way round,” it says; “its rule is: first gather together the numbers you’re interested in; then do the calculations on them.” BASIC was slow because it asked so little of you. Forth was fast because it asked more.

So you were never talking to the computer. You were talking to BASIC, and BASIC was talking to the computer on your behalf, carefully, slowly, and without ever complaining.

Numbers that aren’t quite what you typed

BASIC is kind about numbers too, and a little kinder than it is honest. It lets you type any number you like, and it seems to keep it. This program is the manual’s own.

10 PRINT 1e10+1-1e10,1e10-1e10+1
20 PRINT 5e9+1-5e9
The top of a Spectrum screen showing 0 and 1 on the first line and 2 on the second
Three sums that should each come to 1.

Every one of those sums should come to 1. The first comes to 0, the second to 1, and the third to 2. The manual explains: numbers are held “to about nine and a half digits accuracy”, so ten thousand million, 1e10, can’t be held exactly, and the 1 you add to it is lost. In the last sum, the 1 is “rounded up to 2”. Add first and subtract second, and you get a different answer from subtracting first and adding second.

It isn’t a fault in the ROM. A number has to fit in a fixed number of boxes, and some numbers don’t. BASIC doesn’t mention it, and most of the time you’ll never notice. Chapter 11 opens the boxes.

Why it’s still a kind lie

None of this makes BASIC bad. The care that makes it slow is the same care that makes it forgiving.

It starts before you’ve run anything. Type a line BASIC can’t make sense of, such as PRINT 2+, with nothing after the plus, and press ENTER. BASIC won’t take it.

The bottom line of a Spectrum screen reading PRINT 2+, followed by an inverted question mark and an inverted L
A line BASIC wouldn’t take, with the flashing question mark where it stopped understanding.

It hands the line back for you to fix, with a flashing question mark at the point where it stopped understanding. Every line you type is checked the moment you press ENTER, so a mistake is caught while you can still see it, not halfway through a run. That checking is work too, done on your behalf, without being asked.

And when a running program does go wrong, BASIC stops and tells you which line, and which statement in it. Poke a value that doesn’t fit in a byte and it stops you before anything breaks. Make a mistake in machine code and the screen fills with rubbish, or goes blank, or nothing happens at all, and you have to work out why on your own.

And BASIC is quick in the way that mattered most in 1982: you could type a line, run it and see what happened, all inside a few seconds. For learning, that loop is worth far more than raw speed.

But a kind lie is still a lie, and this one has a cost you’ve now seen: about 46 seconds, against less than a tenth of one. The next part of this book is about what happens when you stop asking BASIC to pass your messages on, and speak to the processor yourself.

That’s the end of Part 1

Part 2 carries on from here, with assembly language and what the Spectrum’s screen really is, in the PDF and ebook editions.

See everything the full book covers