Part 24
The memory

Subjects covered...

	PEEK
	POKE
	CLEAR
	Memory management

Deep inside the +3, everything is stored as bytes, i.e. number between
0 and 255 (FFh). You may think you have stored away the price of
Ruddles or the players' names in the Arsenal football team, but in
fact, all the information has been converted into collections of
bytes, and bytes are what the computer sees.

Each place where a byte can be stored has an address, which is a
number between 0 (or 0000h) and 65535 (FFFFh). This means that an
address can be stored as two bytes. You can think of the memory as a
long row of numbered boxes, each of which can contain a byte. Not all
the boxes are the same, however - the boxes from 4000h to FFFFh are
RAM boxes, which means you can open the lid and alter the contents,
but those from 0 to 3FFFh are ROM boxes, which have a glass lid that
cannot be opened - you just have to read whatever was put into them
when the computer was made. In the +3, we have crammed in more than
twice the amount of memory than can comfortably fit. While the
processor can address 65536 bytes, there are in fact 131072 bytes of
RAM and 65536 bytes of ROM making 196608 bytes (192K) in all! All this
is hidden from the processor by the hardware using a process called
paging - BASIC (and the processor) always 'sees' the memory as 16K of
ROM and 48K of RAM (or 64K of RAM with no ROM - though this latter
combination is never used by BASIC).


		      65535  +---------+  FFFFh
			     | RAM 0-7 |
		      49152  |---------|  C000h
			     |  RAM 2  |
		      32768  |---------|  8000h
			     |  RAM 5  |
		      16384  |---------|  4000h
			     | ROM 0-3 |
			  0  +---------+  0000h

			  The +3 memory map


To inspect the contents of a box, we use the PEEK function. Its
argument is the address of the box, and its result is the
contents. For example, this program prints out the first 21 bytes in
ROM (and their addresses)...

	10 PRINT "Address"; TAB 8; "Byte"
	20 FOR a=0 TO 20
	30 PRINT a; TAB 8; PEEK a
	40 NEXT a

All these bytes will probably be quite meaningless to you, but the
processor chip understands them to be instructions telling it what to
do.

To change the contents of a box (if it is RAM), we use the POKE
command. Its form is...

	POKE address,contents

...where address and contents are numeric expressions. For example, if
you type...

	POKE 31000,57

...then the byte at address 31000 is given the new value 57. Now
type...

	PRINT PEEK 31000

...to prove this. (Try poking in other values, to show that there is
no cheating.) The new value must be between -255 and +255; if it is
negative, then 256 is added to it.

The ability to poke gives you immense power over the computer if you
know how to wield it, and immense destructive possibilities if you
don't. It is very easy (by poking the wrong value into the wrong
address) to lose vast programs that took you hours to type
in. Fortunately though, you won't do the computer any permanent
damage.

We shall now take a more detailed look at how the RAM is used. Don't
bother to read this unless you're really interested.

The memory is divided into different areas (shown in the diagram
ahead) for storing different kinds of information. The areas are only
large enough for the information that they actually contain, and if
you insert some more at a given point (for instance by adding a
program line or variable), then space is made by shifting up
everything above that point. Conversely, if you delete information,
then everything is shifted down.

The display file stores the contents of the TV screen. It is rather
curiously laid out, so you probably won't want to PEEK or POKE in
it. Each character position on the screen has an 8 x 8 grid of dots;
each dot can be either 0 (paper) or 1 (ink), so by using binary
notation we can store the pattern as 8 bytes - one for each
row. However, these 8 bytes are not stored together. The corresponding
columns in the 32 characters of a single line are stored together as a
scan of 32 bytes, because this is what the electron beam in the TV
needs as it scans from the left-hand side of the screen to the
other. Since the complete picture has 24 lines of 8 scans each, you
might expect the total of 192 scans to be stored in order, one after
the other - well you'd be wrong! First come the top scans of lines 0
to 7, then the next scans of lines 0 to 7, and so on to the bottom
scans of lines 0 to 7; then the same for lines 8 to 15; and again for
lines 16 to 23. The upshot of all this is that if you're used to a
computer that uses PEEK and POKE on the screen, then you'll have to
start using SCREEN$ and 'PRINT AT' instead (or PLOT and POINT).

The attributes are the colours and so on for each character position,
using the format of ATTR. These are stored line by line in the order
you'd expect.

The way that the computer organises its affairs changes slightly
between 48 BASIC and +3 BASIC mode. The area that was the printer
buffer in 48 BASIC mode, is used for extra system variables in +3
BASIC mode in much the same way as it was on the Spectrum +2. The
variables have changed, though.


                                              5C00h
                                             (23552)
                                                |
                                                v
                              +-----------------+-----------------+
             (48K mode only)  | Printer buffer  |   System vars   |
                              +-----------------+-----------------+
                              :                                   :
  +--------------+------------+-----------------------------------+--
  | Display file | Attributes |        System variables           |
  +--------------+------------+-----------------------------------+--
  ^              ^            ^                 ^                 ^
  |              |            |                 |                 |
4000h          5800h        5B00h             5C00h             5CB6h
(16384)       (22528)      (23296)           (23552)           (23734)
                                                                CHANS

--+-------------+-----+-------+------+-----+-------------------+----+-----+--
  |   Channel   | 80h | BASIC | Vars | 80h | Command or prog.  | NL | 80h |
  | information |     | prog  |      |     | line being edited |    |     |
--+-------------+-----+-------+------+-----+-------------------+----+-----+--
      ^                                                                   ^
      |                                                                   |
    5CB6h                                                             WORKSP
   (23734)
    CHANS

--+-------+----+------------+------------+-------+---------+--
  | INPUT | NL | Temporary  | Calculator | Spare | Machine |
  | data  |    | work space |    stack   |       |  stack  |
--+-------+----+------------+------------+-------+---------+--
  ^                         ^            ^       ^
  |                         |            |       |
WORKSP                    STKBOT      STKEND     SP
                                             (stack pointer)

--+--------------+---+-----+-----------------------+
  | GO SUB stack | ? | 3Eh | User defined graphics |
--+--------------+---+-----+-----------------------+
                     ^     ^                       ^
                     |     |                       |
                  RAMTOP  UDG                   P RAMT


The system variables contain various pieces of information that tell
the computer what sort of state it's in. They are listed fully in part
25 of this chapter, but for the moment, note that there are some
(called CHANS, PROG, VARS, E LINE, and so on) that contain the
addresses of the boundaries between the various areas in memory. These
are not BASIC variables, and their names will not be recognised by the
+3.

The channel information contains information about the input and
output devices, namely the keyboard (together with the lower half of
the screen), the upper half of the screen, and the printer.

Each line of BASIC program has the form...


	Most significant byte
       	  |
	  |  Least significant byte
	  |    |
	  v    v
	+----+----+---------+-------- - - - - --------+-+-+-+-+-+-+-+-+
	|    |    |         |  		              | | | | | | | | |
       	| 2 bytes | 2 bytes |  		              |0 0 0 0 1 1 0 1|
       	|    |    |         |  		              | | | | | | | | |
       	+----+----+---------+-------- - - - - --------+-+-+-+-+-+-+-+-+
         \_______/ \_______/ \_______________________/ \_____________/
	     |         |       	         |                    |
	    Line   Length of   		Text		    ENTER
	   number  text + ENTER


Note that, in contrast with all other cases of two-byte numbers in the
Z80, the line number here is stored with its most significant byte
first, i.e. in the order that you'd write them down.

A numerical constant in the program followed by its binary form, using
the character 'CHR$ 14' followed by five bytes for the number itself.

The variables have different formats according to their different
natures. The letters in the names should be imagined as starting off
in lower case.

Number whose name is one letter only:


				     Sign bit
					 |
					 v
       	+-+-+-+-+-+-+-+-+---------------+-+----- - - - - ------+
	| | | |	| | | |	| 		| |                    |
	|0 1 1          | Exponent byte	|    4 Mantissa bytes  |
        | | | | | | | | |		| |		       |
       	+-+-+-+-+-+-+-+-+---------------+-+----- - - - - ------+
	       \_______/ \____________________________________/
		   |     		   |
	       Letter-60h		 Value


Number whose name is longer than one letter:


       	+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - -+-+-+-+-+-+-+-+-+--- - - ---+
	| | | |	| | | |	| | | | | | | | |    | | | | | | | | |           |
        |1 0 1          |0             	|    |1              |  5 bytes  |
        | | | | | | | | | | | | | | | | |    | | | | | | | | |           |
       	+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- - +-+-+-+-+-+-+-+-+--- - - ---+
	       \_______/ \_____________/      \_____________/ \_________/
		   |            |              	     |	     	   |
	       Letter-60h  2nd character       Last character	 Value


Array of numbers:


       	+-+-+-+-+-+-+-+-+-------+------+-------+ - - +-------+-------+
	| | | |	| | | |	|   2	|  1   |   2   |     |   2   |   5   |
        |1 0 0          | bytes | byte | bytes |     | bytes | bytes |
        | | | | | | | | | 	|      |       |     | 	     | each  |
       	+-+-+-+-+-+-+-+-+-------+------+-------+ - - +-------+-------+
               \_______/ \_____/ \____/	\_____/	      \_____/ \_____/
		   |        |      |       |             |       |
	       Letter-60h  Total  No.   1st dim.       Last   Elements
			  length  of dims              dim.
		      of elements &
		      dims + 1 for no.
		      of dimensions


The order of the elements is:

First - the elements for which the first subscript is 1.
Next - the elements for which the first subscript is 2.
Next - the elements for which the first subscript is 3...
...and so on for all possible values of the first subscript.

The elements with a given first subscript are ordered in the same way
using the second subscript, and so on down to the last.

As an example, the elements of the 3 x 6 array 'c' in part 12 of this
chapter are stored in the order
c(1,1) c(1,2) c(1,3) c(1,4) c(1,5) c(1,6) and
c(2,1) c(2,2) ... c(2,6) and c(3,1) c(3,2) ... c(3,6).


Control variable of a FOR...NEXT loop:


			     Least significant byte  Most significant byte
					          |   |
					       	  v   v
       	+-+-+-+-+-+-+-+-+-------+-------+-------+---+---+------+
	| | | |	| | | |	|   5	|  1    |   2   |   |   |  1   |
        |1 1 1          | bytes | byte  | bytes |2 bytes| byte |
        | | | | | | | | |       |       |       |   |   |      |
       	+-+-+-+-+-+-+-+-+-------+-------+-------+---+---+------+
               \_______/ \_____/ \_____/ \_____/ \_____/ \____/
		   |        |       |       |       |       |
	       Letter-60h  Value  Limit   Step   Looping  Statement
						  line    number
							within line


String:


       	+-+-+-+-+-+-+-+-+---------+--------- - - - ----------+
        | | | |	| | | |	| 	  |          		     |
	|0 1 0          | 2 bytes |	        	     |
        | | | | | | | | |         |	        	     |
       	+-+-+-+-+-+-+-+-+---------+--------- - - - ----------+
	       \_______/ \_______/ \________________________/
		   |         |       	       |
	       Letter-60h  Number        Text of string
			     of      	 (may be empty)
			 characters


Array of characters:


       	+-+-+-+-+-+-+-+-+-------+------+-------+ - - +-------+------+
	| | | |	| | | |	|   2	|  1   |   2   |     |   2   |   1  |
        |1 1 0          | bytes | byte | bytes |     | bytes | byte |
        | | | | | | | | | 	|      |       |     | 	     | each |
       	+-+-+-+-+-+-+-+-+-------+------+-------+ - - +-------+------+
               \_______/ \_____/ \____/	\_____/	      \_____/ \____/
		   |        |      |       |             |       |
	       Letter-60h  Total  No.   1st dim.       Last   Elements
			  length  of dims              dim.
		      of elements &
		      dims + 1 for no.
		      of dimensions


The calculator is the part of the BASIC system that deals with
arithmetic, and the numbers on which it is operating are held mostly
in the calculator stack.

The spare area contains the space so far unused.

The machine stack is the stack used by the Z80 processor to hold
return addresses and so on.

The GO SUB stack was mentioned in part 5 of this chapter.

The byte 'pointed to' by RAMTOP has the highest address used by the
BASIC system. Even NEW, which clears the RAM, only does so as far as
this - so it doesn't change the user-defined graphics. You can change
the address RAMTOP by putting a number in a CLEAR statement, i.e....

	CLEAR new RAMTOP

...which does the following:

	1. Clears out all variables.

	2. Clears the display file (like CLS does).

	3. Resets the PLOT position to the bottom left-hand corner.

	4. RESTOREs the DATA pointer.

	5. Clears the GO SUB stack and puts it at the new RAMTOP
	   (assuming that this lies between the calculator and the
	   physical end of RAM; otherwise it leaves RAMTOP where it
	   was).

RUN also performs a CLEAR, although it never changes RAMTOP.

Using CLEAR in this way, you can either move RAMTOP up to make more
room for the BASIC by overwriting the user-defined graphics, or you
can move it down to make more RAM that is preserved from NEW. It can
also be used to ensure that the machine stack is below BFE0h (49120)
when intending to call +3DOS - this means that the stack will not have
to be subsequently moved within your own machine code.

If you are in an experimental frame of mind you can also use CLEAR to
explore the extra memory. 'CLEAR 49151' moves all of BASIC below the
addresses that hold the switchable RAM paging. By using 'POKE
23388,16+n' where 'n' is a number between 0 and 7, you can make the
computer switch in page 'n' of the RAM. You will then be able to use
PEEK and POKE in the normal way to examine and change the page. Beware
- the extra pages are normally used by the system for disk and editor
operations, so always reset the +3 after exploring in this way, before
doing anything else.


Type NEW, select '+3 BASIC', then enter the command 'CLEAR 23825' to
get some idea of what happens to the machine when it fills up.

If you then try to make the +3 compute, (for example, type in 'PRINT
1+1') you will see the report '4 Out of memory' displayed. This means
the computer has no more room for information. If you come up against
this message while entering a large program, you will have to empty
the memory slightly (delete a line or so) in order to control the
computer.


Memory management

We mentioned earlier that there is rather more memory in the computer
than the processor can deal with. While the processor can indeed
address only 64K of memory at once, the extra memory can be slotted in
and out of that 64K at will. Consider a TV set. Although it (and you)
can only deal with one channel at a time, there are another three
channels always there which can be selected with the right
buttons. So, even though there's four times as much information as you
can use at any one time, you can pick and choose which part is
relevant.

It is much the same for the processor. By setting the right bits in an
I/O port it can pick and choose which chunks of the 192K of memory it
wants to use. For the majority of the time in BASIC it ignores most of
the memory, but for games playing, having three times as much RAM is
really rather useful. Look again at the +3's memory map (shown at the
beginning of this section). RAM pages 2 and 5 are always in the
positions shown when BASIC is used, though there's no reason why they
shouldn't be in the banked section (C000h to FFFFh) - however, it
would be difficult to see any use for this.

The RAM banks are of two types: RAM pages 4 to 7 which are contended
(meaning that they share time with the video circuitry), and RAM pages
0 to 3 which are uncontended (where the processor has exclusive
use). Any machine code which has critical timing loops (such as music
or communications programs) should keep all such routines in
uncontended banks. For example, executing NOPs in contended RAM will
give an effective clock frequency of 2.66Mhz as opposed to the normal
3.55MHz in uncontended RAM. This is a reduction in speed of about 25%.

The hardware switch normally used to select RAM is at I/O address
7FFDh (32765). The bit field for this address is as follows:

	D0...D2		- RAM select
	D3		- Screen select
	D4		- ROM select
	D5		- Disable paging

D2...D0 is a three bit number that selects which RAM page goes into
the C000h to FFFFh slot. In BASIC, RAM page 0 is normally in
situ. When editing or calling +3DOS routines, RAM page 7 is used for
various buffers and 'scratchpads'. D3 switches screens: screen 0 is
held in RAM 7 (beginning at C000h) and can only be used by machine
code programs. It is entirely feasible to set up a screen in RAM 7 and
then page it out; this leaves the entire 48K free for data and
program. Note that the +3's COPY (file) command may well use buffers
in the second screen area (corrupting a second screen which may be
'hidden' there). D4 determines which ROM is paged into 0000h to 3FFFh
(in combination with bit 2 of port 1FFDh - see below). D5 is a safety
feature - once this bit has been set, no further paging operations
will work. This is normally used when the machine assumes a standard
48K Spectrum configuration and all the memory paging circuitry is
locked out. It cannot be turned back into a 128K machine other by
switching off or pressing RESET button; however, the sound chip can
still be driven by OUT. If a 48K Spectrum game loaded from disk will
not work, it is possible that by using the SPECTRUM command followed
by 'OUT 32765,48' (which locks bit 5 in this port), the game might
then work.

The +3 also uses I/O port 1FFDh for some ROM and RAM switching. The
bit field for this address is as follows:

	D0...D1		- ROM/RAM switching
	D2		- Affects whether D0...D1 work on RAM/ROM
	D3		- Disk motor
	D4		- Parallel port strobe (active low)

When bit 0 is 0, bit 1 has no effect and bit 2 is a 'vertical' ROM
switch (i.e. between ROM 0 and ROM 2, or between ROM 1 and ROM 3). Bit
4 in the port at 7FFDh is a 'horizontal' ROM switch (i.e. between ROM
0 and ROM 1, or between ROM 2 and ROM 3). The following diagram serves
to show the various ROM switching possibilities...


	+-------------+	   Bit 4  7FFDh (23388)	   +-------------+
	|	      |	 (system variable: BANKM)  |		 |
	|    ROM 0    |				   |	ROM 1	 |
	|	      | <-----	horizontal  -----> |		 |
	|   Editor    |				   |   Syntax	 |
	|	      |				   |		 |
	+-------------+				   +-------------+
	       ^					  ^
	       |					  |
							  |
      Bit 2  1FFDh (23399)				  |
   (system variable: BANK678)
	   vertical				       vertical

	       |					  |
	       v					  v
	+-------------+				   +-------------+
	|	      |				   |		 |
	|    ROM 2    |				   |	ROM 3	 |
	|	      | <-----	horizontal  -----> |		 |
	|     DOS     |				   |  48 BASIC	 |
	|	      |				   |		 |
	+-------------+				   +-------------+


		  Horizontal and vertical ROM switching


It is best to think of bit 4 in port 7FFDh and bit 2 in port 1FFDh
combining to form a 2-bit number (0...3) which determines which ROM
occupies the memory area 0000h...3FFFh. Bit 4 of port 7FFDh is the
least significant bit and bit 2 of 1FFDh is the most significant bit.


Bit 2 of 1FFDh		Bit 4 of 7FFDh		Switched ROM at
(sys. var.: BANK678)	(sys. var.: BANKM)	 0000h...3FFFh

	0			0			0
	0			1			1
	1			0			2
	1			1			3

	  ROM switching (with Bit 0 of 1FFDh set to 0)


When bit 0 of port 1FFDh is set to 1, bits 1 and 2 switch in various
RAM combinations that occupy the full 64K address space. These are not
used by +3 BASIC but are provided for authors of operating
systems/games. When the +3DOS 'DOS BOOT' routine is used, the
bootstrap is loaded into the 4, 7, 6, 3 RAM page environment. The
various +3 extra RAM paging options are as follows:


Bit 2 of 1FFDh		Bit 1 of 1FFDh		RAM pages used
						(0000h...3FFFh,
						4000h...7FFFh, etc.)

	0			0		   0, 1, 2, 3
	0			1		   4, 5, 6, 7
	1			0		   4, 5, 6, 3
	1			1		   4, 7, 6, 3

	Extended memory paging (with Bit 0 of 1FFDh set to 1)
[Back] [Contents] [Next]