Chapter 2
Defs:

Equates and Definitions


Let's get started. Recall that the boldface numbers within the text refer to line numbers within the program listings at the end of each chapter. The first section of LADS defines many of the variables which are used throughout the program. It's called "Defs."

Defs for Relocatability
One of the advantages of advanced assemblers, LADS included, is that they create object code (runnable ML programs) which are both relocatable anywhere within a computer's RAM memory as well as transportable between computer brands and models.
     If you want to put LADS at $5000 instead of $2AF8, you can relocate it quite simply: Just change line 10 in the Defs source code file, the first file in the chain of LADS source code files. As written, line 10 reads *= 11000 (equivalent to *= $2AF8) and that causes the entire object program to start at that address. Changing line 10 to * = $5000 relocates LADS when you next assemble it. If you include the pseudo-op D, the object program will be saved to disk under the filename you specify.
     In the source code of LADS itself, at the end of this chapter, the ".D LADS64" in line 30 will create a version of LADS on disk by the name of LADS64 and if you later LOAD "LADS64",8,1 it will come into your computer ready to run with a SYS 11000. If you change the start address in line 10, however, to $5000, and then reassemble the source code, your LADS will start with a SYS 20480 (decimal for $5000).
     The numbers generated by the assembly (the object code) will be sent to a disk file if you specify that with D. They will be sent into RAM memory if you use the .O pseudo-op. If you do turn on storage of object code to memory, LADS will send the results of the assembly right into memory during the assembly process. This can cause mysterious difficulties unless you are careful not to assemble over LADS itself. If you have created a version of LADS which starts at $4000 and you then start assembly of some object program at $5000, you'll eat into LADS itself. LADS is about 5K long. This, of course, would cause havoc. Using the D pseudo-op is safe enough, since the new ML program assembles to disk. But the .O pseudo-op will send bytes right into RAM during assembly.
     Be aware, too, that LADS builds its label array down from the start of its own code. During assembly, the labels and their values are stored in a growing list beneath the start address of LADS (where you SYS to start the assembler). If you send object code into an area of RAM which interferes with this array, you'll get lots of UNDEFINED LABEL errors. So be sure you know where you're putting object code if you store it in RAM during assembly by using the .O pseudo-op.

Defs for Transportability
The only part of LADS which is intensely computer-specific is this first file, this first subprogram, called Defs. Here we define all the machine-specific equates. (An equate is the same thing as a variable definition in BASIC. For example, RAMSTART = $213 is a typical equate.) We'll use the Commodore 64 Defs (Program 2-1) as our example. The labels (variable names like RAMSTART) for all other computers' versions of LADS will be the same-only the particular numbers assigned to these labels will vary. The addresses of pointers and ROM routines vary between computer models.
     Defs contains the definitions of all zero page or ROM addresses that will be used in the rest of the source code. Once again, remember that all zero page equates must be defined at the start of the source code (Defs illustrates that rule: Defs is the first part of the LADS source code). From lines 60 to 170 we define the locations within zero page that we'll be using. In line 70 we define the top of the computer's RAM memory. We're going to lower it from its usual spot to fall just below where LADS itself starts.
     ST is the location where errors in disk file manipulation can be detected. Like all of these zero page equates, this location varies from computer to computer. LOADFLAG (line 90) signals the computer that we want to LOAD a program file (rather than VERIFY a previously SAVEd program file). This flag will be set in the version of LADS which assembles from RAM memory (and LOADs in chained source code programs from disk). This RAM-based version of LADS will be created later in Chapter 11, the chapter on modifying LADS.

Disk I/O Information
The next five definitions show where information is stored just before a disk operation. They tell the operating system where in memory a filename is located, how long the name is, the file number, the file's secondary address, and the device number (8 for disk, 4 for printer, in Commodore computers).
     CURPOS always contains the position of the cursor onscreen (as a number of spaces over from the left of the screen). We'll use this to format the screen listings. And the final machine-specific zero page definition is RAMSTART. It tells LADS where BASIC RAM memory starts. It, too, is used in the version of LADS which assembles from RAM.
     Why do we need to define these locations if the operating system uses them? Because we're going to use a few of the built-in BASIC routines to handle the I/O (Input/Output) operations for us when we need to communicate with a peripheral. To OPEN a file, for example, we need to set up several of these pointers. To OPEN file #1, we have to put a 1 into address $B8 (that's where the file number is held on the Commodore 64). But why not just use LDA #1: STA $B8? Why do we want to use these labels, these variable names?
     Programming with pure numbers instead of labels prevents transportability. It locks your program into your computer, your model. It's far easier to change this single equate in line 120 to $D2 to make the program run on a PET/CBM with BASIC 4.0 than it would be to go through the entire source code, changing all B8's to D2's. Also, if you buy a newer model and they've moved things around in zero page (they almost always do), making the adjustments will be simple. You just use a map of the new zero page and make a few changes in the Defs file.

LADS Zero
Because LADS needs to use the valuable Indirect Y addressing mode-LDA (12),Y or STA (155),Y-it will want to usurp a few of those scarce zero page locations itself. Line 170 defines a two-byte temporary register called TEMP which will be used in many ways. SA is going to function as a two-byte register for the LADS Program Counter which will keep track of where we are currently storing object bytes during the assembly process.
     MEMTOP is used in the construction of our label data base. It will always know where the last symbol in our label table was stored. All through pass 1 it will be lowering itself, making room for new symbols and labels. (This data base will later be referenced as we fill in the blanks on pass 2.) PARRAY makes that search through the symbol table on pass 2 easy and fast. It points us through the array. PMEM is used as a pointer during assembly from RAM, if you decide to use the RAM-based version of LADS described in Chapter 11. The uses of all these variables will become clear when we examine, throughout the book, the techniques which utilize them.

Borrowing from BASIC
The next section, lines 190-320, defines the routines within BASIC ROM memory that we're going to use. Naturally, these are particular to each computer brand and model, so we want them up front where they can be easily identified and changed.
     BASIC always has an entry point called the warm start address, a place where you can jump into it "warmly." But there's another entry that's not as gentle. Many BASICS clear out RAM memory and radically reset pointers, etc., when you first turn on the computer. This is called the cold start entry point, and it's as much of a shock to the computer as walking outdoors into a winter wind is to you. We don't want this shock when we return from LADS to BASIC. Instead, we want the RAM memory left alone. After all, LADS is in there and possibly an object or source program is in there too. So when assembly is finished, we want to go into BASIC via the warm start entry point.
     KEYWDS is the address of the first BASIC keyword. We'll see why we need this address in the chapter on the Indisk subprogram. OUTNUM is a ROM routine which is used to print line numbers for the BASIC LIST command. We'll use it in a similar way to list the line numbers of our source code.
     OPEN, CHKIN, CHKOUT, CLRCHN, and CLOSE allow us to communicate with the disk drives and printers. CHARIN is like BASIC's GET command, PRINT like PRINT. STOPKEY sees if you've pressed the STOP or BREAK key on your keyboard. And, last, SCREEN tells LADS where in RAM your video memory starts.
     The use of these routines, and the ways that ML programs can borrow from BASIC, will be covered in detail as they appear in the LADS source files. For now, we only need to know that they are defined here, in Defs, and can be quickly changed to suit different computers, different BASICs.
     There you have it. We'll be explaining these pointers and registers as we come upon them in the explication of LADS. Now on to the heart of LADS, the section which evaluates all the mnemonics (like LDA) and addressing modes and turns them into opcodes (like A9) that are the machine's language. This next section, Eval, is-by itself-a complete assembler. It would stand alone. The rest of the sections of LADS add things to this core, things like disk management, arithmetic and other pseudo-op routines, label interpretation, screen and other output, and a host of other niceties. But Eval is the sun; the rest of the routines are lesser bodies, planets in orbit around it.
Note: Because the Defs subprogram is computer-specific, there are five source code listings at the end of this chapter, one for each computer. There are also multiple listings in Chapter 5 since it deals with computer-specific peripheral communication. However, the majority of chapters will have only a single complete listing, followed by the few modifications required by the different computers, because the majority of LADS' source code is identical and entirely transportable between 6502-based computers.

Program 2-1. Defs: Commodore 64
10 *= 11000
20 .NO
30 .D LADS64
40 ; "DEFS64" EQUATES AND DEFINITIONS FOR COMMODORE 64
50 ;--------------------- MACHINE SPECIFIC ZERO PAGE EQUATES -----------
60 RAMSTART = $2B; BASIC'S START OF RAM MEMORY POINTER
70 BMEMTOP = $37; BASIC'S TOP OF RAM MEMORY POINTER
80 ST = 144; STATUS WORD FOR DISK/TAPE I/O
90 LOADFLAG = $93; FLAG WHICH DECIDES LOAD OR VERIFY (0 = LOAD)
100 FNAMELEN = $B7; LENGTH OF FILENAME FOR OPEN A FILE
110 FNAMEPTR = $BB; POINTER TO FILENAME LOCATION IN RAM.
120 FNUM = $B8; CURRENT FILE NUMBER FOR OPEN, GET & PUT CHARS TO DEVICE
130 FSECOND = $B9; CURRENT SECONDARY ADDRESS FOR OPEN
140 FDEV = $BA; DEVICE NUMBER (8 FOR COMMODORE DISK)
150 CURPOS = 211; POSITION OF CURSOR ON A GIVEN SCREEN LINE.
160 ;--------------------- LADS INTERNAL ZERO PAGE EQUATES -----------
170 TEMP = $FB:SA = $FD:MEMTOP = $B0:PARRAY = $B2:PMEM = $A7
180 ;------------------ MACHINE SPECIFIC ROM EQUATES -----------
190 BABUF = $0200; BASIC'S 'INPUT BUFFER
200 TOBASIC = $A474; GO BACK TO BASIC
210 KEYWDS = $A09E; START OF KEYWORD TABLE IN BASIC
220 OUTNUM = $BDCD; PRINTS OUT A (MSB), X (LSB) NUMBER
230 OPEN = $E1C1; OPENS A FILE (3 BYTES PAST NORMAL OPEN IN ROM).
240 CHKIN = $FFC6; OPENS A CHANNEL FOR READ (FILE# IN X)
250 CHKOUT = $FFC9; OPENS CHANNEL FOR WRITE (FILE# IN X)
260 CHARIN = $FFE4; PULLS IN ONE BYTE
270 PRINT = $FFD2; SENDS OUT ONE BYTE
280 LOAD = $E175; LOAD A BASIC PROGRAM FILE (SOURCE CODE FILE) INTO RAM.
281 ; (F322 FOR UPGRADE/E172 FOR VIC)
290 CLRCHN = $FFCC; RESTORES DEFAULT I/O
300 CLOSE = $FFC3; CLOSE FILE (FILE# IN A)
310 STOPKEY = $FFE1; TESTS STOP KEY, RETURNS TO BASIC IF PRESSED.
320 SCREEN = $0400; ADDRESS OF 1ST BYTE OF SCREEN RAM
330 ;------------------
340 .FILE EVAL


Program 2-2. Defs: VIC-20
10 *= 11000
20 .D LADSV
30 .NO
40 ;    VIC VERSION
50 ; "DEFSV" EQUATES AND DEFINITIONS
60 ;--------------------- MACHINE SPECIFIC ZERO PAGE EQUATES -----------
70 BMEMTOP = $37; BASIC'S TOP OF MEMORY POINTER
80 ST = 144; STATUS WORD FOR DISK/TAPE I/O
85 LOADFLAG = $93
90 FNAMELEN = $B7; LENGTH OF FILENAME FOR OPEN A FILE
95 FNAMEPTR = $BB; POINTER TO FILENAME LOCATION IN RAM.
100 FNUM = $B8; CURRENT FILE NUMBER FOR OPEN, GET & PUT CHARS TO DEVICE
110 FSECOND = $B9; CURRENT SECONDARY ADDRESS FOR OPEN
120 FDEV = $BA; CURRENT DEVICE NUMBER
130 CURPOS = 211; POSITION OF CURSOR ON A GIVEN SCREEN LINE.
135 RAMSTART = $2B; POINTER TO START OF RAM MEMORY (FOR RAM-BASED ASSEM.)
140 ;--------------------- LADS INTERNAL ZERO PAGE EQUATES -----------
150 TEMP = $FB:SA = $FD:MEMTOP = $B0:PARRAY = $B2:PMEM = $A7
160 ;------------------ MACHINE SPECIFIC ROM EQUATES -----------
170 TOBASIC = $C474; GO BACK TO BASIC
175 BABUF = $0200; BASIC'S INPUT BUFFER
176 LOAD = $E172
180 KEYWDS = $C09E; START OF KEYWORD TABLE IN BASIC
190 OUTNUM = $DDCD; PRINTS OUT A (MSB), X (LSB) NUMBER
200 OPEN = $E1BE; OPENS A FILE (3 BYTES PAST NORMAL OPEN IN ROM)
210 CHKIN = $FFC6; OPENS A CHANNEL FOR READ (FILE# IN X)
220 CHKOUT = $FFC9; OPENS CHANNEL FOR WRITE (FILE# IN X)
230 CHARIN = $FFE4; PULLS IN ONE BYTE
240 PRINT = $FFD2; SENDS OUT ONE BYTE
250 CLRCHN = $FFCC; RESTORES DEFAULT I/O
260 CLOSE = $FFC3; CLOSE FILE (FILE# IN A)
270 STOPKEY = $FFE1; TESTS STOP KEY, RETURNS TO BASIC IF PRESSED.
280 SCREEN = $1000; ADDRESS OF 1ST BYTE OF SCREEN RAM (W/EXPANDED MEMORY)
640 .FILE EVAL


Program 2-3. Defs: PET/CBM 4.0 BASIC
10 *= 11000
20 .NO
30 .D LADS
40 ; "DEFS" EQUATES AND DEFINITIONS FOR PET/CBM 4.0 BASIC
50 ;-------------------- MACHINE SPECIFIC ZERO PAGE EQUATES -----------
60 RAMSTART = $28; BASIC'S START OF RAM MEMORY POINTER
70 BMEMTOP = $34; BASIC'S TOP OF RAM MEMORY POINTER
80 ST = 150; STATUS WORD FOR DISK/TAPE I/O
90 LOADFLAG = $9D; FLAG WHICH DECIDES LOAD OR VERIFY (0 = LOAD)
100 FNAMELEN = $D1; LENGTH OF FILENAME FOR OPEN A FILE
110 FNAMEPTR = $DA; POINTER TO FILENAME LOCATION IN RAM.
120 FNUM = $D2; CURRENT FILE NUMBER FOR OPEN, GET & PUT CHARS TO DEVICE
130 FSECOND = $D3; CURRENT SECONDARY ADDRESS FOR OPEN
140 FDEV = $D4; DEVICE NUMBER (8 FOR COMMODORE DISK)
150 CURPOS = 198; POSITION OF CURSOR ON A GIVEN SCREEN LINE.
160 ;--------------------- LADS INTERNAL ZERO PAGE EQUATES -----------
170 TEMP = $FB:SA = $FD:MEMTOP = $BB:PARRAY = $BD:PMEM = $BF
180 ;------------------ MACHINE SPECIFIC ROM EQUATES -----------
190 BABUF = $0200; BASIC'S INPUT BUFFER
200 TOBASIC = $B3FF; GO BACK TO BASIC
210 KEYWDS = $B0B2; START OF KEYWORD TABLE IN BASIC
220 OUTNUM = $CF83; PRINTS OUT A (MSB), X (LSB) NUMBER
230 OPEN = $F563; OPENS A FILE (3 BYTES PAST NORMAL OPEN IN ROM).
240 CHKIN = $FFC6; OPENS A CHANNEL FOR READ (FILE# IN X)
250 CHKOUT = $FFC9; OPENS CHANNEL FOR WRITE (FILE# IN X)
260 CHARIN = $FFE4; PULLS IN ONE BYTE
270 PRINT = $FFD2; SENDS OUT ONE BYTE
280 LOAD = $F356; LOAD A BASIC PROGRAM FILE (SOURCE CODE FILE) INTO RAM.
281 ; (F322 FOR UPGRADE/E172 FOR VIC/E175 FOR 64)
290 CLRCHN = $FFCC; RESTORES DEFAULT I/O
300 CLOSE = $F2E2; CLOSE FILE (FILE# IN A)
310 STOPKEY = $FFE1; TESTS STOP KEY, RETURNS TO BASIC IF PRESSED.
320 SCREEN = $8000; ADDRESS OF 1ST BYTE OF SCREEN RAM
330 ;------------------
340 FILE EVAL


Program 2-4. Defs: Apple
10 *= $79FD
20 .D LADS
30 .NO
40 ;APPLE VERSION
50 ; "DEFS" EQUATES AND DEFINITIONS
60 ;--------------------- MACHINE SPECIFIC ZERO PAGE EQUATES ------------
70 BMEMTOF = $4C; BASIC'S TOP OF MEMORY POINTER:
80 TXTFTR = sB8; POINTER; TO NEXT BYTE !3F TEXT
85 FNAMELEN = $F9; LENGTH OF FILE NAME
90 CHRGET = $B1; GET NEXT BYTE OF TEXT
95 PRGEND = $AF; POINTER TO END OF PROGRAM
100 HIGHDS = $94; HIGH DESTINATION OF BLOCK: TRANSFER UTILITY (BLTU)
110 VARTAB = $69; VARIABLE TABLE POINTER
130 CURPOS = 36; POSITION OF CURSOR ON A GIVEN SCREEN LINE.
140 ;--------------------- LADS INTERNAL ZERO PAGE EQUATES -----------
150 TEMP = $FB:SA = $FD:MEMTOP = $EB:PARRAY = $ED
155 FARM = $2A:FMOP = $2C
160 ;------------------ MACHINE SPECIFIC ROM EQUATES -----------
170 TOBASIC = $3D0; GO BACK TO BASIC
175 BABUF = $0200; BASIC'S INPUT BUFFER
180 KEYWDS = $D0D0; START OF KEYWORD TABLE IN BASIC
190 OUTNUM = $ED24; PRINTS OUT A (MSB). X (LSB) NUMBER
200 CSWD = $AA57; ADDRESS OF CHARACTER OUTPUT ROUTINE
210 LOUT = $FDF0; OUTPUT ONE BYTE
220 PRNTR = $C090; I/0 LOCATION FOR PRINTER
2 0 PRNTRDN = $C1C1; PRINTER READY SIGNAL
240 LINGET = $DA0C; GET LINE NUMBER FROM TXTPTR INTO LINNUM
250 LININS = $D46A; INSERT BASIC LINE INTO BASIC TEXT
280 SCREEN = $0400: ADDRESS OF 1ST BYTE OF SCREEN RAM
640 .FILE EVAL


Program 2-5. Defs: Atari
100 *= $8000
110 .D D:LADS.OBJ
120 ST = $01
130 FNAMELEN = $80
140 FNAMEPTR = $81
150 FNUM = $83
160 FSECOND = $84
170 FDEV = $85
180 CURPOS = 85
190 TEMP = $86
200 SA = $88
210 MEMTOP = $8A
220 PARRAY = $8C
230 INFILE = $8E
240 OUTFILE = $8F
250 PMEM = $A0
260 RAMFLA6 = $A2
270 BABUF = $0500
280 SAVMSC = $58
290 .FILE D:EVAL.SRC


Return to Table of Contents | Previous Chapter | Next Chapter