Books Issue 8 Contents Mind Games

helpline




Andrew Hewson

Spanners poked in the Sinclair works

THIS MONTH I answer some problems concerning PEEKing and POKEing. David Anthes writes: My ZX-81 has a bug. When I POKE 57 into various addresses as per page 163 of the manual, I get weird effects. Sometimes the machine crashes but Sinclair claims there is nothing wrong with it.

When you enter PRINT PEEK address, your computer PRINTs a positive integer number between 0 and 255 inclusive. That is the number which your machine holds in the byte at location "address". The value of "address" must be a positive integer between 0 and 32767 on the 16K ZX-81 or Spectrum.

POKE is the complementary command to PEEK. It puts a number into a location. The form of the command is:

POKE address, number

where address is a positive integer in the range 0 to 32767 - 16K machines - and number is a positive integer in the range 0 to 255. It is a dangerous command, because POKEing the wrong location can cause the machine to crash for any one of a hundred reasons. PEEKing is a means of looking at what your computer is doing, whereas POKEing is a way of putting a spanner in the works; if you put the spanner in the wrong place or the wrong spanner in the right place you can cause havoc.

John Hawes wants to PEEK the ZX-81 display file. He asks: Is it possible to discover whether a given character is at a given position in the display of the 16K ZX-81?

There are two golden rules to remember when manipulating the ZX-81 display. They are:

The ZX-81 display file must always contain at least 25 bytes filled with the NEWLINE character, decimal 118.

The 1K ZX-81 display file contains only the characters which have been PRINTed or PLOTted, plus sufficient spaces to fill any gap between the left-hand side of the screen and the character in question. The 16K ZX-81 display file contains 25 lines of 32 characters unless SCROLL has been used since the last CLS. The following routine PRINTS the character at row R, column C of the 16K ZX-81 display file:

 10 FOR I=0 TO 5
 20 PRINT "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 30 NEXT I
100 LET D=PEEK 16396+256*PEEK 16397
110 INPUT R
120 INPUT C
130 PRINT AT 21,0;CHR$ PEEK (D+33*R+C)

Steve Packman has a Spectrum and he writes: A subroutine returns to the line following the line from which it was called. I want to write a program in which the line number to which the return is made depends on the results of calculations within the subroutine. How can this be done?

The simple solution to his problem is not to use a GO SUB statement but to use GO TO instead. The subroutine can then perform its calculations and return to the appropriate line in the main program by means of a second GO TO statement.

If it is essential to the logic of the program to use a GO SUB statement, then care must be taken to ensure that the program also executes a RETURN statement subsequently. The reason is that the GO SUB statement saves the number of the line in which it occurs at the bottom of the GO SUB stack, which lies immediately below RAMTOP. The RETURN statement deletes the stack entry and causes the program to jump to the line number following the GO SUB line. Therefore if the program executes more GO SUBs than RETURNS, the line numbers accumulate at the bottom of the GO SUB stack, causing it to grow downwards and eventually fill all the spare space in RAM.

When the 16K Spectrum is switched on, RAMTOP is set at 32599. Owners of the 48K Spectrum should enter CLEAR 32599 to simulate a 16K machine. The following routine looks at the 10 bytes immediately below RAMTOP:

9000 FOR T= 32599 to 32590 STEP -1
9010 PRINT i, PEEK i
9020 NEXT i

The resulting display is:

32599 62
32598 ?
32597 19
32596 3
32595 27
32594 118
32593 31
32592 219
32591 31
32590 237

Address 32599 always contains 62 and the contents of 32598 depend on previous calculations made by the Spectrum. Locations 32597 downwards form the machine stack and need not concern us. One or more addresses can be put on the GO SUB stack using the following routine.

 10 INPUT j
 20 FOR T=1 TO j
 30 GO SUB 100
 40 NEXT i
 50 GO TO 9000
100 GO TO 40

Add that routine to the previous one, RUN it and enter, say, 2 for the value of j. The resulting display is:

32599 62
32598 ?
32597 2
32596 0
32595 30
32594 2
32593 0
32592 30
32591 19
32590 3

The contents of 32597 downwards have been displaced downwards by six locations. For example, 32591 now contains the value of 19, as 32597 did previously. The contents of 32597 and 32594 each show that the next two lower bytes i.e., 32596 and 32595; 32593 and 32592 respectively contain a two-byte GO SUB address. The GO SUB instruction is on line 30, so it is no surprise to see that

PEEK 32595+256*PEEK 32596=30

It can be seen that to change the RETURN address of a subroutine it is necessary to POKE new values into the appropriate pair of bytes at the top of RAM. The following program calls the subroutine from line 20 but RETURNS directly to line 100 as dictated by the value of the variable "return":

  10 LET return=99
  20 GO SUB 2000
  30 PRINT "LINE 30": STOP
  99 REM
 100 PRINT "LINE 100":STOP
2000 LET r=PEEK 23730+256*PEEK 23732-2
2010 IF PEEK r=2 THEN LET r=r-3: GO TO 2010
2020 POKE r+1,return-256*INT (return/256)
2030 POKE r+2,INT(return/256)
2040 RETURN

Note that line 99 must exist, or the Spectrum stops with the error message N "statement lost". Thus the problem can be solved by adding lines 2000 2040 to the end of the subroutine and setting the variable "return" appropriately.

Finally, I have to thank several people, including Ettrick Thompson, for pointing out an error in the column in September. I claimed that -3↑2 = 9 but I was incorrect. Page 201 of ZX Spectrum Basic Programming explains that the Spectrum assigns a priority of 10 to the task of raising a number to a power and a priority of 9 to changing the sign of number.

The parts of an arithmetic expression are evaluated in order of priority; therefore 3↑2 is evaluated before negation takes place. In other words -3↑2 is evaluated as if it were written as -(3↑2), hence the Spectrum is correct and I was not.



Books Issue 8 Contents Mind Games

Sinclair User
November 1982