There are many reasons why you may need to access memory directly on an Archimedes. You might for example need to work with text strings longer than the 255 character limit imposed by Basic, or you may need to set up parameter blocks for use with SYS calls. Here is how it is done.
First of all you must reserve an area of memory. You should never attempt to access memory directly by giving a logical address (though this practice was acceptable on the old BBC micro). To reserve an area of memory, a version of the DIM statement is used:
DIM ram% 40
will reserve 41 bytes of RAM (i.e. one byte more than specified) for use by your program, and the variable ram% will be set (by Basic) to the start address of this block. It is worth noting that this block is always word-aligned (i.e. the start address is always divisible by 4).
Four so-called indirection operators are provided for reading and writing directly to memory - see Figure 1.
Symbol | Purpose | No of bytes |
? | read/write a byte | 1 |
! | read/write an integer | 4 |
| | read/write floating pt | 5 |
$ | read/write a string | 0 to 256 |
To store a byte of value 255 at the location ram%, use:
?ram%=255
Only integers in the range 0 to 255 may be stored in this way. To print out the value at ram%, use:
PRINT ?ram%
This will only work of course if you have already reserved an area of RAM at ram%.
The pling operator (!) works in a similar way:
!ram%=100000
will store the value 100000 at ram%. But now it is stored in four consecutive bytes (low byte first), providing a much greater range:
-2147483648 to 2147483647
To print the four-byte (=32 bit) value at ram%, use:
PRINT !ram%
The two operators ! and ? (but not | or $) can make use of a special so-called dyadic form of notation, where:
ram%?4
is equivalent to ?(ram%+4)
and
ram%!100
equates to !(ram%+100)
In other words, the address is formed by adding the two values together. The value before the operator must be a variable, while the second value may be a variable, a number or a bracketed expression.
The "|" operator (the "|" key is just above the Return key) functions similarly, except that it uses five consecutive bytes, and is used for treating floating point numbers. The range of these is:
-1.7x10^38 to 1.7x10^38
with an accuracy of 9 significant figures.
The $ operator will store and retrieve strings. To store the string "bananas" at ram%, use:
$ram%="bananas"
The effect of this is to store ASCII "b" at ram%, ASCII "a" at ram%+1, and so on. A carriage return character (ASCII 13) is automatically added at the end of the string in memory (in this case at ram%+7), but this is not echoed when the string is retrieved. Thus if you use:
A$=$ram%
to read the string into A$, the latter will not contain a carriage return.
Finally, you might like to try the short accompanying program to demonstrate the use of each operator.
10 REM >MemAccess
20 REM Demo of indirection ops
30 REM------------
40 DIM ram% &100
50 REM----------store
60 ?ram%=255
70 ram%!4=100000
80 |(ram%+8)=1.23456789876E9
90 $(ram%+13)="String storage"
100 REM----------retrieve
110 PRINT?ram%
120 PRINTram%!4
130 PRINT|(ram%+8)
140 PRINT$(ram%+13)