(tm) CHASM Cheap Assembler for the IBM Personal Computer (1983) by David Whitman Version 2.01 Table of Contents I. Why Chasm?...............................................2 II. What can Chasm do?......................................3 III. What WON'T it do?......................................3 IV. Syntax..................................................4 V. Operands.................................................6 VI. Resolution of Ambiguities..............................10 VII. Pseudo-Operations.....................................13 VIII. Outside the Program Segment..........................15 IX. Running Chasm..........................................16 X. Error and Diagnostic Messages...........................18 XI. Execution of Assembled Programs........................20 XII. Notes for Those Upgrading to This Version of Chasm....23 XIII. Miscellaneous and A Word From Our Sponsor............25 2 I. Why Chasm? Why go to the trouble to write an assembler, when one already exists? The IBM Macro Assembler is a very powerful software tool available off the shelf. It supports features such as macros, definition of multiple segments, and linking to external procedures. Unfortunately, all of this power doesn't fit into a 64K machine, and even when using the small subset version, 64K users are limited by memory to only very small programs. The macro assembler is also very complex, hard to understand, and costs a hundred bucks. Even though the price of memory keeps dropping, I suspect that the majority of the IBM PC's out there have no more than 64K installed. Also, I suspect that most end-user assembly language programmers are like myself, and are not interested in writing huge, complicated programs in assembler. I want to write short subroutines to call from BASIC, small patches to existing assembler programs (such as DOS), and perhaps some games. For such uses, I think the combination of the Macro Assembler and a tub full of extra memory represents an incredible overkill. Chasm is, I hope, a more reasonable compromise between power and accessibility (both in cost and complexity). 3 II. What can Chasm do? Chasm takes a text file, consisting of mnemonics, user-defined symbols, numbers, and pseudo-ops, and produces a file of corresponding machine language for the 8088 processor. Chasm allows you to define labels for branching, rather than requiring you to figure out offsets or addresses to jump to. It allows you to represent with a name any constants you want to use, making your programs easier to understand. Most importantly, it translates mnemonics to their machine language equivalents freeing you from the task of hand translation. III. What WON'T it do? In the interest of simplicity, Chasm has a number of restrictions: 1. Statement syntax is not quite as free as in the macro assembler. 2. The number of pseudo-ops is severely cut down from the macro assembler. 3. Macros are not supported. (Note that the IBM assembler doesn't support macros in systems smaller than 96K) 4. Expressions (such as BUFFER - 2 ) are not supported, at least in version 1.0. 5. Multiple segment definitions are not allowed, at least in version 1.0. Chasm assumes that your entire program fits in one segment, that the cs, ds, and es registers all point to this same segment, and that the ss register points to a valid stack area. 6. External linking is not supported, at least in version 1.0. 4 IV. Syntax Chasm accepts a standard DOS text file for input. Lines may be any combination of upper and lower case characters. Chasm does not distinguish between the two cases: everything except single quoted strings are automatically converted to upper case during the parsing process. Thus, BUFFER, Buffer, buffer, and bUFFer all refer to the same symbol. The characters blank ( ), comma (,), single quote (') semi-colon (;) and TAB are reserved, and have special meaning to Chasm (see below). Note also that Chasm is written in BASIC, and use of the double quote character (") may cause bizarre effects by confusing the interpreter into breaking down input lines in an undesirable way. The double quote may be safely represented in a text message by declaring a byte containing its ASCII value. Thus, to represent the text: Use ASCII value for "double quotes" You may use: DB 'Use ASCII value for ' 22H 'double quotes' 22H Each line must be less than 256 characters long and have the following format: Label Operation Operand(s) ;comment The different fields of an input line are separated by the delimiters blank ( ), comma (,) or TAB. Any number of any delimiter may be used to separate fields. Users who produce source files with IBM's utility EDLIN should be aware that when you press the tab key, EDLIN does *not* insert a variable number of blanks into your text. Rather, ASCII character 09, horizontal TAB, is inserted. Chasm will correctly assemble source files where fields are separated by TAB, but your listings may look a little funny, depending on how your printer handles this character. 5 Explanation of Fields: Label: A label is a string of characters, beginning in column 1. Depending on the operation field, the label might represent a program location for branching, a memory location, or a numeric constant. Note that anything beginning in column 1, except a comment, is considered a label. Operation: Either a pseudo-op (see section VII) or an instruction mnemonic as defined in "The 8086 Book" by Rector and Alexy. Note 1: Except as modified below,"The 8086 Book" is the definitive reference for use with Chasm. Note 2: There are several ways to resolve some ambiguities in 8086 assembly language. Please read page 3-285 of The 8086 Book, and section VI of this document. Operand(s): A list of one or more operands, as defined in section V, separated by delimiters. Comment: Any string of characters, beginning with a semicolon (;). Anything to the right of a semicolon will be ignored by Chasm. Note that except for the case of an operation which requires operands, or the EQU pseudo-op which requires a label, all of the fields are optional. The fields MUST appear in the order shown. 6 V. Operands The following operand types are allowed. 1. Immediate data: A number, stored as part of the program's object code. Immediate data are classified as either byte, expressible as an 8 bit binary integer; or word, expressible as a 16 bit binary integer. If context requires it, CHASM will left-pad byte values with zeroes to convert them to word values. Attempts to use a word value where only a byte will fit will cause an error message to be printed. Immediate data may be represented in 5 ways: A. An optionally signed decimal number in the range -32768 to 32767. Examples: MOV AL,21 MOV BX,-6300 B. A series of up to 4 hex digits, followed by the letter H. Examples: ADD CX,1234H ADD DL FDH C. A symbol representing types A or B above, defined using the EQU pseudo-op. Examples: MASK EQU 10H MAX EQU 1000 AND CL,MASK SUB AX,MAX D. The offset of a label or storage location returned by the OFFSET operator. OFFSET always returns a word value. OFFSET is used to get the address of a named memory location, rather than its contents. Example: MOV DI,OFFSET(BUFFER) BUFFER DS FFH 7 E. The ASCII value of a printable character, represented by the character enclosed in single quotes ('). Thus, the following lines will generate the same object code: MOV AL,41H ;ascii code for 'A' MOV AL,'A' 2. Register Operands: One of the 8088's internal registers. A. An 8 bit register from the following list: AH AL BH BL CH CL DH DL B. A 16 bit register from the following list: AX BX CX DX SP BP SI DI C. A segment register from the following list: CS SS DS ES 3. Memory Operands: The contents of a memory location addressed by one of the following methods. Note that none of the memory addressing options specifies whether a byte or word operand is being referenced. See section VI for more on this topic. A. Direct address. 1. A number, or symbol representing a number, enclosed in brackets, indicating an offset into the data segment. Example: BUFFER EQU 5A5AH MOV BH,[BUFFER] MOV [80H],DI 2. A symbol, defined to be a variable (i.e. a named memory location) using the EQU pseudo-op. Example: FCB EQU [80H] MOV DI,FCB 8 3. A symbol, defined to be a variable by its use on a storage defining pseudo-op. Examples: MOV AX,FLAG MOV DATE,BX FLAG DS 1 DATE DB 31 B. Indirect Address: The address of the operand is the sum of the contents of the indicated register(s) and a displacement. The register, or sum of registers, are enclosed in square brackets: [] The displacement is optional, and takes the form of an immediate operand, placed without intervening delimiters to the left of the first bracket. Displacements in the range -128 to 127 (i.e. hex 0 - 7F, FF80 - FFFF) are interpreted as signed 8 bit quantities. All other displacements are interpreted as unsigned 16 bit quantities. (Note that although the 8088 supports unsigned 16 bit displacements up to hex FFFF for indirect addressing, Chasm isn't smart enough to distinguish between -1 and FFFFH.) The following indirect modes are allowed: 1. Indirect through a base register (BX or BP). Examples: ENTRYLENGTH EQU 6 MOV AX, ENTRYLENGTH[BP] MOV DL, -2[BX] MOV CX, [BP] MOV 9A9AH[BX], AX 2. Indirect through an index register (DI or SI). Examples: MOV [DI], CX MOV CX, -5[SI] 9 3. Indirect through the sum of one base register and one index register. Examples: MOV [BP+DI], SP ;note that no spaces are MOV BX, 10H[BX+SI] ;allowed within the MOV CL, [BP+SI] ;brackets. MOV DH, -2[BX+DI] 4. Labels A label on an instruction may be used as an operand for call and jump instructions. Examples: START PROC NEAR CALL GETINPUT JMPS START ENDP GETINPUT PROC NEAR 5. Strings A string is any sequence of characters (including delimiters) surrounded by single quotes ('). Example: DB 'Copyright May 15,1982' 10 VI. Resolution of Ambiguities. The language defined in "The 8086 Book" contains a number of ambiguities which must be resolved by an assembler. This is discussed throughout the book, but pages 3-285 and 3-286 specifically cover this topic. Chasm's solutions of these problems are discussed in this section. A. Memory references: When one specifies the address of a memory location, it is unclear how large an operand is being referenced. An operand might be a byte, or a word. 1. If a register is present as an operand, it is assumed that the memory operand matches the register in size. An exception to this rule are the shift and rotate instructions, where the CL register is used as a counter, and has nothing to do with the size of the other operand. Examples: MOV MASK,AX ;mask is a word MOV DH,[BX] ;BX points to a byte NEG [SI] ;error, operand of unknown size SHR FLAG,CL ;error, flag is of unknown size 2. If no register is present, (or if the only register is CL being used as a counter) the size of the memory operand is specified by adding the suffix "B" or "W" to the instruction mnemonic. Examples: NEGB [SI] ;SI points to a byte SHRW FLAG,CL ;flag is a word MOVW MASK,0AH ;mask is a word MOVB MASK,0AH ;mask is a byte MOVW MASK,9A9AH ;must specify size even though ;immediate operand implies word MOVB DH,[BX] ;error(!), register already ;specifies size 11 B. Indirect Branching. The 8088 supports two flavors of indirect branching: intra, and intersegment. A register is set to point at a memory location which contains a new value for the program counter, and in the case of intersegment branching, a new value for the CS register as well. The syntax of "The 8086 Book" does not specify which flavor of branch is being invoked. Chasm adds the suffixes "N" (for near, or intrasegment) and "F" (for far, or intersegment) to the indirect CALL and JMP mnemonics. Examples: CALLN [BX] ;intrasegment call JMPF [DI] ;intersegment jump JMP [BP] ;error, unspecified flavor C. Long and Short Jumps Two types of relative jumps are supported by the 8088: short (specified by a signed 8 bit displacement) and long (specified by an unsigned 16 bit displacement). Both are implemented in Chasm as a jump to a label. The short jump is specified by mnemonic JMPS, in accord with the IBM disassembler, but not with The 8086 Book, which uses JMP. Since one of the displacement bits is used to indicate direction, only seven are left to express the magnitude of jump. JMPS (and similarly, all the jump on condition instructions) is thus limited to branching to labels within a range of -128 to +127 bytes. Chasm reserves mnemonic JMP for the long jump. Note that JMP may only be used to jump in the forward direction, since the sixteen bit displacement is unsigned, and assumed to be positive. Examples: START PROC NEAR JMPS START ;short jump JMPS END ;short jump JMP END ;long jump JMP START ;error: reverse long jump END ENDP 12 D. Instruction Prefixes. The 8088 supports three instruction prefixes: 1. SEG: segment override. An alternate segment register is specified for a reference to memory 2. REP, REPE,REPNE,REPZ,REPNZ: repeat. A string primitive is repeated until a condition is met. 3. LOCK: Turns on the LOCK signal. Only useful in multiprocessor situations. Chasm implements these prefixes as separate instructions, rather than prefixes to another instruction. They appear on a separate line, immediately before the instruction which they modify. This is in accord with the output of the IBM disassembler, but not with the IBM macro assembler. Examples: SEG ES MOV AX,FLAG ;flag is in the extra segment REP MOVSB ;move bytes until CX decremented to 0 13 VII. Pseudo-Operations The following pseudo-ops are implemented: A. DB: Declare Bytes Memory locations are filled with values from the operand list. Any number of operands may appear, but all must fit on one line. Acceptable operands are numbers between 0 and FFH (0-255 decimal), or strings enclosed in single quotes ('). If a label appears, it is considered a variable, and the location may be referred to using the label, rather than an address. Examples: MOV AX,MASK MASK DB 00H,01H STG DB 'A string operand' B. DS: Declare Storage Used to declare large blocks of identically initialized storage. The first operand is required, a number specifying how many bytes are declared. If a second operand in the form of a number 0-FFH appears, the locations will all be initialized to this value. If the second operand is not present, locations are initialized to 0. As with DB, any label is considered a variable. To save space, the object code does not appear on the listing. Examples: DS 10 ;10 locs initialized to 0 DS 100H,1AH ;256 locs initialized to 1AH C. ENDP: End of Procedure See PROC (below) for details. D. EQU: Equate Used to equate a symbolic name with a number. The symbol may then be used anywhere the number would be used. Use of symbols makes programs more understandable, and simplifies modification. 14 An alternate form of EQU encloses the number in square brackets: []. The symbol is then interpreted as a variable, and may be used as an address for memory access. This version is provided to allow symbolic reference to locations outside the program segment. Examples: MOFFSET EQU B000H MONOCHROME EQU [0000H] Warning: Difficult to debug errors may result from using a symbol prior to its being defined by EQU. I strongly urge that all equates be grouped together at the beginning of programs, before any other instructions. See "Phase Error" in section IX. E. ORG: Origin Allows direct manipulation of the location counter during assembly. By default, Chasm assembles code to start at offset 100H, the origin expected by COMMAND.COM for .COM programs. Using ORG you may override this default. Example: ORG 0 ;Code will be assembled for starting ;offset of 0 F. PROC ...ENDP: Procedure Definition Declares a procedure. One operand is required on PROC, either the word NEAR, or the word FAR. This pseudo-op warns Chasm whether to assemble returns as intra (near) or intersegment (far). Procedures called from within your program should be declared NEAR. All others should be FAR. ENDP terminates the procedure, and requires no operands. If a RET is encountered outside of a declared procedure, an error occurs. Procedures may be nested, up to 10 deep. Example: MAIN PROC FAR ... ... ;body of procedure ENDP 15 VIII. Outside the Program Segment As mentioned previously, Chasm does not support multiple segment definitions. Provision is made for limited access outside of the program segment, however. A. Memory References To access memory outside the program segment, you simply move a new segment address into the DS register, then address using offsets in the new segment. The memory option of the EQU pseudo-op allows you to give a variable name to offsets in other segments. For example, to access the graphics character table in ROM: BIOS EQU F000H CHARTABLE EQU [FA6EH] MOV AX,BIOS ;can't move immed. to DS MOV DS,AX MOV AL,CHARTABLE ;1st byte of char. table B. Code Branching Chasm supports 4 instructions for branching outside the program segment. 1. Direct CALL and JMP New values for the PC and CS registers are included in the instruction as two immediate operands. Example: BIOS EQU F000H ;RAM bios segment DISKETTE_IO EQU EC59H ;disk handler JMP DISKETTE_IO,BIOS 2. Indirect CALLF and JMPF Four consecutive bytes in memory are initialized with new values for the PC and CS registers. The CALLF or JMPF then references the address of the new values. Example: BIOS EQU F000H ;RAM bios segment PRINTER_IO EQU EFD2H ;printer routine MOV [DI],PRINTER_IO MOV 2[DI],BIOS CALLF [DI] 16 IX. Running Chasm From DOS, type: CHASM or BASIC CHASM/C:0 After a few seconds, Chasm prints a hello screen, then prompts: Hit any key to continue... Chasm prompts: Source code file name? [.asm] Type in the name of the file which contains your program. If you do not include an extension for the filename, Chasm assumes it to be .ASM. If Chasm is unable to find the file, it will give you the option of naming another file, or returning to DOS. Assuming your file is present, Chasm prompts: Direct listing to Printer (P), Screen (S), or Disk (D)? Respond with either an upper or lower case letter. If you select "D", Chasm will prompt: Name for listing file? [fname.lst] Type in a name for the listing file. If you just press ENTER, the name defaults to that of your source file, with an extension of .LST. The final prompt is: Name for object file? [fname.com] Type in a name for the assembled program. If you just press ENTER, the name defaults to that of your source file, with an extension of .COM. 17 Chasm now assembles your program. A status line is maintained on the screen, showing how many lines have been processed. Chasm makes two passes over your source file, outputting the listing and object code on the second pass. Be patient, Chasm is written in BASIC, and does a good imitation of a snail crawling through molasses. ****NOTE: I will send the Golden Bootstrap Award to the first person submitting a complete implementation of Chasm, rewritten in assembly language, and small enough to be assembled by Chasm version 1.9 on a 64K system. When finished, Chasm returns you to DOS, and you see the prompt: A> 18 X. Error and Diagnostic Messages Error messages generated on pass one appear on the listing before any source code is printed, and mention the line number to which they refer. The majority of messages occur during pass two, and will appear in the listing immediately prior to the line which caused the message. Could Use JMPS: Diagnostic. The specified label requires an offset of less than 128 bytes; specifying the short jump would result in more compact code. The assembled code is correct, however. Data too Long: The value of a immediate byte is found not to be in the range 0-FFH. Duplicate Definition of XXX in (linenum): Pass 1 error. An attempt was made to define a symbol already present in the symbol table. ENDP without PROC: An ENDP was encountered, but no corresponding PROC was found. EQU Without Label: No symbol was found to equate with the operand. Illegal or Undefined Argument for Offset: The argument for the Offset function was not present in the symbol table as a near label or memory location on pass 2. Illegal Reverse Long Jump: Long jumps must in the forward direction, since they are expressed with an unsigned displacement. Missing ENDP: The end of the input file was encountered, and at least one PROC had not been terminated by an ENDP. Phase Error: A near label or memory location is found to have different values on pass 1 and pass 2. A difficult to debug error: generally the problem is not caused by the statement which received the error message. The only documented way to generate this error is by using a symbol prior to defining it using EQU. On pass 1, Chasm assumes that unrecognized symbols are either labels or memory 19 addresses which will be defined later in the program. If the symbol is subsequently defined as immediate data, the location counter may get all messed up. I would appreciate hearing about any other situations which cause this message to appear. Procedures Nested Too Deeply: Procedures may be nested no more than 10 deep. Specify Word or Byte Operation: Diagnostic. Chasm suggests that the Syntax Error might be resolved by adding the suffix "B" or "W" to the instruction mnemonic. Most, but not all, ambiguous memory references are flagged with this diagnostic. Syntax Error: (OP) (DTYPE) (STYPE). Chasm was unable to find a version of the instruction (OP) which allows the operand types (DTYPE) and (STYPE). Either the instruction doesn't exist, or it is an inappropriate choice for the given operands. DTYPE and STYPE are numbers which encode Chasm's guess as to what the 1st and 2nd operands might be. The numbers are sums of the types given in the following list: 1 = 8 bit accumulator 2 = 16 bit accumulator 4 = 8 bit register 8 = 16 bit register 16 = indirect memory reference 32 = CS register 64 = other segment register 128 = memory location 256 = immediate byte 512 = immediate word 1024 = none 2048 = string 4096 = near label 8192 = reserved 16384 = CL (count) register Too Far For Short Jump: The displacement to the specified label is not in the range -128 to +127. Too Many User Symbols in (linenum): Pass one error. The symbol table is full. Undefined Operand for EQU: Any operands on an EQU statement must have been previously defined. Undefined Symbol XXX: The symbol XXX was used as an operand, but never appeared as a label, and is not a predefined symbol. Unrecognized Operand XXX: XXX is used in the DB operand list, but is not a string or byte value. 20 XI. Execution of Assembled Programs A. Object code format The object code file produced by CHASM is in the form of a memory image, exactly as will be present in your computer at run time. No link step is required. Provided that the segment registers are set correctly, the architecture of the 8088 guarantees that code is self-relocating, and will run correctly loaded anywhere in memory. Storing a program as an exact image of memory at run time is called the COM format by IBM. This COM format is *not* that produced by the IBM assembler. The output of the IBM assembler is in the form of an "object module" suitable for input to the linker. To the best of my knowledge, the object module is not directly executable, but must first be "filtered" through the linker. This adds an extra step to the process of producing a working program, but gives you the option of combining multiple object modules into one program. The resulting linked program is *still* not a memory image, but has a header which is used to perform relocation during loading. This linked program plus header is called the EXE format by IBM. B. Running Assembled Programs From DOS DOS provides a loader for running machine language programs. To run a program, you merely type it's name, with or without the extension. This is what you're doing every time you use a DOS external command such as FORMAT or CHKDSK. In fact, the COM format is named after "external COMmand". When you type the name, DOS examines the file extension to determine what format the file is in, either COM or EXE. This is why CHASM defaults to using the extension .com for your object file. If you plan to run the program from DOS, don't change the extension. For COM programs, DOS builds a 255 byte long "program segment prefix" and sets the segment registers to point to this PSP. The contents of the file are then loaded verbatim right after the PSP, at offset hex 100 in the segment defined by the segment registers. As soon as loading is complete, your program is executed starting with the instruction at hex 100. 21 Although you can totally ignore the PSP, you should read pages E-3 through E-11 of the DOS manual to see what DOS puts there for you. It turns out there are some real goodies which your program might want to use. When your program is done, it must transfer control back to DOS, otherwise the 8088 will continue to fetch what it believes are instructions from whatever garbage or bit-hash happens to follow your program in memory. The easiest way to return to DOS is to execute the instruction: INT 20H This is the vectored interrupt reserved by DOS for program termination. While we're on the topic of vectored interrupts, you would be well rewarded to study both the DOS manual and Technical Reference to find out what happens when you execute some of the other interrupts. Some very useful functions, such as file handling and screen i/o, are available at the machine language level through this mechanism. By changing the interrupt vector for a given function to point to your own code, you can override the way DOS or the BIOS does something, and do it your way. This document was produced from Easywriter directly, in standard DOS format, by printing it to disk. It was not necessary to manually add an end of paragraph marker at the end of each line, and I didn't need to run it through the program TRANSFER which IBM provides. I had changed the vector for printer support to point to some code which sent the output to disk. Easywriter thought it was using the printer, and formatted everything nicely. C. Debugging Assembled Programs IBM provides an excellent utility with DOS, called DEBUG.COM. By specifying your program's name as a parameter when invoking DEBUG, you can observe your program execute with DEBUG's trace and other functions. To debug your program, from DOS type: DEBUG progname.COM 22 DEBUG builds a PSP and loads your program just like DOS does, but you have the added power of the debugging commands to monitor your program while it runs. See chapter 6 of the DOS manual for more details about using DEBUG. D. Using Assembled Programs in BASIC To incorporate a machine language subroutine in a BASIC program, write it in assembly language, then assemble it with CHASM. You should read page C-7 of the BASIC manual for some conventions to use in writing your subroutine. In particular, note that you must declare the routine to CHASM as a FAR procedure using the PROC pseudo-op, and that the last instruction of the routine should be a RET. Convert the assembled program into a form accessible to BASIC, using the utility COM2DATA supplied on your CHASM disk. The resulting series of DATA statements can be merged into your BASIC program. Your program can then READ the data and POKE it into memory. An example program to do this is given on page C-6 of the BASIC manual. An alternative approach would be to store the routine in a string variable, which could later be located with the VARPTR function. You transfer control to your routine with either the USR function, or the CALL statement. Syntax for these statements can be found in the BASIC manual. 23 XII. Notes for Those Upgrading to This Version of Chasm. Chasm is not yet cast in stone - improvements and corrections are made fairly frequently, based on both my own experience in using the program, and the comments of outside users. This section summarizes the changes which have been made since version 1.2 was released. The utility COM2DATA was added to the CHASM distribution package as of version 2.01, as an aid to including machine language subroutines in BASIC programs. Version 2.00 corrected a bug in the DS and DB pseudo-ops which caused the last label in a program to be redefined as a memory location, whether it was intended to be one or not. Also in version 2.00, the TAB character was added as a new delimiter, and a 20 page introductory primer was added to the CHASM distribution package. The only change which could invalidate an already correct program involves the short jump instruction. Versions prior to 1.9 represented this instruction with mnemonic JP. This mnemonic was chosen to be in accord with the output of the unassemble command of DEBUG. Either I simply made a mistake in this regard, or IBM changed the mnemonic in the DEBUG supplied with DOS 1.1. At any rate, DEBUG 1.1 represents the short jump with mnemonic JMPS, and CHASM now follows this syntax. JP is now recognized as an alternate form of instruction JPE (jump on even parity), in accord with The 8086 Book. Version 1.8 added the operand type "character" as a new way to represent immediate data. A single character enclosed in single quotes (') is equivalent to the numeric value of the ASCII code for the character. See section V-1-E of this document for details. As of version 1.7, the DS operator works for blocks larger than 255 bytes. To keep the listing under control, object code generated by DS is no longer shown on the listing. Also corrected in version 1.7, the OFFSET function now works properly in the displacement field of an indirect memory reference. 24 Version 1.6 was a revision of this document. Some sections were improved slightly, and in response to user requests, a section on execution of assembled programs was added. Version 1.5 corrected an error which generated the message "Data too Long" if the value FFH was used as 8 bit immediate data. The user interface was improved as of version 1.4. Chasm now traps some common input errors such as misspelling a file name, or forgetting to turn on your printer, giving you a second chance rather than just crashing. Version 1.3 involved a speed improvement by a factor of 5 over 1.2. Users should note that a number of copies labeled as version 1.2 actually incorporate this improvement. As can be seen, revisions are made on a regular basis. It is my policy that after once contributing, users are entitled to all future versions free of charge, with no further donation expected. Contributing users are encouraged to send a disk and return mailer from time to time, to receive the most current version. Major improvements will be announced in IPCO INFO and Programmer's Journal. 25 XIII. Miscellaneous and A Word From Our Sponsor... There is a bewildering array of files on your disk. As you've discovered by now, the file CHASM.DOC is documentation. PRIMER.DOC is a gentle introduction to assembly language programming for beginners. Neither of these files need be present on your disk for CHASM to run. Deleting them will free up about 100K of disk space. The actual program is in CHASM.BAS. To run the program, three other files *must* be present. You must copy BASIC.COM from your DOS disk to interpret the program. CHASM.DAT contains data about the various instruction mnemonics Chasm recognizes, and must be present. The last file needed is CHASM.OVL. OVL is an empty file, which is merged to fool BASIC into deleting some of the initialization code to make more room for the symbol table. The file CHASM.BAT is a batch file to make it easier to start Chasm from DOS. With CHASM.BAT, you can just type: chasm. Without it you'd type: basic chasm/c:0. TCHASM.BAT is a batch file used to breed new CHASM disks, if you want to give a copy to someone else. It copies the program, documentation, data; the whole works. Please only distribute the complete CHASM system, as generated by this batch file. CLS.ASM is provided as a sample source file. You can try out Chasm using CLS as input. COM2DATA.BAS is a little utility which converts a machine language file into a series of BASIC DATA statements, to make it easier to include machine language subroutines in BASIC programs. Documentation is in the file COM2DATA.DOC. Programming Notes: 1. Chasm is written in heavily commented BASIC, so modifications would be easy, if you'd like to customize. I'd like to hear about any improvements people make, for possible inclusion in future releases. 26 2. If you do try to modify Chasm, there is a quirk you should know about. Most of the initialization code is in a "transient section" which is used once, then deleted to make more room for the symbol table. Lines 50,000 - 65529 are reserved as this transient section. Note Well: If you run Chasm, then save it to disk, you save the program WITHOUT THE INITIALIZATION CODE. The resulting program is non-functional. Be careful! Keep a backup. 3. Chasm truncates source lines to about 50 characters in the listing, to avoid going over an 80 character line. If your printer has a condensed mode with more than 80 characters/line, provision has been made for a simple customization to make Chasm turn on the special mode before listing, and print as many characters as possible. The printer will be returned to normal when Chasm finishes. The modification only affects listings to the printer, not to screen or disk. Find subroutine HEADER in the transient section. After the IF statement under the comment "printer set up?" you must set the width of device #2 to the number of characters per line in condensed mode with a WIDTH#2 statement, and set the variable LWIDTH to this number minus 1. Print whatever control sequence turns on your condensed mode, and set the variable PMODEOFF$ to a string which returns the printer to normal. An example modification is embedded at the correct spot as a series of remarks. Disclaimer: CHASM is distributed as is, with no guarantee that it will work correctly in all situations. I cannot be responsible for any damages associated with its use. Nonetheless, it is my intention to fix any bugs which are brought to my attention. Drop me a line if you think you've found a problem. 27 I am joining the experiment started by the folks at Freeware (tm), by distributing un-protected software, and *encouraging* copying. The catch, (of course there's a catch) is that I request that all users who think the program is worthwhile send a donation. The suggested donation is $20, but send what you think the program is worth to *you*. The underlying philosophy here is based on three principles: First, that the value and utility of software is best assessed by the user on his/her own system. Only after using a program can one really determine whether it serves personal applications, needs, and tastes. Second, that the creation of independent personal computer software can and should be supported by the computing community. Finally, that copying and networking of programs should be encouraged, rather than restricted. The ease with which software can be distributed outside traditional commercial channels reflects the strength, rather than the weakness, of electronic information. There is obviously no way I can enforce payment, but I hope people will recognize the amount of work that went into writing and documenting Chasm, and will make a donation. Contributing users are entitled to all upgrades free of charge, and their names are added to my mailing list to be notified of significant improvements. I hope folks find CHASM useful. David Whitman 2 North Park Street Apartment L Hanover, NH 03755 (603) 643-2115