How to Use LADS
Here is a step-by-step explanation of how to assemble machine language programs using the LADS assembler. As you familiarize yourself with its features and practice using it, you will likely discover things about the assembler which you'll want to change or features you'll want to add. For example, if you find yourself frequently using an impossible addressing mode like LDY (15,Y), you might want to insert an error trap for that into LADS source code. Chapter 11, "Modifying LADS," shows you how these customizations can be accomplished. But here is a description of the features which are built into LADS.
Apple and Atari Versions
For the most part, the commands and features of LADS are the same for all versions: Apple, Atari, and Commodore. A few differences are discussed at the end of the general instructions for all versions of LADS. No matter which computer you use, you should read the body of this chapter to understand how to get the most out of LADS. Then, if you use an Atari or an Apple, you can read the special notes at the end of this appendix which explain some minor variations applicable to those computers.
General Instructions for Using LADS
LADS assembles from source files. They are particularly easy and convenient to create; just turn on your computer and pretend you're writing a BASIC program. (To create source files for the Atari, see "Special Atari Notes" below.) Commodore and Apple LADS work with source files created exactly the way you would write a BASIC program. Here's an example:
10 * = $0360
15 .S
20 LDA #22:LDY #0
30 STA $1500,Y
40 END TEST
Use line numbers, colons, and whatever programmer's aids (Toolkit, BASIC Aid, POWER, automatic line numbering, etc.) you ordinarily use to write BASIC itself.
After you've typed in a program, save to disk in the normal way. (Tape drive users: See special "Note to Tape Users" at the end of this appendix.) Notice line 10 in the example above. The first line of any LADS source file must provide the starting address, the address where you want the ML program to begin in the computer's memory. You signify this with the *= symbol, which means "program counter equals." When LADS sees *=, it sets the Program Counter to the number following the equals sign. Remember that there must be a space between the = and the starting address.
The last line of each LADS source file must contain either the END pseudo-op or the FILE pseudo-op. Both of them link source files together in case you want to chain several files into one large ML program. However, FILE names the next linked source file in the chain whereas END always specifies the first source file of the chain. If there is only one file (as in our example above), you still must end it with END and give its name as the first file. More about this shortly.
Also notice that you can use either decimal or hexadecimal numbers interchangeably in LADS. Lines 10 and 30 contain hex; line 20 has decimal numbers.
After you've saved the source code to disk, you can assemble it by loading LADS and then typing the name of the source file in the upper left-hand corner of the screen. (The Atari version differs here as well.) Let's go through the process step by step. Type in the little source program above as if you were writing a BASIC program. SAVE it by typing:
SAVE "TEST",8
Then LOAD "LADS",8,1
Type NEW
Clear the screen and type in the source file's name in the upper left-hand corner:
TEST
Then cursor down a line or two and type SYS 11000 and hit the RETURN key. That will activate LADS on the Commodore 64, VIC-20, and 8032 PET/CBM. See the special notes below for using the Atari and Apple versions of LADS.
You will see the assembler create the object code, the bytes which go into memory and comprise the ML program.
Note: Be sure to remember that every source code program must end with the .END NAME pseudo-op. In our example, we concluded with .END TEST because TEST is the name of the only file in this source code. Also notice that you do not use quotes with these filenames.
To review: Every source code program must contain the starting address in the first line (for example, 10 *= $0800) and must list the filename on the last line (for example, 500 .END SCREENPROG). If you chain several source code programs together using the FILE pseudo-op, you end only the final program in the chain with the END pseudo-op. These two rules will become clearer in a minute when we discuss the .END and .FILE pseudo-ops.
Features
There are a number of pseudo-ops (direct instructions to the assembler) available in LADS. The .S in line 15 is such an instruction. It tells LADS to print the results of an assembly to the screen. If you add the following lines to our test program, you will cause the listing to be in decimal instead of hex and cause LADS to save the object code (the runnable ML program) to a disk file called T.OBJ.
10 * = $0360
11 .NH
12 .D T.OBJ
20 LDA #22:LDY #0
30 STA $1500,Y
40 .END TEST
The pseudo-op .NH means no hex (causing the listing to change from hex to decimal), and .D means create a disk file containing the ML program which results from the assembly process.
You can add REM-like comments by using a semicolon. And you can turn the screen listing off with .NS, anytime. Turn it on or off as much as you want:
10 * = $0360
11 .NH
12 .D T.OBJECTPROGRAM
15 .NS
20 LDA #22:LDY #0; load A with 22, load Y with zero
30 STA $1500,Y
40 .END TEST
You turn on printer listings with .P and turn them off with .NP. However, for the .P pseudo-op to work, the .S screen listings pseudo-op must also be turned on. In other words, you cannot have listings sent to the printer without also having them listed on the screen at the same time. To have the ML stored into memory during assembly, use .O and turn off these POKES to memory with .NO.
The pseudo-ops which turn the printer on and off; direct object code to disk, screen, and RAM; or switch between hex or decimal printout can be switched on and off within your source code wherever convenient. For example, you can turn on your printer anywhere within the program by inserting P and turn it off anywhere with .NP. Among other things, this would allow you to specify that only a particular section of a large program be printed out. This can come in very handy if you're working on a 5000-byte program: you would have a long wait if you had to print out the whole thing.
Always put pseudo-ops on a line by themselves. Any other programming code can be put on a line in any fashion (divided by colons: LDA 15:STA 27:INY), but pseudo-ops should be the only thing on their lines. (The BYTE pseudo-op is an exception-it can be on a multiple-statement line.)
100 .P .S (wrong)
100 .P (right)
110 .S (right)
Here's a summary of the commands you can give LADS:
.P |
Turn on printer listing of object code (.S must be
activated). |
.NP |
Turn off printer listing of object code. |
.O |
Turn on POKES to memory. Object code is stored into
RAM during assembly. |
.NO |
Turn off POKES to memory. |
.D filename |
Open a file and store object code to disk during
assembly (use no quotes around filename). |
.FILE filename |
Link one source file to the next in a chain so that
they will all assemble together as a single large source program (end the
chain with END pseudo-op). |
.END filename |
Link the last source file to first source file in
a chain. If you are assembling from a single file, give its filename as the
END so the assembler knows where to go for the second pass. Any source code
must have END as the last line in the program, whether the source code is
contained within a single disk file or spread across a multiple-file chain. |
.S |
Turn on screen listing during assembly (required
if you desire a hardcopy listing from a printer using the P pseudo-op). |
.NS |
Turn off screen listing during assembly. |
.H |
Turn on hexadecimal output for screen or printer
listing. |
.NH |
Turn off hexadecimal output for screen or printer
listing. (As a result, the listings are in decimal.) |
* = |
Set program counter to new address. |
A Stable Buffer
The pseudo-op *= is mainly useful when you want to create data tables. The subprogram Tables in LADS source code is an example. (A subprogram is one of the source code files which, when linked together, form an entire ML program.) You might want to create an ML program and locate its tables, equates, buffers, and messages at the high end of the ML program the way LADS does with its Tables subprogram. Since you don't know what the highest RAM address will be while you're writing the program, you can set *= to some address perhaps 4K above the starting address. This gives you space to write the program below the tables. The advantage of stable tables is that you can easily PEEK them and this greatly assists debugging. You'll always know exactly where buffers and variables are going to end up in memory after an assembly-regardless of the changes you make in the program.
Here's an example. Suppose you write:
10 *= $5000
20 STA BUFFER
30 * = $6000
40 BUFFER.BYTE 00000000000000
50 .END BUFFEREXAMPLE
This creates an ML instruction (STA buffer) at address $5000 (the starting address of this particular ML program), but places the buffer itself at $6000. When you add additional instructions after STA buffer, the location of the buffer itself will remain at address $6000. This means that you can write an entire program without having to worry that the location of the buffer is changing each time you add new instructions, new code. It's high enough so that it remains stable at $6000, and you can debug the program more easily. You can always check if something is being correctly sent into the buffer by just looking at $6000.
This fragment of code illustrates two other features of LADS. You can use the pseudo-op BYTE to set aside some space in memory (the zeros above just make space to hold other things in a "buffer" during the execution of an ML program). You can also use BYTE to define specific numbers in memory:
.BYTE 65 66 67 68
This would put these numbers (you must always use decimal numbers with this pseudo-op) into memory at the location of the BYTE instruction. An easy way to create messages that you want to print to the screen is to use the BYTE pseudo-op with quotes:
500 FIRSTLETTERS BYTE "ABCD":.BYTE 0
Then, if you wanted to print this message, you could write:
2 * = $0360
5 LDY #0
10 LOOP LDA FIRSTLETTERS,Y
20 BEQ ENDMESSAGE
30 STA $0400,Y; location of screen RAM on Commodore 64
40 INY
50 JMP LOOP
60 ENDMESSAGE RTS; finished printout
500 FIRSTLETTERS BYTE "ABCD:.BYTE 0
900 .END MESSAGETEST
Note that using the second set of quotes is optional with the .BYTE pseudo-op: You can use either .BYTE "ABCD:.BYTE 0 or.BYTE "ABCD":.BYTE 0. To POKE numbers instead of characters, just leave out the quotes: .BYTE 10 15 75. And since these numeric values are being POKEd directly into bytes in memory, they cannot be larger than 255.
Labels
With LADS, or with other assemblers that permit labels, you need not refer to locations in memory or numeric values by using numbers. You can use labels.
In the example above, line 10 starts off with the word LOOP. This means that you can use the word LOOP later on to refer to that location (see line 50). That's quite a convenience: The assembler remembers where the word LOOP is used and you need not refer to an actual memory address; you can refer to the label instead. Throughout this book, this kind of label is called a PC-type (for Program Counter) or address-type label.
The other type of label is defined is with an assembly convention called an equate (an equals sign). This is quite similar to the way that BASIC allows you to assign value to words-it's called "assigning variables" when you do it in BASIC. In ML, the = pseudo-op works pretty much the way the = sign does in BASIC. Here's an example:
5 "= $0360
10 SCREEN = $0400; the location of the 1st byte in RAM of the 64 screen
20 HEARTSYMBOL = 83, the heart figure
30; -----------------------
40 START LDA HEARTSYMBOL; notice "START" (an addresstype label)
50 STA SCREEN
60 RTS
Line 10 assigns the number $0400 (1024 decimal) to the word SCREEN. Anytime thereafter that you use the word SCREEN, LADS will substitute $0400 when it assembles your ML program. Line 20 "equates" the word HEARTSYMBOL to the number 83. So, when you LDA HEARTSYMBOL in line 40, the assembler will put an 83 into your program. (Notice that, like BASIC, LADS requires that equate labels be a single word. You couldn't use HEART SYMBOL, since that's two words.)
Line 30 is just a REMark. The semicolon tells the assembler that what follows on that line is to be ignored. Nevertheless, blank lines or graphic dividers like line 30 can help to visually separate subroutines, tables, and equates from your actual ML program. In this case, we've used line 30 to separate the section of the program which defines labels (lines 1020) from the program proper (lines 40-60). All this makes it easier to read and understand your source code later.
Automatic Math
There are times when you will want to have LADS do addition for you. That's where the + pseudo-op comes in. If you write "label+1" you will add 1 to the value of the label. Here's how it works:
10 * = 864
20 MEMTOP = $34; top-of-memory pointer for 8032 PET.
30; -----------------------------
40 LDA #0:STA MEMTOP:LDA #$50:STA MEMTOP+1
Here we are putting a new location into the top-of-memory pointer which the computer uses to decide where it can store things. (Doing that could protect an ML program which resides above the address stored in this pointer.) Like all pointers, it uses two bytes. If we want to store $5000 into this pointer, we store the lower half (the least significant byte) into MEMTOP. We'll want to put the number $50 into the most significant byte of the pointer-but we don't want to waste time making a new label. It's just one higher in memory than MEMTOP. Hence, MEMTOP+1.
You'll also want to use the + pseudo-op command in constructions like this:
10 * = 864
15 SCREEN = $0400
17; ----------------------------
20 LDA #32; the blank character
30 LDA #0
40 START STA SCREEN,Y
50 STA SCREEN+256,Y
60 STA SCREEN+512,Y
70 STA SCREEN+768,Y
80 INY
90 BNE START
This is the fastest way to fill memory with a given byte. In this case we're clearing out the screen RAM by filling it with blanks. But it's easy to indicate multiples of 256 by just adding them to the label SCREEN.
A similar pseudo-op command is the #<. This refers to the least significant byte of a label. For example:
10 * = $0360
20 SCREEN = $8011
25 SCREENPOINTER = $FB
30 ;--------------------
40 LDA #<SCREEN; LSB (least significant byte of the label SCREEN, $11)
50 STA SCREENPOINTER
You'll find this technique used several times in the LADS source code. It puts the LSB (least signficant byte) or the MSB (most signficant byte) of a label into the LSB or MSB of a pointer. In the example above, we want to set up a pointer that will hold the address of the screen RAM. The pointer is called SCREENPOINTER and we want to put $11 (the LSB of SCREEN) into SCREENPOINTER. So, we extract the LSB of SCREEN in line 40 by using # combined with the less-than symbol. We would complete the job with the greater-than symbol to fetch the MSB: 60 LDA #>SCREEN. Notice that these symbols must be attached to the label; no space is allowed. For example, LDA #> SCREEN would create problems. This LSB or MSB extraction from a label is something you'll need to do from time to time. The #< and #> pseudo-ops do it for you.
Chained Files
It is sometimes convenient to create several source code subprograms, to break the ML program source code into several pieces. LADS source code is divided into a number of program files: Array, Equate, Math, Pseudo, etc. This way, you don't need to load the entire source code in the computer's memory when you just want to work on a particular part of it. It also allows you to assemble source code far larger than could fit into available RAM.
In the last line of each subprogram you want to link, you put the linking pseudo-op .FILE NAME (use no quotes) to tell the assembler which subprogram to assemble next. Subprograms, chained together in this fashion, will be treated as if they were one large program. The final subprogram in the chain ends with the special pseudo-op .END NAME, and this time the name is the filename of the first of the subprograms, the subprogram which begins the chain. It's like stringing pearls and then, at the end, tying thread so that the last pearl is next to the first, to form a necklace.
Remember that you always need to include the .END pseudo-op, even if you are assembling from a single, unlinked source code file. In such a case (where you're working with a solo file), you don't need the linking .FILE pseudo-op. Instead, refer the file to itself with .END NAME where you list the solo file's name. Here's an illustration of how three subprograms would be linked to form a complete program:
5 * = 864
10; "FIRST"--first program in chain
20;its first line must contain the start address
30;----------
40 LDA #20
50 STA $0400
60 .FILE SECOND
Then you save this subprogram to disk (it's handy to let the first remark line in each subprogram identify the subprogram's filename):
SAVE "FIRST",8
Next you create SECOND, the next link in the chain. But here, you use no starting address; you enter no *= since only one start address is needed for any program:
10; "SECOND"
20 INY:INX:DEY:DEX
30 .FILE THIRD
SAVE"SECOND",8
Now write the final subprogram, ending it with the clasp pseudo-op .END NAME which links this last subprogram to the first:
10 ; "THIRD"
20 LDA #65:STA $0400
30 .END FIRST
SAVE "THIRD",8
When you want to assemble this chain, just type FIRST in the upper left-hand corner of the screen, SYS to LADS, and it will assemble the entire chain.
If you want the object code (the finished ML program) stored in the computer's memory during the LADS assembly, add this line to FIRST above:
35 .O
If you want to save the object code as an ML program on disk that can be later loaded into the computer and run, add this line to FIRST:
36 .D PROGRAMNAME
When LADS is finished assembling, there will be an ML program on disk called PROGRAMNAME. You can load it and SYS 864 (that was the start address we gave this program), and the newly assembled ML program will execute.
One additional pseudo-op is the #". It is sometimes useful when you want to load the Accumulator with a particular ASCII character and don't offhand recall the numerical value. The letter A is 65 in the ASCII code. If you LDA #65:STA SCREEN, you would store the letter A to the screen. But, for convenience, you can LDA #"A:STA SCREEN. You can, in other words, use the #" followed by the character itself rather than by its ASCII code number.
Rules for LADS
Here are the rules you need to follow when writing ML for LADS to assemble:
1. In general, all equate labels (labels using an equals sign) should be defined at the start of your program. While this isn't absolutely necessary for labels with numbers above 255 (see SCREEN in the example below), it is the best programming practice. It makes it easier for you to modify your programs and simplifies debugging. LADS itself locates all its equate labels in the subprogram Defs, the first subprogram in its chain of source code files.
What's more, it is necessary that any equate label with a value lower than 256 be defined before any ML mnemonics reference that label. So, to be on the safe side, just get into the habit of putting all equate labels at the very start of your programs:
10 * = 864
20 ARRAYPOINTER = $FB; (251 decimal), a zero page address
30 OTHERPOINTER = $FD; (253 decimal), another zero page address
40 ;------------------------
50 MY #0:LDA $41
60 STA ARRAYPOINTER,Y
70 SCREEN = $8000
Notice that it's permissible to define the label SCREEN anywhere in your program. It's not a zero page address. You do have to be careful, however, with zero page addresses (addresses lower than 255). So most ML programmers make it a habit to define all their equates at the start of their source code.
2. Put only one pseudo-op on a line. Don't use a colon to put two pseudo-ops on a single line:
10 * = 864
20 .O:.NH (wrong)
30 .O (right)
40 .NH (right)
The main exception to this is the BYTE pseudo-op. Sometimes it's useful to set up messages with a zero at their end to delimit them, to show that the message is complete. When you delimit messages with a zero, you don't need to know the length of the message; you just branch when you come upon a zero:
10 * = 864
20 SCREEN = $0364
30 ;----------------------
40 LDY #0
50 LOOP LDA MESSAGE,Y:BEQ END; loading a zero signals end of message.
60 STA SCREEN,Y:INY: JMP LOOP; LADS ignores spaces after a colon.
70 ; ---------- message area here ----------
80 MESSAGE .BYTE "PRINT THIS ON SCREEN":.BYTE 0
Any embedded pseudo-ops like + or = or #> can be used on multiple-statement lines. The only pseudo-ops which should be on a line by themselves are the I/O (input/output) instructions which direct communication to disk, screen, or printer, like .P, .S, .D, .END, etc.
Generally, it's important that you space things correctly. If you wrote:
SCREEN= 864
LADS would think that your label was screen= instead of screen. So you need that space between the label and the equals sign. Likewise, you need to put a single space between labels, mnemonics, and arguments:
LOOP LDA MESSAGE
Running them together will confuse LADS:
LOOPLDA MESSAGE
and
LOOP LDAMESSAGE
are wrong.
It's fine to have leading spaces following a colon, however. LADS will ignore those (see line 60 above). Also, spaces within remarks are ignored. In fact, LADS ignores anything following a semicolon (see line 70). However, the semicolon should come after anything you want assembled. You couldn't rearrange line 50 above by putting the BEQ END after the remark message. It would be ignored because it followed the semicolon.
When using the text form of BYTE, it's up to you whether you use a close quote:
50 MESSAGE BYTE "PRINT THIS" (right)
60 MESSAGE BYTE "PRINT THIS (also right)
3. The first character of any label must be a letter, not a number. LADS knows when it comes upon a label because a number starts with a number; a label starts with a letter of the alphabet:
10*=864
20 LABEL = 255
30 LDA LABEL
40 LDA 255
Lines 30 and 40 accomplish the same thing and are correctly written. It would confuse LADS, however, if you wrote:
20 5LABEL = 255 (wrong)
since the number 5 at the start of the word label would signal the assembler that it had come upon a number, not a label. You can use numbers anywhere else in a label name-just don't put a number at the start of the name. Also avoid using symbols like # < > * and other punctuation, shifted letters, or graphics symbols within labels. Stick with ordinary alphanumerics:
10 5LABEL (wrong)
20 LABEL15 (right)
30 *LABEL* (wrong)
4. Move the Program Counter forward, never backward. The * = pseudo-op should be used to make space in memory. If you set the PC below its current address, you would be writing over previously assembled code:
10 * = 864
20 LDA #15
30 * = 900 (right)
10 * = 864
20 LDA #15
30 * = 864 (wrong, you'll assemble right over the LDA #15)
Special Note to Tape Drive Users
LADS will assemble source code from disk or RAM memory. It is possible to use the assembler with a tape drive, using the RAM memory-based version (see Chapter 11). Of course, disk users can also assemble from RAM if they choose. But tape users must.
There is a restriction when using a tape drive as the outboard memory device. You cannot link files together, forming a large, chained source code listing. The reason for this is that LADS, like all sophisticated assemblers, makes two passes through the source code. This means that tape containing the source code would have to be rewound at the end of the first pass.
It would be possible, of course, to have LADS pause at the end of pass 1, announce that it's time to rewind the tape (see Atari notes below), and then, when you press a key, start reading the source code from the start of the tape. But this causes a second problem: The object code cannot then be stored to tape. A tape drive cannot simultaneously read and write.
The best way to use LADS with a tape drive is to assemble from source code in RAM memory and to use the .O (store object code to RAM pseudo-op). Then, when the finished object code is in RAM, use a monitor program like "Tinymon" or "Micromon" to save it to tape. If you have access to a disk drive, you could construct a version of LADS which automatically directs object code to tape during assembly using the D pseudo-op.
Special Atari Notes
The Atari version of LADs is a complete programming environment. Unlike the Commodore and Apple versions of LADS, where you use the BASIC program editor to write and edit your source code, the Atari version has a special editor integrated into LADS itself. This is necessary because with Atari BASIC, you can only enter BASIC instructions. The line
10 * = $0600
is just as illegal as
10 PRIMT "NAME":INPPUT A#
Both are coolly received with an error message. This syntax checking is fine when working with BASIC, but prevents the standard BASIC editor from accepting and storing LADS source code. Once the decision was made to create an entirely new source code editor, LADS became a self-contained package. The BASIC cartridge is neither needed nor especially desired. Since LADS takes over the Atari, DOS is the only other program in memory, freeing up all the RAM ordinarily used by BASIC.
One note: If you'd rather use a word processor or other text editor to enter and edit your source code, you can, as long as your editor will send out numbered statements, in ASCII, ending with 155's (ATASCII carriage returns). Most Atari word processors conform to this; it you're not sure, experiment with a short source code program. Be sure to end each source line with a carriage return. You can then load the file into the LADS editor or assemble directly from disk with the LADS D:filename command.
Entering LADS
The object code for Atari LADS is typed in with the Atari version of MLX, a machine language entry editor. See Appendix C for details. After you've typed it in, you can save LADS to disk under the filename AUTORUN.SYS. This will cause LADS to load and automatically run when you turn on (boot) your computer and disk drive. LADS as assembled requires at least 40K of memory. If you have access to a 40K Atari, you can reassemble the source code to almost any memory location you want (see "Programming Atari LADS" in Chapter 11).
If you didn't save LADS as AUTORUN.SYS, you need to load it from the DOS menu, then use menu selection M and run it at address 8000. If you bought the LADS source/object code disk, LADS will automatically load and run when you insert the disk and turn on your system. LADS will then print its prompt, "LADS Ready." This indicates that LADS is ready to receive commands or source code.
Using the Editor
You enter your ML source code just as you do in BASIC. To start a new line, type a line number, then the text, followed by the RETURN key. To delete a line, type the line number by itself, then press RETURN. To insert a line between two existing lines, just give it a line number that falls between the two. For example, line 105 will end up between line 100 and 110.
The editor assumes that a line beginning with a line number should be stored as part of your source code. If your line starts with leading zeros, these leading zeros will be erased. As the editor reads the line you've entered, it converts lowercase to uppercase, and inverse video characters to normal ones. It will not convert characters within double quotes (SHIFT-2) or after a semicolon, which marks the start of a comment. This line:
0100 lda #"a":jmp ($fffc); FFFC is the reset vector
would become:
100 LDA #"a":JMP ($FFFC); FFFC is the reset vector
If there is no line number, the editor assumes you've entered an editor command. Note that if a command has any parameters after it, the command must be followed by a space.
Atari Editor Commands
LIST
LIST all by itself displays the entire source program. LIST 150 lists just line 150. LIST 110-160 shows all the lines between and including lines 110 through 160. If you want to list from a certain line number to the end of your program, just make the second line number very large, as in LIST 2000,9999. If you want to send a listing to the printer, use the SAVE command.
SAVE device:filename
SAVE works just like LIST, but sends the listing to the specified device with the given filename. To list the entire source code to the printer, use SAVE P:. Be sure to put a space between the command and the device. To LIST to cassette, use SAVE C:. When using disk, remember to use D:, for example, SAVE D:DEFS.SRC. We recommend that you do use an extender, such as .SCR (see .FILE below). Check the DOS manual for examples of legal filenames. You can also save a portion of the program. SAVE P:,100,150 would list lines 100 to 150 to the printer.
LOAD device:filename
Load will replace any source code in memory with that read from the specified device. LOAD C: reads from tape, LOAD D:DEFS.SRC or LOAD D2:INDISK.SRC from disk.
MERGE device:filename
Merge is used to combine two programs. MERGE works just like ENTER does in BASIC. Instead of the keyboard being used to accept text, the editor looks to the file for input. After all the lines have been entered, the editor restores keyboard control. MERGE does not just append one program to the other. If there is a line 150 in the program to be merged, it will replace line 150 in memory. Therefore, MERGE can replace selected lines, or add lines to the top or bottom of a program in memory. You can use SAVE to list to disk a part of a program, then use MERGE to add it to another program. You can have a whole disk full of commonly used routines, then use MERGE to combine the routines you need, speeding up the development of large ML programs.
DOS
If used with standard Atari DOS 2.0S, this command will load and run DUP.SYS, the DOS menu. Remember that DUP.SYS will erase any program in memory if MEM.SAV is not used. Now you can manipulate files and display the disk directory. The DOS command makes an indirect jump through the DOS vector, location $0A.
SYS address
Transfers control with a JSR to the decimal address following the SYS. Always put a space between SYS and the address. If the routine ends with a RTS, control will return to the LADS editor. If a BRK ($00) is encountered, the editor will also be reentered through the breakpoint, and the address where the BRK was found will be displayed.
LADS (optional device: filename)
Transfers control to the assembler. Although the editor merely manipulates text source code, it's as if all of LADS was just another editor command. When LADS takes control, the left margin is set to 0, to give a full 40-column width for printout. The left margin reverts to 2 when the editor is reentered. If you give the filename, as in LADS D:DEFS.SRC, then LADS will assemble the given source code from disk. This is like Commodore LADS' default-assembling from disk. If you leave off the filename, LADS will behave as a RAM-based assembler, reading the current source code in memory and assembling it. Unlike Commodore or Apple LADS, where you change the source code and reassemble a separate version of LADS dedicated to RAM-based assembly, Atari LADS features both disk assembly and memory assembly in the same program, executing the appropriate code by checking RAMFLAG. For more information on this, see "Notes on the Structure of Atari LADS" in Chapter 11.
After an assembly is complete, or if you halt assembly by hitting the BREAK key, control will return to the editor.
Error Handling
Within the editor, any error will be displayed with Error - and the error number. This may be Error - 170 for file not found when you try to load a nonexistent file from the editor, or it may be an error returned from the assembler. Use your DOS or BASIC manual for a list of error numbers and error messages. Any illegal command or a command the editor can't understand will result in a Syntax Error.
Special Notes for Cassette Users
The filename for the cassette is C:. It is possible to assemble from cassette. When you see the END, and hear the single tone, rewind the tape, press play, and then press any key to start the second pass. If you're using linked files, each file must link to the next with .FILE C:. The last source file should end with END C:. Assembling from tape is a cumbersome affair in any case. It might be preferable for tape drive users to keep all source code in memory, then assemble to memory, using the cassette only to store and retrieve source code.
Pseudo-ops
All the pseudo-ops described above for the Commodore and Apple versions are fully operative in Atari LADS. A few usage notes follow:
.O This causes the assembler to POKE the object code into memory. Its converse is .NO. You must not overwrite the assembler, which uses memory from $8000 to approximately $9FFF. During assembly, the labels are stored below $8000, descending towards $7000. Only a very long program will need memory between $7000 and $8000 when it is assembled. Also avoid overwriting your source code, which starts at $2000 and works its way up.
A good location for very small routines is in page 6, $0600-$06FF. During assembly, all of page 5 will be corrupted. You can store your object code fairly safely at $5000 or $6000, assuming your source code in memory is not too long. You can break your source code into modules, which will link together with .FILE and END (see below). If you remove all cartridges (or hold down OPTION when you turn on your machine, which removes BASIC on a 600XL or 800XL), there will be unused memory from $A000 to about $AFFF, less screen memory usage.
An alternative to .O is the .D pseudo-op, which stores the object code to disk. This entirely avoids any memory constraints. You can go to DOS and load the object code, then use the M. RUN AT ADDRESS option to execute and test it.
.D If storing object code to disk, be sure to use the D:, as in .D D:LADS.OBJ. Storing object code to tape is risky, since an excessively long leader may be written. Besides, there is no facility for loading cassette object files without a BASIC loader program. After the assembly is complete, you can go to the DOS menu and use menu selection L to load your program, then selection M to run it. Menu selection M. RUN AT ADDRESS requires a hexadecimal number without the dollar sign.
.P This assumes an 80-column printer. Remember to use it with S if you want the assembly listing to also go to the printer. If the printer is not turned on, assembly will abort and you will be returned to the editor with an Error - 138.
.FILE Be sure to follow .FILE (or simply F) with a space, then D:, followed by the filename. You may get occasional errors if you don't use an extender. It is recommended that you add the extender.SRC, as in VALDEC.SRC (SRC for SouRCe). For example, .FILE D:EVAL.SRC
.END Use this only at the end of the last file in a linked chain of source code. You can abbreviate it to E. An example of proper usage is .END D:DEFS.SRC
Programming Aids
Following are two utility programs, written in BASIC. Program A-1 will renumber an Atari LADS source program. Just run it and follow the prompts. Program A-2 partially converts a file from the Assembler Editor, EASMD, or MAC/65 assembler to the LADS syntax. It removes leading spaces after a line number, trailing spaces at the end of a line, and tucks comments right next to the operand fields. Into the DATA statements starting at 500, insert the filenames of the files you want converted. Be sure to make END the last item in the DATA statements. To use LADS to assemble code written for one of these other assemblers, you must complete the conversion yourself by adjusting the pseudo-ops. See the descriptions of the LADS pseudo-ops at the start of this appendix.
Program A-1. Atari LADS Renumber Utility
10 GRAPHICS 0:? "Renumber LADS":? --------
-------"
20 DIM T$(20),F$(20),F2$(20),A$(120)
30 ? "Enter filename. Do not use D:":INPUT T
$:F$="D:":F$(3)=T$
40 F2$="D:TEMP,":F2$(LEN(F2$)+1)=T$
50 TRAP 500:OPEN #1,4,0,F$:TRAP 40000
60 ? :? "We will renumber the entire file."
70 ? :? "What line number do you want the fi
le":? "to start with?100{4 LEFT}";:INPUT
T$:LNUM=VAL(T$)
80 ? :? "What step do you want between":? "e
ach line?10{3 LEFT}";:INPUT T$:INCR=VAL(T
$)
90 OPEN #2,8,0,"D:TEMP"
100 TRAP 150:INPUT #1,A$:Z=1
110 IF A$(Z,Z)<>" " THEN IF Z<LEN (A$) THEN Z
=Z+1:GOTO 110
130 PRINT #2;LNUM;A$(Z):LNUM=LNUM+INCR
140 GOTO 100
150 IF PEEK(195)<>136 THEN 200
160 CLOSE #1:CLOSE #2:XIO 33,#1,0,0,F$:XIO 3
2,#1,0,0,F2$
170 ? :? "Finished!":END
200 ? "{CBELL}Error - ";PEEK(195);" during re
number " :END
500 ? "{BELL}Cannot open ";F$:? "Error - ";P
EEK (195) :END
Program A-2. Atari LADS File Converter Utility
3 GRAPHICS 0
4 DIM A$(100),T$(100),F$(20),F2$(50)
10 READ T$:? T$:F$="D:":F$(3)=T$:IF T$="END"
THEN END
20 F2$="D:TEMP,":F2$(LEN(F2$)+1)=T$
100 OPEN #1,4,0,F$
110 OPEN #2,8,0,"D:TEMP"
130 TRAP 170:INPUT # #1.A$:IF A$(1,1)="0" THEN
A$=A$(2)
135 Z=LEN(A$)
140 IF A$(Z,Z)=" " THEN Z=Z-1:GOTO 140
142 A$=A$(1,Z):Z=1
144 IF A$(Z,Z)<>" " THEN Z=Z+1:GOTO 144
145 SZ=Z:Z=Z+1
146 IF A$(Z,Z)=" " THEN Z=Z+1:GOTO 146
147 T$=A$(Z):A$=A$(1,SZ):A$(SZ+1)=T$:Z=LEN(A
$):IF T$(1,1)=";" THEN 169
150 IF A$(Z,Z)<>";" THEN Z=Z-1:IF Z THEN 150
152 SZ=Z:Z=Z-1:IF Z<0 THEN 169
154 IF A$(Z,Z)=" " THEN Z=Z-1:GOTO 154
156 T$=A$(SZ):A$=A$(1,Z):A$(Z+1)=T$
169 PRINT #2; A$:GOTO130
170 CLOSE #1 :CLOSE #2:XIO 33,#1,0,0,F$:XIO 3
2,#1,0,0,F2$:GOTO 10
180 REM PUT YOUR FILENAMES HERE
190 REM E.G. DATA DEFS.SRC,EVAL.SRC,END
Special Apple Notes
Once you have typed in Apple LADS, you must BSAVE it to disk. The start address is $79FD and the length is $1674. To execute LADS you BRUN the binary file. After it loads and sets up its special wedge (see Chapter 11 for details on this wedge), you will be prompted with the BASIC prompt and a cursor. You can now type in your files and save them just as you would an Applesoft file. After saving the program to disk, you assemble it by typing:
ASM filename
Make sure you have a space between ASM and your filename. If you do not have the space, you will get a syntax error. With the wedge in, the BASIC tokenize routine does not execute, so you cannot type in BASIC programs after you BRUN LADS. Otherwise, all the features of Apple LADS operate as described under the general instructions at the start of this chapter.
Return to Table of Contents | Previous Chapter | Next Chapter