Programming Concepts

Author(s): Albert Rodriguez
Pub Details: Time Designs Magazine v3 n2 (Volume 3, Issue 2)
Date: January/February 1987
Pages: 36-37
Timex Sinclair 1000 computer
Timex Sinclair 1000 computer

The following article deals with programming on a Sinclair ZX81 (or TS1000). It is just a portion of a large document, with the remainder to be published in the next issue of TDM, along with a program listing. The listing is a game program, “ZX81 TIC-TAC-TOE“, which will serve as the chief example and will be discussed extensively. If readers would like to get a “head start”, a complete listing of the program, declarations and array content are available for $6.20 ppd.; or a cassette is available (non-listable) for those who don’t want to key in the program, from the author. Albert F. Rodriguez, 1605 Pennsylvania Ave. #204, Miami Beach, FL 33139. (Foreign buyers add $2 for the cassette, or $1 for the listing).

This article was meant to be an exercise in learning about the actual aspects, functions and limitations of the Sinclair ZX81 microcomputer and it’s version of the BASIC language. It also provides a tool for finding if, given the technology of this machine, quality software could be produced, and if indeed so, how would someone do it.

First of all, a word of caution to the reader about what lies ahead is in order. Some of the concepts presented in this article, which pertain to programming habits and techniques, were borrowed from works by other parties. Careful attempts in this article have been taken to clearly credit their ideas to each of them. However, the integration of these ideas into a concise whole, as well as any derivations of new ideas thereof, is only this writer, who does accept full credit and responsibility for this work.

As a novice I must say that I was oblivious to the most basic aspects of writing a program using the ZX81: Space and Time. Both of these elements are usually, but not always, directly proportional. The less available programmable memory used, the less time it should take for a program to either execute or transfer from cassette to the computer.

The load time for my program ZX81 TIC-TAC-TOE (which we will look at later on) is 4.17 minutes, without any special hardware assistance. It is saved, self-runs and executes in FAST mode. The actual RAM occupied by the program is 10535 bytes. How this figure was determined reveals a relevant proceedure about programming with this machine.

Both the ZX81 and the TS1000’s User Manual fail to discuss how a given amount of RAM programmable memory can be measured in order to determine the total amount of it available, how much is used, and how much remaining for programming.

It is well known that a byte is a memory location that, when active, is holding either blank space, numerical or alphanumerical characters. Given as an example, a machine with 16k of RAM that is turned on, and is not exhibiting a program, plus the fact that 1k is equal to 1024 bytes, we would expect that it’s total available programmable memory is (16 X 1024)…16384 bytes. Yet the display file constantly occupies 1k of memory, even when it is providing nothing but a blank screen with a cursor (for this piece of info, I am grateful to Memotech Corp., Denver, CO 80227). Hence, a blank screen actually represents 1024 bytes of memory occupied by character spaces.

If the programmable area of the screen consists of only 23 lines and 32 columns, then there are only (23 X 32) 736 programmable memory locations (i.e.; only 736 programmable bytes) available in the display file. The other (1024-736) 288 bytes in the display file are found starting with the first line after the cursor line in the work space area and consist of (288/32) 9 lines each having 32 columns. If then, we subtract 288 from 16384 we obtain the total available bytes–16096–that can be used before the machine’s entire programmable memory becomes full.

To determine the amount of programmable memory used by a program, the following expression should be placed as the last line of a program and executed with a GOTO from the immediate mode:

9999 PRINT PEEK (16404)+PEEK (16405)*256-16597;"_BYTES"

(In part, for this expression I am grateful to Ms. Toni Baker, “Mastering Machine Code On Your ZX81“, Reston Publishing Co., 1981, page 30.) The figure 16597 was determined by taking the starting address of the program area (16509) then adding to it the bytes occupied by this expression (66) and 22 more bytes occupied by another expression (described below) that reveals the amount of programmable memory remaining.

In determining how many bytes of programmable memory remains during, or after a program is being (or was) composed…the following expression should be placed as the first line of a program and executed from the immediate mode by the statement “PRINT USR 16514”:

1 REM E0RNDLN ACS : FAST AT 5 = GOSUB PI FAST AT TAN

(For this expression I am grateful to Dr. Ian Logan, “Bytes Remaining–8k”, SYNTAX, Vol.2 No.12, Dec. 1981, page 5). With this expression I obtained 5559 bytes of memory remaining after finishing my ZX81 TIC-TAC-TOE program. My memory used (10535) plus my memory remaining (5559) equals 16094. If, however, we add 2 bytes occupied by the cursor sign, then we have the exact sum (16096) of the total available programmable memory for a 16k machine that was mentioned earlier.

Another pertinent phenomenon I realized about both time and space, while writing my program, was about how the ZX81 uses it’s available memory to store and manipulate data and the effect of the same on processing time.

My primary concern while writing my program was whether I could fit it all within 16k of RAM. I strived to make my routines as concise and as frugal as possible with respect to the utilization of memory. Consequently, my programming impetus was to make a program that was primarily a space maximizer: “Do all that you have to do, with what you have, in the least amount of space that you can.”

It was the inadvertent pursuit of this maxim and the fact that I happened to be reading Chapter 3 of Mr. Randle Hurley‘s book, “The Sinclair ZX81: Programming For Real Applications” (available from Time Designs), that made me become aware of the fact that less space utilization does not always result in less processing time required for a program or routine to execute properly.

It would be redundant (and beyond the scope of this article) to reiterate the fine explanation that Mr. Hurley provides in his book, as proof, of why the ZX81 sacrifices processing time at the expense of storing and manipulating more accurate data, than say it’s forebear the ZX80. Its suffice to say that the ZX81 pays for these new capabilities in terms of more time and less speed during processing.

It should, therefore, be a priority of ZX81/TS1000 programmers, who use BASIC, to accomplish their programming objectives by using instruction-code techniques that minimize memory consumption while simultaneously mzximizing (or at least not minimizing) processing speed.

In his book, Mr. Hurley identifies five important techniques that were helpful toward obtaining an optimum memory-cost-to-processing-speed (MC/PS) ratio when I wrote my program. Though I did use most of these techniques in writing my program, I cannot honestly claim that each part of my program represents the most optimal acheivement of said ratio. Nonetheless, they were employed enough to make somewhat of a positive effect on processing speed and memory savings.

First, there is an advantage in using numerical variable names versus using numerical constants within code expressions. The savings in memory costs can be as much as 40% while still maintaining a faster processing speed. It is for these reasons that all of my subroutines, within my ZX TIC-TAC-TOE program, are called via a respective variable name. This technique also helps to easily access a particular routine in the program for purposes of editing or debugging.

Second, one of the most important aspects about my program is that it requires and makes plenty of use of FOR/NEXT loops. How these loops are structured can have a significant effect on the MC/PS ratio. how they can be made to optimize this ratio is a matter of determining the instruction-code placed inside this kind of loop structure, which will use the least amount of memory to accomplish the necessary accurate manipulation of data with the least amount of loop repetitions. Specific examples that illustrate this principle can be found in Mr. Hurley’s book on page 36.

Third, another benefit regarding how to preserve processing speep while saving memory is in how values are calculated with FOR/NEXT loops containing different arithmetic functions. For example, values determined by power functions tend to take longer to compute than if either multiplication or addition were used instead (Ibid., page 36).

Fourth, a substantial optimization of the MC/PS ratio results by initializing numerical variable name constants, in the immediate mode, versus listing them within the programming area. For both memory costs and execution time are augmented when these variables, unnecessarily occupy space both in the instruction area and the variable store. If entered via the immediate mode, they will still be saved on tape; so, why list them in the instruction area again?

Finally, Mr. Hurley’s book briefly mentions that where a subroutine is located in a program can affect the MC/PS ratio (Ibid., page 37). Routines (that differ only by size of their line numbers) at the beginning of a program use less memory, but are slower in executing; whereas, those further down the program execute faster but use more memory.

More programming concepts next time.