Program listings on the ZX/TS computers are available on command. With either LIST or LLIST, the program in the machine is displayed for you to study or change. But not everything in the program file is displayed! Three elements are censored from the Listings you see.
But ignorance is bliss, you may say. To an extent you would be right. For most programming chores, understanding the structure of the ZX/TS program file is unnecessary. There are times, however, when you may want to work with the program file itself, e.g., when renumbering lines or trying to save space, and, at these times, knowledge of the structure is important.
Computer Structure
This paper is a tool for holding information. The shapes written on it (letters) mean different things as they are combined (words and sentences). The computer is also a tool for holding information, but it is built in a different way. There are two main differences: 1) it holds binary numbers only, and 2) it is linear, like a string of beads, rather than two dimensional as this paper is. For the convenience of the human users, both of these attributes have been “covered up.” You can communicate with the machine using letters and decimal numbers, and receive its replies in the same way, but the machine is doing a lot of extra work to accommodate you. When we look at the structure of the computer, though, we must keep those differences in mind.
Mechanics
The computer stores numbers in a long string. Each number, in reality, is a collection of 32 transistors, formed into eight switches, or bits. These eight bits together are called a byte. As it happens, eight switches can be arranged in 256 different ways, from 00000000, 00000001, 00000010,… to 11111111. We can think of each arrangement as a number, between 0 and 255. Each of these eight bit numbers has a fixed position in the string of numbers; these positions are called addresses. Not all addresses have switches presently attached—it is a little like a new Levittown, with empty streets stretching off into the distance. In the basic TS1000, only the addresses from 0 to 8192, and from 16384 to 18432 are used, while the machine could work with addresses up to 65536!
The Program
Type in the program in Listing 1. It will be stored between 16509 and 16607. You may want to change LPRINT to PRINT after you have RUN it once.
Listing 1.
10 REM SAMPLE PROGRAM, NO. 1
20 FOR N=16509 TO 16608
30 SCROLL
40 LPRINT N;" ";PEEK N;TAB 10;CHR$ PEEK N
50 NEXT N
Otherwise, type it in exactly as written—the success of your future POKEs depends on it.
This program uses two features of Basic to help us examine the machine’s memory: PEEK and CHR$. PEEK, followed by an address, will give us the decimal value of the number at that address. The machine can interpret that number in several ways—(as text, as a binary number, or as machine code). We can use CHR$ to command the machine to translate the number into text. POKE, the companion command to PEEK, lets us change the value stored in RAM.
Tokens
RUN the program and look carefully at the results. “Wait!” you say, “each address is supposed to hold one number, and some seem to hold whole words.” You are seeing tokens. When the machine translates its memory into text, some numbers are assigned whole words, rather than individual characters. A list of all the tokens is in the character list in your User’s Manual.
The Powerful 118
The next thing you notice is that the nice, neat program lines are gone; the numbers run along without an apparent break. However, two kinds of breaks are there. Note how each line of the program has a 118 to conclude it (each line of the screen display has one also, but that is a subject for another time). When the LIST routine is drawing the program to the screen, it uses the 118 markers to signal the end of a line.
We can have some fun with that. Type in POKE 16520,118 and ENTER. The LIST routine now thinks that the REM is in two parts! The program will still run; the machine uses a different method of keeping things straight as it RUNs.
Now try POKE 16521,118 and ENTER. List the program. Where did it go? It is still there; try RUN to prove it. The LIST routine interprets two 118’s together as the end of the program file. If you want to see the rest of the program again, POKE 16520,0 and 16521,0
The Silent 126
The machine has another flag hidden in the listing. RUN the program again, and watch the LISTing of line 28 (addresses 16536 to 16566). The number 16509 appears, starting at 16543. You see the character codes for 1, 6, 5, 0, and 9, but there are six bytes of garbage before you get to the “TO.” The 126 tells the computer that a five byte binary number follows. This number is inserted after each decimal number you include in your program line, as the line is copied from the bottom of the screen into the program area. When you press EDIT, these numbers are stripped out.
Figure 1. 16509 0 16534 29 1 16559 36 8 16584 211 PEEK 16510 10 ▒ 16535 118 ? 16560 126 ? 16585 51 N 16511 23 * 16536 0 16561 143 ▒ 16586 25 ; 16512 0 16537 20 = 16562 1 16587 194 TAB 16513 234 REM 16538 27 . 16563 192 " 16588 29 1 16514 56 S 16539 0 16564 0 16589 28 0 16515 38 A 16540 235 FOR 16565 0 16590 126 ? 16516 50 M 16541 51 N 16566 118 ? 16591 132 ▒ 16517 53 P 16542 20 = 16567 0 16592 32 4 16518 49 L 16543 29 1 16568 30 2 16593 0 16519 42 E 16544 34 6 16569 2 ▒ 16594 0 16520 0 16545 33 5 16570 0 16595 0 16521 53 P 16546 28 0 16571 231 SCROLL 16596 25 ; 16522 55 R 16547 37 9 16572 118 ? 16597 214 CHR$ 16523 52 O 16548 126 ? 16573 0 16598 211 PEEK 16524 44 G 16549 143 ▒ 16574 40 C 16599 51 N 16525 55 R 16550 0 16575 24 / 16600 118 ? 16526 38 A 16551 250 IF 16576 0 16601 0 16527 50 M 16552 0 16577 225 LPRINT 16602 50 M 16528 26 , 16553 0 16578 51 N 16603 3 ▒ 16529 0 16554 223 TO 16579 25 ; 16604 0 16530 51 N 16555 29 1 16580 11 " 16605 243 NEXT 16531 52 O 16556 34 6 16581 0 16606 51 N 16532 27 . 16557 34 6 16582 11 " 16607 118 ? 16533 0 16558 28 0 16583 25 ; 16608 118 ?
Try POKE 16520,126. LIST now thinks that the letters “PROGR” are a binary number and hides them from you. They are still there; RUN the program again to prove it. Now LIST it again and pull line 10 down with EDIT. It looks the same as in the listing, but “PROGR” is now deleted. Press ENTER to replace it, and RUN to prove it.
This will happen to machine code if it happens to contain a 126 (which, unfortunately, is a very important command) and is pulled down with EDIT.
Try POKE 16548,0 and LIST. This will remove the 126 from behind the decimal number 16509, and LIST will provide the CHR$ for the five following bytes, rather than skipping them as it normally does. Sometimes, a bad load will change 126 to something else, and the program will not operate correctly. The symptom, of course, is six characters of garbage following a good number in the LISTing. If you like, you can add a program such in Listing 1. Identify the address of the missing 126, and replace it with a POKE.
More Anatomy Line Numbers . . .
There are two more “structures” that help the machine navigate through the program file. The first is the line number. This is stored in an almost logical way. Remember that the largest number that an address can hold is 255. How would it hold a line number larger than that? Let’s see.
EDIT line 50, change its line number to 300, and RUN. The line number for that line is held at addresses 16601 and 16602. The computer has taken the line number 300, seen how many 256’s would go in it (one), and put the remainder in the next address. Try POKEing 16601,10 and LIST. The first number now represents 2560, and the remainder from before is added in, making 2604.
And Line Length
There are two more bytes to account for. These are extremely important for the machine, as they tell the computer how long the present line is, and thus, how many addresses to move to get to the next line,
RUN, and look at line 10. Address 16511 holds 23. Now starting at the first byte of the text of the line (16513), count down 23. You find the 118 at the end! Many computers only allow lines of less than 256 characters (can you guess why?), but the ZX/TS machines support lines of essentially any length. If the length is greater than 255, the same operation as the line number is performed, with one byte getting the number of 256’s in the length, and the other getting the remainder. There is one catch though: the two bytes are in reverse order, to speed the handling of the numbers by the Z80.
If You Have a 2068
The 2068 is organized in a similar way to the 1000 and the 1500, however, it was designed to provide a wider variety of abilities. Therefore its overall organization is much more complex. The organization of the program file, though, is very similar. The changes are:
1) The program file no longer starts at 16509, or any fixed address for that matter. Finding the program is simple, however, as the address where it starts is stored at a fixed address. The starting address of the program can be found by using
PEEK 23635+256*PEEK 23636
2) The character codes have been changed to conform to the codes used by other computers (ASCII code). This is not too criticial—CHR$ will still give you the meaning of the given addresses—but the 1000’s end line and number markers (118 and 126) had to be changed. The new end line marker is 13, and the new number flag is 14.
3) ASCII codes below 32 are not printable. Like the end line (also called line feed or newline) or number marker, the other numbers below 32 generally give the machine instructions and will affect only how you see the characters that follow if you attempt to print them.
We can still look into the anatomy of the 2068’s program lines, though. The program in Listing 2 will do it.
Listing 2.
10 REM 2068 anatomy
20 FOR x=PEEK 23635+256*PEEK 23636 TO PEEK 23627+256*PEEK 23628
30 PRINT x;" ";PEEK x,: IF PEEK x>31 THEN PRINT CHR$ PEEK x;
40 PRINT
50 NEXT x
Run it, and now go back to the TOKENS section, and follow the exploration of your machine. You will have to substitute 13 for 118, and 14 for 126 as you go along. Try hitting inverse video somewhere in the listing, and look for where it appears in the program printout.
Now you have seen part of the machine’s structure that was hidden before. Like a sleek car, it sometimes pays to lift the hood and appreciate the effort that went into the works under there as well.
Figure 2.
26710 0 26782 0
26711 10 26783 43 +
26712 14 26784 50 2
26713 0 26785 53 5
26714 234 REM 26786 54 6
26715 50 2 26787 14
26716 48 0 26788 0
26717 54 6 26789 0
26718 56 8 26790 0
26719 32 26791 1
26720 97 a 26792 0
26721 110 n 26793 42 *
26722 97 a 26794 190 PEEK
26723 116 t 26795 50 2
26724 111 o 26796 51 3
26725 109 m 26797 54 6
26726 121 y 26798 50 2
26727 13 26799 56 8
26728 0 26800 14
26729 20 26801 0
26730 75 K 26802 0
26731 0 26803 76 L
26732 235 FOR 26804 92
26733 120 x 26805 0
26734 61 = 26806 13
26735 190 PEEK 26807 0
26736 50 2 26808 30
26737 51 3 26809 30
26738 54 6 26810 0
26739 51 3 26811 245 PRINT
26740 53 5 26812 120 x
26741 14 26813 59 ;
26742 0 26814 34 "
26743 0 26815 32
26744 83 S 26816 34 "
26745 92 26817 59 ;
26746 0 26818 190 PEEK
26747 43 + 26819 120 x
26748 50 2 26820 44 ,
26749 53 5 26821 58 :
26750 54 6 26822 250 IF
26751 14 26823 190 PEEK
26752 0 26824 120 x
26753 0 26825 62 >
26754 0 26826 51 3
26755 1 26827 49 1
26756 0 26828 14
26757 42 * 26829 0
26758 190 PEEK 26830 0
26759 50 2 26831 31
26760 51 3 26832 0
26761 54 6 26833 0
26762 51 3 26834 203 THEN
26763 54 6 26835 245 PRINT
26764 14 26836 194 CHR$
26765 0 26837 190 PEEK
26766 0 26838 120 x
26767 84 T 26839 59 ;
26768 92 26840 13
26769 0 26841 0
26770 204 TO 26842 40 (
26771 190 PEEK 26843 2
26772 50 2 26844 0
26773 51 3 26845 245 PRINT
26774 54 6 26846 13
26775 50 2 26847 0
26776 55 7 26848 50 2
26777 14 26849 3
26778 0 26850 0
26779 0 26851 243 NEXT
26780 75 K 26852 120 x
26781 92 26853 13
26854 248 SAVE