Good home wanted for machine code
(not too near Basic programs) APPLY WITHIN
By IAN MURRAY
WHEN we received our review copy of Assembly Programming Made
Easy for the BBC Micro, by lan Murray, we were so impressed that,
instead of a review, we decided to print an extract — with the
kind permission of the book's publishers. Century.
We're certain that, when you've read it, you too will be struck
with the clarity of lan's easy-to-understand explanations, and
want a copy for yourself.
So we've made obtaining this gentle guide to machine code programming
as simple as possible by making it a Micro User special offer.
See page 98 for full details.
The extract we've picked is on a subject we're often asked about
— where exactly can you store machine code?
Knowing that the BBC Micro assembles its code to the memory
location given by P% is one thing ... but how do you choose P%
to ensure that the code is safe from, say Basic programs?
Read on, and lan Murray will show you just how easy it is!
THE assembly language on the BBC Micro is written as part of
a Basic program. This is unique to the BBC machine as most other
assemblers stand alone and have nothing whatever to do with Basic
or any other language.
Obviously the machine code made by the assembler has to be found
a safe home somewhere in the computer's memory. Preferably this
home should not be part of or even near the Basic program itself.
If your Basic program with its assembly program "grows",
then it may bump into where your machine code would like to rest.
If your Basic program is unlikely ever to change in size, you
may get away with putting the machine code near Basic. But best
of all is to use the facilities provided for you by the BBC Micro.
You now need to know something about how the memory is divided
up. You would be foolish to try and put "your" machine
code where the designers of the BBC Micro have put "their"
code.
You will find a version of Figure I in the user guide on Page
500. As you can see, the whole of the top half of the memory is
just not available to you. Memory locations from 65535 decimal
to 49152 decimal are all used by the operating system.
Figure
I: The BBC Micro's memory map
This operating system is responsible for all the ordinary and
clever tricks of the BBC Micro, such as getting the tape loading
and saving to work, defining the red function keys, scanning the
keyboard for which key you have pressed and putting it on to the
screen, allowing you to change colours on the screen easily and
quickly. The list is endless.
Then the Basic language takes up locations 49151 decimal to
32768 decimal. Remember, Basic needs all this memory so that it
can work out the machine code equivalent of the program that you
typed in in human readable form. For the more technical of you,
Basic in the BBC Micro is an "interpreted language".
This means that, though you may have a 500 line Basic program,
it goes to work converting into machine code only the actual instruction
it has to carry out next, leaving all the others unconverted until
needed.
We are told by the manufacturers that, starting from the bottom,
memory locations 0 to 3583 decimal are also reserved for use by
the operating system.
This means that the only memory location available to the Basic
program you write, with the assembly program inside it, the machine
code generated by the assembly program and the screen graphics,
is from 3584 decimal to 32767 decimal (on a Model B machine).
Whatever you write in your Basic program is stored by the operating
system upwards from 3584 decimal. If you type the Basic command:
PRINT TOP
then the top memory address used by your program will appear
on the screen. TOP is a word reserved by Basic for this purpose.
Similarly if you type into the machine:
PRINT LOMEM
that will tell you where Basic intends to keep the values associated
with any of the variables used in your Basic program. Mostly it
will be one different from TOP — but you can change this. The
screen graphics need a slice of memory and this works down from
location 32767 decimal. Where it finishes is shown by the Basic
word HIMEM.
In every mode it is different. HIMEM is not the same in Mode
2 and Mode 7. Type into the machine:
MODE 2
PRINT HIMEM
MODE 7
PRINT HIMEM
You can think of HIMEM as a huge wall across memory. Most of
the memory below HIMEM can be used by you in various ways.
None of the memory above HIMEM can be used by you as it is needed
by either the screen, Basic language or the operating system.
But this is a wall with rollers under it. It is possible to
roll the HIMEM wall down memory, creating empty space behind it
and before the start of the screen graphics.
Typing in Mode 7 and PRINT HIMEM in a BBC Model B will have
given you the answer 31744. If you type:
HIMEM = 31000
then you will have created 744 empty memory locations which
are free for any machine code that you would like to pop into
them. The first one free will be 31001 decimal. You can set the
program counter to 31001 by typing:
LET P% =31001
and then all the machine code you assemble will slip into the
memory locations free to it.
But beware! If it turns out that you need more than 744 memory
locations the computer will not tell you — unless you ask — and
certainly no error messages will appear.
So after you have finished assembling your program into machine
code you would need to type:
PRINT P%
to find out if it was 31744 decimal - or perhaps more - so intruding
into the area for Mode 7 screen graphics.
For the technically minded, now is the time to reveal that strictly
speaking P% is not the true program counter. It is a variable
used by Basic and the BBC operating system which usually shows
what the program counter has stored in it. But it operates just
like the program counter.
So Rule 1 for finding space for machine code is:
MOVE HIMEM down memory.
PLACE machine code between HIMEM and start of screen graphics.
Problems with Rule 1:
• You have to make certain that you reserve enough space and
do not overwrite screen graphics.
• Any change of mode in your program will reset HIMEM and probably
lead to screen graphics in the new mode over-writing your machine
code.
• As TOP shows where the Basic program itself is, we could place
our machine code in some memory locations above TOP. We can type:
LET P% = TOP + 1000
Our machine code would then be placed from "TOP + 1000"
upwards. This may interfere with work space that Basic needs,
which starts at HIMEM and works downwards towards LOMEM. But as
a temporary measure in Mode 7 it will work adequately.

Rule 2 for finding space for machine code is:
SET the program counter to a suitable value above TOP.
Problems with Rule 2:
• The location above TOP that you set for the program counter
must give Basic enough room to store its variable values.
• With a large Basic program in Mode 7 or even a small Basic
program in Mode 2 you must make sure that your resetting of the
program counter does not take you too near HIMEM or you will not
allow yourself enough memory space.
You can, of course, try to overcome one of these disadvantages
by shifting the LOMEM wall upwards and fitting your machine code
between TOP and LOMEM.
Basic's variables are dealt with where LOMEM starts, so you
would have unused space by doing this shift, like:
LOMEM = LOMEM + 250
This would give you 250 free memory locations. You would then
need to type:
LET P% = TOP
Rule 3 for finding machine code space:
MOVE LOMEM upwards to a suitable new location.
SET the program counter to TOP
Disadvantages of Rule 3:
• You must give yourself enough space for your machine code,
or you will overwrite where Basic keeps its variable values.
• You must move LOMEM upwards before any reference to any variable.
Otherwise that variable will sit where it usually does, just one
above TOP. Your machine code would then overwrite it.
• You may move LOMEM too close to HIMEM causing the Basic to
"scramble".
As you remember from Figure I showing how the BBC Micro's memory
is organised, there are interesting areas at the bottom of memory.
Just as we can move LOMEM and HIMEM around in memory, so we
can move PAGE.
PAGE always has the memory location of the beginning of your
Basic program. For tape-based machines this is always 3584 decimal
(&E00 hex). For disc-based machines this is different. For
technical reasons any movement of :he PAGE wall must be groups
of 256 memory locations.
So we can type:
PAGE = PAGE + 512
This would give us 512 free memory locations from 3584 decimal
upwards. We could then type:
LET P% = 3584 (for tape machines)
This is a bit messy. It would be better to type:
LET P% = PAGE - 512
This would mean it would not matter if you were using disc or
tape machines.
Rule 4 for finding space for machine code is:
SET PAGE to a new value above its current value. This must
be a multiple of 256.
SET the program counter to the old value of PAGE.
Disadvantages of Rule 4:
• Any new Basic program you now load must be forced to load
above the machine code, either by manually resetting PAGE to the
suitable value, or by specifying the load address when you do
load it.
• If you need 260 memory locations for the machine code, then
you will have to take the full 512 memory locations, which will
mean wasting empty memory locations. This could be significant
in a high resolution graphics program.
The BBC Micro's operating system seems (with tape-based machines)
to have left memory locations 3328 decimal (&D00 hex) to 3583
decimal (&DFF hex) free for machine code use.
If this is enough space for you, then you can type:
LET P% = 3328
or
LET P% = &D00
These mean the same. &D00 is 3328 in the hexadecimal counting
system which will be explained in detail later. Some of the games
programs on the market hide their machine code at &D00. You
may have noticed this.
Rule 5 for finding machine code space:
SET the program counter to 3328 decimal (&D00 hex).
Disadvantages of Rule 5:
• Very little space is available to you for the machine code
before you start overwriting the Basic program beginning at 3584
decimal.
• If you have a disc based system, you will find that the system
itself uses some of this memory. Then you may find that the machine
code starts doing funny things to the disc drives (such as turning
them on), or that any disc load operations are incorrect or that
use of the Break key overwrites your machine code.
This is often the cause of problems you may have found with
copying machine code games over to a disc system. These games
probably had machine code sitting at &D00 hex.
Rule 5 can sometimes be extended to start at either 3072 decimal
(&C00 hex) or 2816 decimal (&B00 hex). These memory locations
also get round the problems with disc based machines.
But you can only use them if:
• Nowhere in your program do you use program (or user) defined
characters. These are stored from 3072 decimal (&C00 hex)
to 3327 decimal (&CFF hex).
• Nowhere in your program do you use the red function keys.
Your plans for these keys are stored in memory locations 2816
decimal (&B00 hex) to 3071 decimal (&BFF hex).
But, as I said earlier, the BBC Micro does try to make life
easy for you. The designers were aware that all these different
hiding places for machine code could be annoying to organise.
They invented a special Basic command which allows the BBC operating
system to fit in your machine code wherever it can find space,
thus taking the worry off your shoulders.
If you type:
LET P% = DIM A% 300
then the program counter is set to start at a 300-long block
of memory locations which begins at A%. You do not need to know
where the block of memory is, but you can find out by typing:
PRINT A%
This is the most common and useful method of hiding machine
code, as it does not depend on what mode you are in or on PAGE,
HIMEM or LOMEM.
Rule 6 for finding machine code space:
SET aside memory space with the DIM statement.
SET the program counter to the DIM statement.
Generally if the machine code is to be part of a Basic program,
such as a games or educational program, then Rule 6 is the best
method.
But if you want to engage in software protection or have a machine
code sitting in the machine whatever Basic program is running,
then you will have to choose one of the other rules. Probably
it is best to hide short programs at 3328 decimal (&D00 hex).