|
 |
 |
3
The
Monitor
A monitor is a program which
allows you to work directly with your computer's memory cells. When
the computer "falls below" BASIC into the monitor mode, BASIC is no
longer active. If you type RUN, it will not execute anything. BASIC
commands are not recognized. The computer waits, as usual, for you
to type in some instructions. There are only a few instructions to
give to a monitor. When you're working with it, you're pretty close
to talking directly to the machine in machine language.
The PET and Apple II have monitors in ROM. This means
that you do not need to load the monitor program into the computer;
it's always available to you. (PETs with Original ROM sets do not
have a ROM monitor; you must load in the monitor from a tape or
disk.) Atari and VIC computers have a monitor as part of a larger
"Assembler Editor" plug-in cartridge. The monitor on the Atari
cartridge is called the "Debugger." That's a good name for it:
debugging is the main purpose of a monitor. You use it to check your
ML code, to find errors. The various
computers have different sets of instructions which their monitors
recognize. However, the main functions are similar, so it is worth
reading through all of the following descriptions, even if the
discussion is not specifically about the monitor for your computer.
On the PET/CBM, VIC, and 64 you can add many of these functions with
a monitor "extension" program called Micromon or Supermon (about
which more later). These monitors are included in Appendix F. The
monitors on the Apple II and available in the Atari Assembler Editor
Cartridge do not need "extending." They contain most of the
significant features required of a monitor. However, the special
extensions in Appendix F for the Commodore computers add
considerably to the Commodore ML programmer's
repertoire.
The
Apple II You enter the Apple monitor by typing CALL
-151. You will see the "*" monitor prompt and the cursor immediately
after it. Here are the monitor instructions:
1. Typing an address (in hex) will show you the number
contained in that memory cell. *2000 (hit RETURN) will show 2000 -
FF (if, in fact, 255 decimal ($FF, hex) is in that
location). 2. You can examine a larger amount
of memory in hex (this is called a memory dump or a hex dump). The
Apple monitor remembers the address of the last number displayed.
This can be used as a starting address for the dump. If you type the
instruction in number one above, and then type *.2010, you will see
a dump of memory between 2001 and 2010. The only difference between
this and instruction one is the period (.) before the requested
address. 3. You can directly cause a dump by
putting the period between two addresses: *2000.2010 combines the
actions of instructions one and two above. 4.
Hitting RETURN will continue a dump, one line at a time.
5. The last displayed memory location can be changed by
using the colon (:). This is the equivalent of BASIC's POKE. If
*2000 results in FF on the screen, you can change this FF to zero by
typing *:00. To see the change, type *2000 again. Or you could type
*2000:00 and make the change directly. The Apple II reference
manual contains excellent descriptions of the monitor instructions.
We will list the rest of them only briefly here:
6. Change a series of locations at once: *2000: 00 69 15 65
12. 7. Move (transfer) a section of memory:
*4000 < 2000.2010M will copy what's between 2000 and 2010 up to
address 4000. (All these addresses are hex.)
8. Compare two sections of memory: *4000 < 2000.2010V. This
looks like Move, but its job is to see if there are any differences
between the numbers in the memory cells from 2000-2010 and those
from 4000-4010. If differences are found, the address where the
difference occurs appears on screen. If the two memory ranges are
identical, nothing is printed on the screen.
9. Saving (writing) a section of ML to tape: *2000.2010W. This
is how you would save an ML program. You specify the addresses of
the start and end of your program. 10.
Loading (reading) a section of memory (or an ML program) back into
the computer from tape: *2000.2010R will put the bytes saved, in
instruction nine, above, back where they were when you saved
them. An interesting additional feature is
that you could send the bytes to any address in the computer. To put
them at 4000, you would just type *4000.4010R. This gives you
another way to relocate subroutines or entire ML programs (in
addition to the Move instruction, number seven above). If you move
an ML program to reside at a different address from the one it was
originally intended during assembly, any JMP or JSR (Jump To
Subroutine, like BASIC's GOSUB) instructions which point to within
your program must be adjusted to point to the new addresses. If your
subroutine contained an instruction such as 2000 JSR 2005, and you
loaded at 4000, it would still say 4000 JSR 2005. You would have to
change it to read 4000 JSR 4005. All the BNE, BPL, BEQ, branching
instructions, though, will make the move without damage. They are
relative addresses (as opposed to the absolute addressing of JSR
2005). They will not need any adjusting. We'll go into this in
detail later. 11. Run (go): *2000G will start
executing the ML program which begins at address 2000. There had
better be a program there or the machine is likely to lock up,
performing some nonsense, an endless loop, until you turn off the
power or press a RESET key. The program or subroutine will finish
and return control of the computer to the monitor when it encounters
an RTS. This is like BASIC's SYS command, except the computer
returns to the monitor mode. 12. Disassemble
(list): *2000L will list 20 lines of ML on the screen. It will
contain three fields (a field is a "zone" of information). The first
field will contain the address of an instruction (in hex). The
address field is somewhat comparable to BASIC's line numbers. It
defines the order in which instructions will normally be carried
out. Here's a brief review of disassembly
listings. The second field shows the hex numbers for the
instruction, and the third field is where a disassembly differs from
a "memory" or "hex" dump (see numbers one and two, above). This
third field translates the hex numbers of the second field back into
a mnemonic and its argument. Here's an example of a
disassembly:
2000 A9
41 LDA
#$41 2002 8D 23 32
STA $3223 2005 A4
99 LDY
$99
Recall that a
dollar sign ($) shows that a number is in hexadecimal. The pound
sign (#) means "immediate" addressing (put the number itself into
the A register at 2000 above). Confusing these two symbols is a
major source of errors for beginning ML programmers. You should pay
careful attention to the distinction between LDA #$41 and LDA $41.
The second instruction (without the pound sign) means to load A with
whatever number is found in address $41 hex. LDA #$41 means put the
actual number 41 itself into the accumulator. If you are debugging a
routine, check to see that you've got these two types of numbers
straight, that you've loaded from addresses where you meant to (and,
vice versa, you've loaded immediately where you intended).
13. Mini-assembler. This is an assembler program,
though it is not part of the monitor ROM. It is in the Integer BASIC
ROM, so systems using firmware Applesoft II cannot use it although
the Apple II Plus can, in the INT mode. Like the Simple Assembler,
this mini-assembler cannot use labels or calculate forward branches.
(The Simple Assembler can be used for forward branches, however, as
we'll see later.) You enter the Apple mini-assembler by typing the
address, mnemonic, and argument of your first instruction. The ! is
printed by the computer:
!2000:LDA
#15
This will be
disassembled, and then you type in the next line, using spaces
between each field:
! LDY
#01
14. Step and Trace.
These are very useful ways to isolate and fix errors. Remember that
ML does not have much in the way of error messages. In fact, unless
you are using a very complex assembler program, the only error that
an assembler can usually detect is an impossible mnemonic. If you
mistyped LDA as LDDA, your assembler would print ??? or, in the
Apple, sound a beep and put a circumflex (^) near the error. In any
case, you are not going to get elaborate SYNTAX ERROR messages. The
Simple Assembler will type the word ERROR on the screen. Try
it. We'll examine step and trace debugging
methods under numbers 10 and 11 of the discussion of the Atari
cartridge below. The Atari Assembler Cartridge and the Commodore
Monitor Extension programs both allow step and trace, too.
15. Changing registers. *(CONTROL) E will display the
contents of the Accumulator, the X and Y registers, the status
register (P) and the stack pointer (S). You can then change the
contents of these registers by typing them in on screen, following a
colon. Note that to change the Y register, you must type in the A
and X registers as well:
*(CONTROL) E
You'll see: A=01 X=05 Y=FF P=30 S=FE (whatever's in the
registers at the time). To change the Y
register to 00, you type in the A, X, and then the new version of
Y:
*:01 05 00 (and hit RETURN)
16. Going back to BASIC. You can use * (CONTROL) B to
go to BASIC (but it will wipe out any BASIC program that might have
been there). Or you can use * (CONTROL) C to go back to BASIC,
non-destructively.
The Atari
Monitor To enter the monitor on the Atari, you put the
assembler cartridge into the left slot. The Atari does not have a
monitor in ROM; you need the cartridge. As mentioned at the start of
this chapter, the monitor mode in Atari is called DEBUG and is a
part of the larger program within the assembler cartridge. There are
three parts (or modes) within the cartridge: EDIT, ASM (assembler),
and DEBUG. Before looking at the commands available in the DEBUG
mode, let's briefly explore how an ML program is created using the
EDIT mode followed by ASM. The cartridge provides the Atari with a
more advanced assembler than the Simple Assembler or the
mini-assemblers available within the Apple II monitor or the
Commodore monitor extension programs. The cartridge allows labels,
comments, and line numbers. Until now, we've
discussed ML programming which uses three fields (zones). Here's an
example program which shows these three simple fields. We will print
ten "A's" on the screen (the numbers are decimal):
Address
Field
|
Instruction
Field
|
Argument (Operand)
Field
|
2000
|
LDY
|
#10
|
2002
|
LDA
|
#33
|
2004
|
STA
|
(88),y (The screen
location is remembered by the Atari in addresses 88 and
89.)
|
2007
|
DEY
|
|
2008
|
BNE
|
2004
|
2010
|
RTS (or BRK)
|
|
When you are in Atari's EDIT mode, you construct a
program somewhat differently than you do with the Simple Assembler
(or with mini-assemblers). Here's the same program using the Atari's
additional fields:
Line # Label
Instruction Argument Comments 100
START LDY
#10 Set up counter for
loop 110
LDA #33
"A" in ATASCII 120
LOOP STA
(88),Y 130
DEY 140
BNE
LOOP Loop until
zero
Notice that labels
allow us to use the word LOOP instead of the specific address we
want to loop back to. In addition to all this, there are pseudo-ops
which are instructions to the assembler to perform some task. A
pseudo-op does not become part of the ML program (it's not a 6502
instruction), but it affects the assembly process in some way. We
would need two pseudo-ops in the above program to allow it to be
assembled properly. Add these lines:
10 * =
$0600 (tells the assembler that this program should be assembled
starting at address $0600. The $ means hexadecimal.)
160 .END (tells the assembler that it should stop assembling
here.)
The example above with line
numbers and labels is called source code because it is the
source from which the assembler gets its information when it
assembles object code (object code is an actual ML program which
could be run, or executed). You cannot run the program above as is.
It must first be assembled into 6502 ML. For one thing, the label
LOOP has to be replaced with the correct branch back to line 120.
Source code does not put bytes into memory as you write it (as a
more elementary assembler like the Simple Assembler
does).
More Than
A Monitor To make this into object
code which you can actually execute, you type ASM (for assemble),
and the computer will put the program together and POKE the bytes
into memory, showing you on screen what it looks like.
To test the program, type BUG to enter the DEBUG mode,
clear the screen, and RUN it by typing G600 (for GO $0600). You'll
see AAAAAAAAAA on screen. It works! All this
isn't, strictly speaking, a monitor. It's a full assembler. The part
of the assembler cartridge program which is equivalent to the
monitor programs on Apple II and PET is the DEBUG mode. There are a
number of commands in DEBUG with which you can examine, test, and
correct ML code. As on the other computers, the DEBUG (monitor) mode
allows you to work closely with single bytes at a time, to see the
registers, to trace program flow. All numbers you see on screen (or
use to enter into the computer) are in hex. You enter the DEBUG mode
by typing BUG when the Assembler Cartridge is in the Atari. (To go
back to EDIT mode, type X.) Here are the commands of
DEBUG: 1. Display the registers: type DR
(RETURN) and you will see whatever is in the various
registers. A=01 X=05 Y=OF P=30 S=FE (P is the
status register and S is the stack pointer.)
2. Change the registers: type CR < 6,2 (RETURN) and you
will have put a six into the accumulator and a two into the X
register. To put a five into the status register, you must show how
far to go by using commas: CR < „, 5 would do it. CR < 5 would
put five into the accumulator. 3. Dump
memory: type D2000 and you will see the eight hex numbers which
start at address 2000 in memory.
D2000 2000 FF 02 60 20 FF D2 00
00 D2000,2020 (would dump out memory between
these two addresses)
4. Change memory:
type C2000 < 00,00 to put zeros into the first two bytes
following address 2000. 5. Transfer (move)
memory: type M1000 < 2000,2010 and you will non-destructively
copy what's between 2000-2010 down into 1000-1010.
6. Compare (verify) memory: type V1000 < 2000,2010 and any
mismatches will be printed out. 7.
Disassemble (list): type L2000 and you will see 20 lines of
instructions displayed, the mnemonics and their arguments.
8. Mini-assemble: the DEBUG mode allows you to enter
mnemonics and arguments one at a time, but you cannot use labels.
(The pseudo-ops BYTE, DBYTE, and WORD are available, though.) This
is similar to the Simple Assembler and the mini-assemblers available
to Apple II and PET monitor users. You type
2000 < LDA $05 and the computer will show you the bytes as they
assemble into this address. Subsequent instructions can be entered
by simply using the less-than sign again: < INC $05. To return to
the DEBUG mode, you can hit the RETURN key on a blank
line. 9. Go (RUN a program): type G2000 and
whatever program starts at address 2000 will run. Usually, you can
stop the RUN by hitting the BREAK key. There are cases, though,
(endless loops) which will require that you turn off the computer to
regain control. 10. Trace: type T2000 and you
will also RUN your program, but the registers, bytes of ML code, and
the disassembled mnemonics and arguments are shown as each
instruction is executed. This is especially useful since you can
watch the changes taking place in the registers and discover errors.
If you have an LDA $03 and you then expect to find the accumulator
to have the number three in it - you'll notice that you made that
very common mistake we talked about earlier. Following LDA $03, you
will see that the accumulator has, perhaps, a ten in it instead of
the three you thought you'd get. Why? Because you wanted to write
LDA #03 (immediate). Instead, you mistakenly loaded A with the value
in address three, whatever it is. Seeing
unexpected things like this happen during trace allows you to
isolate and fix your errors. Trace will stop when it lands on a BRK
instruction or when you press the BREAK key.
11. Step: type S2000 and you will "step" through your program
at 2000, one instruction at a time. It will look like trace, but you
move slowly and you control the rate. To see the following
instruction, you type the S key again. Typing S over and over will
bring you through the program. 12. Return to
EDIT mode: type X.
PET, VIC, And Commodore 64
Monitors The resident monitor on the PET/CBM computer
is the simplest of monitors. You enter it from BASIC by typing SYS 4
when no program is RUNning. This lands on a BReaK instruction;
address 4 always contains a zero which is the opcode for BRK. You
are then in monitor mode. Original ROM PETs, the earliest models, do
not have a monitor in ROM, but one is available on tape, called TIM.
Everything is done with hexadecimal numbers.
There are only six monitor commands: 1.
Go (RUN) : type G 2000 and the program starts at address 2000. It
will continue until it lands on a BRK instruction. There is no key
you can type to stop it. 2. LOAD (from tape
or disk) : type L "0:NAME",08 and a program called "name" on disk
drive zero will be loaded at the address from which it was SAVEd.
There is no provision to allow you to LOAD to a different address. L
"NAME",01 will LOAD from tape. 3. SAVE (to a
tape or disk): type S -0: NAME", 08,2000,2009 and the bytes between
hex 2000 and 2008 will be saved to disk drive zero and called
"name." Important note: you should always be aware that a SAVE will
not save the highest byte listed in your SAVE instruction. You
always specify one byte more than you want to save. In our example
here, we typed 2009 as our top address, but the monitor SAVEd only
up to 2008. S "NAME",01,2000,2009 will SAVE to tape.
An interesting trick is to save the picture on your
screen. Try this from the monitor (for a disk drive) : S "0:
SCREEN", 08,8000,8400 (with a tape drive: S "SCREEN",01,8000,8400).
Then, clear the screen and type: L "0:SCREEN",08 (tape: L
"SCREEN",01). This illustrates that an ML SAVE or LOAD just takes
bytes from within whatever range of memory you specify; it doesn't
care what those bytes contain or if they make ML sense as a
program. 4. See memory (memory dump): type M
2000 2009 and the bytes between these addresses will be displayed on
screen. To change them, you use the PET cursor controls to move to
one of these hex numbers and type over it. Hitting the RETURN key
makes the change in the computer's memory (the same way you would
change a line in BASIC).
Machine Language
Registers 5. See the registers:
type R and you will see something like this on screen (the
particular numbers in each category will depend on what's going on
in your computer whenever you type R):
PC IRQ SR AC XR YR SP 2000 E62E 30
00 05 FF FE
The PC is the
program counter: above, it means that the next instruction the
computer would perform is found at address 2000. If you typed G (for
RUN), this is where it would start executing. The IRQ is the
interrupt request. The SR is the status register (the condition of
the flags). The AC is the accumulator, the XR and YR are the X and Y
registers. The SP is the stack pointer. We'll get into all this
later. 6. Exit to BASIC: type X.
That's it. Obviously, you will want to add trace, step,
transfer, disassemble, and other useful monitor aids. Fortunately,
they are available. Two programs, Supermon and Micromon, can be
LOADed into your Commodore computer and will automatically attach
themselves to your "resident" monitor. That is, when you're in the
monitor mode, you can type additional monitor commands.
Both Micromon and Supermon are widely available through
user groups (they are in the public domain, available to everyone
for free). If there is no user group nearby, you can type them in
yourself. Supermon appeared in COMPUTE! Magazine, December 1981,
Issue #19, on page 134. Micromon appeared in COMPUTE!, January 1982,
Issue #20, page 160. A Micromon for VIC can be found in COMPUTE!,
November 1982. Because of their value, particularly when you are
debugging or analyzing ML programs, you will want to add them to
your program library. Several of these monitor extensions can be
found in Appendix F.
Using The
Monitors You will make mistakes. Monitors are for
checking and fixing ML programs. ML is an exacting programming
process, and causing bugs is as unavoidable as mistyping when
writing a letter. It will happen, be sure, and the only thing for it
is to go back and try to locate and fix the slip-up. It is said that
every Persian rug is made with a deliberate mistake somewhere in its
pattern. The purpose of this is to show that only Allah is perfect.
This isn't our motivation when causing bugs in an ML program, but
we'll cause them nonetheless. The best you can do is try to get rid
of them when they appear. Probably the most
effective tactic, especially when you are just starting out with ML,
is to write very short sub-programs (subroutines). Because they are
short, you can more easily check each one to make sure that it is
functioning the way it should. Let's assume that you want to write
an ML subroutine to ask a question on the screen. (This is often
called a prompt since it prompts the user to do
something.) The message can be: "press any
key." First, we'll have to store the message in a data table. We'll
put it at hex $1500. That's as good a place as anywhere else.
Remember that your computer may be using a different screen RAM POKE
code to display these letters. POKE the letter "A" into your screen
RAM to see what number represents the start of your screen alphabet
and use those numbers for any direct-to-screen messages in this
book.
ASCII
|
ATARI
|
1500 80 P
|
48
|
1501 82 R
|
50
|
1502 69 E
|
37
|
1503 83 S
|
51
|
1504 83 S
|
51
|
1505 32
|
0
|
1506 65 A
|
33
|
1507 78 N
|
46
|
1508 89 Y
|
57
|
1509 32
|
0
|
150A 75 K
|
43
|
150B 69 E
|
37
|
150C 89 Y
|
57
|
150D 00
|
255
(the delimiter, the signal that the message is finished. Atari
must use something beside zero which is used to represent the
space character.)
|
We'll put the subroutine at $1000, but be warned! This
subroutine will not work as printed. There are two errors in this
program. See if you can spot them:
1000
LDY #$00 1002 LDA $1500,Y 1005 CMP $00
(is it the delimiter?) 1007 BNE
$100A (if not, continue
on) 1009 RTS
(it was zero, so quit and return to whatever JSRed,
or called, this subroutine) 100A STA
$8000,Y (for PET) 100D
INY 100E JMP $1000 (always JMP back
to $1000)
Make the following substitutions if you use one of
these machines:
Atari: 1005 CMP $FF
(That's hex for 255.) Atari: 100A STA
($88),Y Apple: 100A STA $0400,Y
Since we haven't yet gone into addressing or instructions
much, this is like learning to swim by the throw-them-in-the-water
method. See if you can make out some of the meanings of these
instructions anyway. This subroutine will not
work. There are two errors and they are two of the most common bugs
in ML programming. Unfortunately, they are not obvious bugs. An
obvious bug would be mistyping: LIDS when you mean LDA. That sort of
bug would be caught by your assembler, and it would print an error
message to let you know that no such instruction as LIDS exists in
6502 ML. The bugs in this routine are
mistakes in logic. If you disassemble this, it will also look fine
to the disassembler, and no error messages will be printed there
either. But, it will not work the way you wanted it to. Before
reading on, see if you can spot the two errors. Also see if you can
figure out how this routine would execute its instructions. Where
does the computer go after the first pass through this code? When
and how does it finish the job?
Two Common
Errors A very common bug, perhaps the most common ML
bug, is caused by accidentally using zero page addressing when you
mean to use immediate addressing. We mentioned this before,
but it is the cause of so much puzzlement to the beginning ML
programmer that we'll go over it several times in this book. Zero
page addressing looks very similar to immediate addressing. Zero
page means that you are addressing one of the cells in the first 256
addresses. A page of memory is 256 bytes. The lowest page is called
zero page and is the RAM cells from number zero through 255. Page
one is from 256-511 (this is the location of the "stack" which we'll
get to later). Addresses 512-767 are page three and so on up to the
top memory, page 255. Immediate
addressing means that the number is right within the ML code,
that it's the number which follows (which is the operand or the
argument of) an instruction. LDA #13 is immediate. It puts the
number 13 into the accumulator. LDA $13 is zero page and puts
whatever number is in address 13 into the accumulator. It's easy and
very common to mix up these two, so you might look at these
instructions first when debugging a faulty program. See that all
your zero page addressing is supposed to be zero page and that all
your immediate addressing is supposed to be immediate.
In the prompt example above, the LDY #00 is correct -
we do want to set the Y register counter to zero to begin printing
the message. So we want an immediate, the actual number zero. Take a
good look, however, at the instruction at location $1005. Here we
are not asking the computer to compare the number in the accumulator
to zero. Instead, we are asking the computer to compare it to
whatever might be in address zero - with unpredictable results. To
fix this bug, the instruction should be changed to the immediate
addressing mode with CMP # 0. The second bug
is also a very common one. The subroutine, as written, can never
leave itself. It is an endless loop. Loop structures are usually
preceded by a short initialization phase. The counters have to be
set up before the loop can begin. Just as in BASIC, where FOR I =1
TO 10 tells the loop to cycle ten times, in ML, we set the Y
register to zero to let it act as our counter. It kills two birds
with one stone in this subroutine. It is the offset (a pointer to
the current position in a list or series) to load from the message
in the data table and the offset to print to the screen. Without Y
going up one (INY) each time through the loop, we would always print
the first letter of the message, and always in the first position on
the screen. What's the problem? It's that JMP
instruction at $100E. It sends us back to the LDY # 0 address at
1000. We should be looping back to address 1002. As things stand,
the Y register will always be reset to zero, and there will never be
any chance to pick up the delimiter and exit the subroutine. An
endless cycle of loading the "P" and printing it will occur. Y will
never get beyond zero because each loop jumps back to 1000 and puts
a zero back into Y. To see this, here's the same bug in
BASIC:
10 T=5 20 T=T+1 30 IF
T=10 THEN 50 40 GOTO 10
Tracking Them
Down The monitor will let you discover these and other
errors. You can replace an instruction with zero (BRK) and see what
happens when you execute the program up to the BRK. Better yet, you
can single step through the program and see that, for example, you
are not really computing CMP #00 where you thought you were. It
would also be easy to see that the Y register is being reset to zero
each time through the loop. You are expecting to use it as a counter
and it's not cooperating, it's not counting up each time through the
loop. These and other errors are, if not obvious, at least
discoverable from the monitor. Also, the
disassembler function of the monitor will permit you to study the
program and look, deliberately, for correct use of #00 and $00.
Since that mix-up between immediate and zero page addressing is so
common an error, always check for it first.
Programming
Tools The single most significant quality of monitors
which contributes to easing the ML programmer's job is that
monitors, like BASIC, are interactive. This means that you can make
changes and test them right away, right then. In BASIC, you can find
an error in line 120, make the correction, and RUN a test
immediately. It's not always that easy to
locate and fix bugs in ML: there are few, if any, error messages, so
finding the location of a bug can be difficult. But a monitor does
allow interactivity: you make changes and test them on the spot.
This is one of the drawbacks of complex assemblers, especially those
which have several steps between the writing of the source code and
the final assembly of executable object code (ML which can be
executed). These assemblers often require
several steps between writing an ML program and being able to test
it. There are linkers, relocatable loaders, double-pass assembly,
etc. All of these functions make it easier to rearrange ML
subroutines, put them anywhere in memory without modification, etc.
They make ML more modular (composed of small, self-sufficient
modules or subroutines), but they also make it less interactive. You
cannot easily make a change and see the effects at once.
However, using a mini-assembler or the Simple
Assembler, you are right near the monitor level and fixes can easily
and quickly be tested. In other words, the simpler assemblers
sometimes gain in efficiency what they lose in flexibility. The
simpler assemblers support a style of programming which involves
less pre-planning, less forethought, less abstract analysis. If
something goes awry, you can just try something else until it all
works.
Plan
Ahead Or Plunge In? Some find such trial and error
programming uncomfortable, even disgraceful. The more complicated
assemblers discourage interactivity and expect careful preliminary
planning, flowcharts, even writing out the program ahead of time on
paper and debugging it there. In one sense, these large assemblers
are a holdover from the early years of computing when computer time
was extremely expensive. There was a clear advantage to coming to
the terminal as prepared as possible. Interactivity was costly. But,
like the increasingly outdated advice urging programmers to worry
about saving computer memory space, it seems that strategies
designed to conserve computer time are anachronistic. You can spend
all the time you want on your personal computer.
Complex assemblers tend to downgrade the importance of a
monitor, to reduce its function in the assembly process. Some
programmers who've worked on IBM computers for 20 years do not use
the word monitor in the sense we are using it. To them, monitors are
CRT screens. The deluxe assembler on the SuperPet, for example, does
have a monitor, but it has no single-step function and has no
provision for SAVEing an ML program to disk or tape from the
monitor. Whether or not you are satisfied
with the interactive style of simple, mini-assemblers and their
greater reliance on the monitor mode and on trial and error
programming is your decision. If you want to graduate to the more
complicated assemblers, to move closer to high-level languages with
labels and relocatable code, fine. The Atari assembler is fairly
high-level already, but it does contain a full-featured monitor, the
"debugger," as well. The choice is ultimately a matter of personal
style. Some programmers are uncomfortable
unless they have a fairly complete plan before they even get to the
computer keyboard. Others are quickly bored by elaborate
flowcharting, "dry computing" on paper, and can't wait to get on the
computer and see-what-happens-if. Perhaps a good analogy can be
found in the various ways that people make telephone calls. When
long-distance calls were extremely expensive, many people made lists
of what they wanted to say and carefully planned the call before
dialing. They would also watch the clock during the call. (Some
still do this today.) As the costs of phoning came down, most people
found that spontaneous conversation was more satisfying. It's up to
you. Computer time, though, is now extremely
cheap. If your computer uses 100 watts and your electric company
charges five cents per KWH, leaving the computer on continuously
costs about 12 cents a day.
Return to Table
of Contents | Previous
Chapter | Next
Chapter |
| |
|