ZX 81 - BASIC Programming

Sinclair ZX Spectrum
Chapter 14.1 - Subroutines
Sometimes different parts of your program will have rather similar jobs to do, & you will find yourself typing the same lines in twice or more; however this is not necessary. You can type the lines in once, in the form known as a subroutine, & then use, or call, them anywhere else in the program without having to type them in again.

To do this, you use the statements GOSUB (GO to SUBroutine) & RETURN.

GOSUB n

where n is the line number of the first line in the subroutine, is just like GOTO n except that the computer remembers the line number of the GOSUB statement so that it can come back again after doing the subroutine. It does this remembering by putting the line number (the return address) on top of a pile of them (the GOSUB stack).

RETURN

takes the top line number off the GOSUB stack, & goes to the line after it.

As a first example,

10 PRINT "THIS IS THE MAIN PROGRAM",

20 GOSUB 1000

30 PRINT "AND AGAIN";

40 GOSUB 1000

50 PRINT "AND THAT IS ALL."

60 STOP

1000 REM SUBROUTINE STARTS HERE

1010 PRINT "THIS IS THE SUBROUTINE,"

1020 RETURN

The STOP statement in line 60 is very important because otherwise the program will run on into the subroutine & cause error 7 when the RETURN statement is reached.

For a less trivial example, suppose you want to write a computer program to handle pounds, shillings and pence. Those with long memories will remember that before 1971 a pound was divided into twenty shillings - so a shilling is 5p - & a shilling was subdivided into twelve old pence; d was the abbreviation for an old penny.) You will have three variables L, S & D (any maybe others - L1, S1, D1 & so on), and arithmetic is dead easy. First you do it separately on the pounds, shillings and pence - for instance, to add two sums of money, you add the pence, add the shillings and add the pounds; to double a sum of money you double the pence, double the shillings and double the pounds; and so on. When all that is done, adjust it to the correct form so that the pence are between 0 & 11, and the shillings between 0 & 19. This last stage is common to all the operations, so we can make it into a subroutine.

Laying aside the notion of subroutines for a moment, it is worth your while trying to write the program yourself. Give the arbitrary numbers L, S & D, how do you convert them into proper pounds, shillings & pence? Part of the problem is that you will start thinking of odder & odder cases.

What first springs to mind will probably be something like 1..25s..17d, which you want to convert to 2..6s..5d. Not so difficult. But suppose you have negative numbers? A debt of 1..25s..17d, or -1..-25s..-17d, might well turn out as - 3..13s..7d, which is rather an odd way of expressing it (as though people only ever lend each other whole pounds). And what about fractions? If you divide 1..25s..17d by two, you get 5..12.5s..8.5d, & although this has the pence, 8.5, between 0 & 11; the shillings, 12.5, between 0 & 19, it is certainly not as good as 1..3s..2.5d. Try & work out your own answers to all this - & use them in a computer program - before you read any further.

Here is one solution.

1000 REM SUBROUTINE TO ADJUST L.S.D. TO THE NORMAL FORM FOR POUNDS, SHILLINGS AND PENCE

1010 LET D=240*L+12*S+D

1020 REM NOW EVERYTHING IS IN PENCE

1030 LET E=SGN D

1040 LET D=ABS D

1050 REM WE WORK WITH D POSITIVE, HOLDING ITS SIGN IN E

1060 LET S=INT (D/12)

1070 LET D=(D-12*S)*E

1080 LET L=INT (S/20)*E

1090 LET S=S*E-20*L

1100 RETURN

On its own, this is not much use because there is no program to set up L, S & d beforehand, nor to do anything with them afterwards. Type in the main program, & also another subroutine to print out L, S & D.

10 INPUT L

20 INPUT S

30 INPUT D

40 GOSUB 2000

45 REM PRINT THE VALUES

50 PRINT

60 PRINT " = ";

70 GOSUB 1000

75 REM THE ADJUSTMENT

80 GOSUB 2000

85 REM PRINT THE VALUES

90 PRINT

100 GOTO 10

2000 REM SUBROUTINE TO PRINT L,S AND D

2010 PRINT "£";L;"..";S;"S..";D;"D";

2020 RETURN

(Recall from chapter 9 that the empty PRINT statement in line 50 prints a black line.)

Clearly we have saved on program by using the printing subroutine at 2000, & this in itself is a very common use for subroutines: to shorten programs. However, the adjustment subroutine in fact makes the program longer - by a GOSUB & a RETURN; so program length is not the only consideration. Used with skill, subroutines can make programs easier to understand for the ones that matter, humans.

The main program is simplified by its using more powerful statements: each GOSUB represents some complicated BASIC, but you can forget that - only the net result matters. Because of this, it is much easier to grasp the main structure of the program.

The subroutines, on the other hand, are simplified for a very different reason, namely that they are shorter. They still use the same old plodding LET & PRINT statements, but they only have to do a part of the whole job & so are easier to write.

The skill lies in choosing the level - or levels - at which to write the subroutines. They must be big enough to have a significant impact on the main program, yet small enough to be significantly easier to write than a complete program without subroutines. These examples (not recommended) illustrate this.

First,

10 GOSUB 1000

20 GOTO 10

1000 INPUT L

1010 INPUT S

1020 INPUT D

1030 PRINT " ";L;"..";S;"S..";D;"D";TAB 8;"=";

1040 LET D=240*L+12*S+D

          :      :

          :      :

2000 RETURN

& second

10 GOSUB 1010

20 GOSUB 1020

30 GOSUB 1030

40 GOSUB 1040

50 GOSUB 1050

          :      :

          :      :

30 GOTO 10

1010 INPUT L

1015 RETURN

1020 INPUT S

1025 RETURN

1030 INPUT D

1035 RETURN

1040 PRINT " ";L;"..";S;"S..";D;"D";TAB 8; "=";

1045 RETURN

1050 LET D=240*L+12*S+D

1055 RETURN

          :      :

          :      :

The first, with its single powerful subroutine, & the second, with its many trivial ones, demonstrate quite opposite extremes, but with equal futility.

A subroutine can happily call another, or even itself (a subroutine that calls itself is recursive), so don't be afraid to having several layers.

Summary

Statements: GOSUB, RETURN

Sinclair ZX Spectrum

  Previous Page Back Next Page