ZZZZZZZZZZZ MMMM MMMM ZZ MM MM MM MM ZZ MM MM MM MM ZZ MM MM MM MM ZZ MM MM MM MM ZZ MM MMMM MM ZZ MM MM MM ZZ MM MM ZZ MM MM ZZZZZZZZZZZ MM MM Copyright (c) 1983 Roger E. Donais If you have ant questions concerning ZM, contact the author: Roger E. Donais, USA Ret 7506 Republic Ct. #201 Alexandria, VA 22306 (703) 765-0615 C O N T E N T S INTRODUCTION .................................... 1 STATEMENT SYNTAX ................................ 4 OPCODES ......................................... 5 OPERANDS ........................................ 5 OPERATORS ....................................... 7 DIRECTIVES ...................................... 9 PREDEFINED USER SYMBOLS ......................... 13 TERMINAL ERRORS ................................. 14 FATAL ERRORS .................................... 16 WARNING MESSAGES ................................ 18 RUNTIME REQUIREMENTS ............................ 19 RESERVED SYMBOLS ................................ 20 Z80 SYNTAX SUMMARY .............................. 21 ALTERATION ...................................... 23 INDEX ........................................... 27 I N T R O D U C T I O N ZM translates symbolic language source files into machine executable code in either (.COM) or Intel loader (.HEX) format. It has been designed to be easily used by the novice, yet provide a variety of capabilities powerful enough for the expert. ZM can be used to assemble large files on relatively small systems. TO USE: Enter ZM drive:filename.type options Where "drive" is the CP/M drive which will receive the assembled object file, "filename.type" is any valid CP/M file, and "options" are one or more of the following: L to get an assembled Listing H to get a .HEX type object file C to get a .COM type object file 1 for printer setup #1 (see alteration notes) 2 for printer setup #2 (see alteration notes) = to enter subject text (see listing) All options, except "=", may be entered in any order. When used, the "=" option must always be entered last. Default settings are NO listing, NO object file and a blank subject line. ZM uses the same resources to produce both a .HEX and .COM Object file, therefore only one or the other may be requested. NOTE: ^C may be used to abort assembly from the keyboard. ^S may be used to pause and restart assembly. EXAMPLE: C>ZM B:JUNK.PDQ C Will cause ZM to create the object file B:JUNK.COM using the first JUNK.PDQ found on the designated drive, default drive, an internally defined drive or drive A:. If JUNK.PDQ cannot be found on any of these drives, ZM will prompt with the message: --Insert disk with JUNK.PDQ and press The disk may then be inserted in any of the previously mentioned drives, EXCEPT the drive destined to receive the object file (in this example B:). The process will repeat until JUNK.PDQ is found, or a ^C is entered in response to the prompt. PAGE 1 LISTING: A two line heading is printed on each page: SUBJECT: __________________________________________ SOURCE FILE: _______ PAGE - nn DATE: yy/mm/dd The source file is the name of the file currently being assembled (see INCL directive). The subject will contain the text immediately following an equal sign. Control characters may be entered to initialize specific printer options. Maximum text length is 63 characters. An assembly listing is printed only when the "L" option has been selected. The actual listing may then be disabled/enabled by LIST directive. A partial listing, consisting of all source statements containing warning and fatal assembly error messages, will be displayed whenever the "L" option has not been selected. The console is the default list device. Use options 1 or 2 to obtain printer output. Used by themselves, they will direct the error and warning messages to the printer. Used with the "L" option, they direct the entire assembly listing to the printer. If the printer is NOT ready when ZM begins to print, output will automatically be set to the console. ZM will wait indefinately if the printer goes off line, or otherwise becomes unavailable, once printer output has started. EXAMPLES: ZM JUNK error messages will be sent to the console. ZM JUNK 1 error messages will be sent to the printer using printer setup string #1. If the printer is not ready, messages will be sent to the console. ZM JUNK L listing will be sent to the console. ZM JUNK L2 listing will be sent to the printer using printer setup string #2. If the printer is not ready, listing will be sent to the console. PAGE 2 END OF ASSEMBLY: The following will be displayed: NEXT ADDRESS nnnnH NEXT DATA nnnnH FREE MEMORY nnnnH STACK SPACE nnnn ERROR COUNT nnnn/nnnn NEXT ADDRESS is the first hexadecimal address following the last item of assembled code. NEXT DATA is the hexadecimal value currently assigned to the predefined symbol DATA. (see directives and predefined symbols). Depending upon how the DATA directive/symbol was used, NEXT ADDRESS or NEXT DATA could be used as the origin for a co-resident or chained program or program overlay. FREE MEMORY is the hexadecimal amount of memory available for symbols and object file buffer (see RUNTIME requirements). STACK SPACE is the decimal amount of unused buffer/stack memory which is available for expression evaluation and source file inclusion (see RUNTIME requirements). ERROR COUNT is a two part decimal number corresponding to the number of statements tagged with fatal/warning messages. The sum of these numbers reflect the total number of statements, not the total number of error messages. PAGE 3 _ _ _ _ _ _ _ _ S T A T E M E N T S Y N T A X _ _ _ _ _ _ _ _ The general format of an assembly statement is: LABEL OPCODE OPERAND(s) COMMENT UNDERSCORE and COLON characters are ignored, except when used between quotes. An exaggerated example is _L_D_: and LD being equivalent. SPACES are used only to identify an item boundary, otherwise they may be used without restriction between any element, including parts of an expression. TABS (ascii 09h or ^I) are treated as spaces during assembly and expanded to every eighth print position within the listing. LINE FEED (ascii 0Ah or ^J) and CARRIAGE RETURN (ascii 0Dh or ^M) are always recognized as the end of a source statement and may NOT be embedded within a statement. FORM FEED (ascii 0Ch or ^L) will assemble when embedded in quotes, however, always cause the list driver to perform a page eject. CONTROL CHARACTERS (ascii 00h through 1Fh) are similiar to spaces in that they mark the boundary of an item, otherwise they may appear at any point within a statement. They are not processed during assembly, but sent to the printer "as is". Note that this applies to all control characters except tabs (ascii 09h or ^I), line feed (ascii 0Ah or ^J) and carriage returns (0Dh or ^M) which are explained above. BIT-7 is removed from all characters in the source file before processing. This eliminates the need to preprocess files that have been edited as a WordStar document. DECIMAL POINTS, entered as the first character in a statement, are assumed to be WordStar DOT COMMANDS. The statement is ignored and will not appear on the listing. LABELS or SYMBOLS are items, 1 to 31 character long whose first character is a letter (A thru Z) and subsequent characters are the letters A thru Z and numbers 0 thru 9. They used to represent an address or value. Embedded underscores and colons are ignored and do NOT count toward the 31 character limit. Upper and lower case may be used interchangeably. SYMBOL and S_y_m_b_o_l: are the same. Labels are optional for all statements except MARK an d DATA. When omited from an EQU statement, the value of the resolved expression wiil be printed, but will not be retained. Labels on a line by themselves are assigned the value of the current assembly address. NO reserved word (opcode, directive, operand or condition code) may be used as a label. Labels do not have to begin in the first character position, but must be the first item in a statement. PAGE 4 OPCODES are Z80 instruction mnemonics or assembler directives. (See Z80 instruction syntax for additional details) OPERANDS are numeric constants, reserved symbols, user defined labels or expressions. Their use is strictly dependent upon the OPCODE used in the source statement. ZM recognizes two special symbols in the operand field. $ The dollar sign is used in an expression to represent the current assembly address. It may be used alone or as part of an arithmetic expression. \ The backslash is used in place of any 8 or 16-bit immediate operand to "cut" the instruction. This allows a formal means of representing and documenting an advanced assembly language technique where the immediate operand for one instruction is itself an instruction. The practice is often used to create a one or two byte relative jump by using an 8 or 16 bit register to load the in-line code, or to flag the entry of a single routine that must later continue with separate procedures. EXAMPLE: ENTRY_1 OR \ ;OR 0AFh makes NZ ENTRY_2 XOR A ;Makes Z True PUSH AF ;Save entry flag (procedure common to both) POP AF ;Retrieve entry flag JP Z,PROC_2 ; (procedure unique to Entry_1) RET PROC_2 (procedure unique to Entry_2) RET EXAMPLE: ERROR_1 LD A,0 LD BC,\ ;Skip-2 ERROR_2 LD A,2 LD BC,\ ;Skip-2 ERROR_3 LD A,4 (Continue with common routine) PAGE 5 NUMERIC CONSTANTS are literal values 1 to 31 characters long whose first character is always a number (0 thru 9). Embedded underscores and colons are ignored and do NOT count toward the 31 character limit. Both upper and lower case may be used interchangeably. A suffix is used to indicate the desired base. Any overflow while evaluating a number is IGNORED, with only the lower 2 bytes being retained. BINARY CONSTANTS are a sequence of 0's and 1's followed by the letter B. OCTAL CONSTANTS are a sequence of the digits 0 through 7 followed by the letter O or the letter Q. DECIMAL CONSTANTS are a sequence of the digits 0 through 9 with no base designation suffix. ( 0d is NOT decimal zero, but an illegal number! ) HEXADECIMAL CONSTANTS are a sequence of the digits 0 through 9 and the letters A through F followed by the letter H. STRING CONSTANTS are a sequence of ANY ascii characters, except line feeds (ascii 0Ah) and carriage returns (ascii 0Dh), enclosed between apostrophes ('). Lower case letters are not converted to uppercase, nor are tab characters (ascii 09h) expanded within the assembled code. Tabs are, however, expanded on the printed listing. An apostrophe may be included within a string by immediately following it with a second one. To include an apostrophe at the end of a string requires three in a row (one to indicate end of string). A string constant containing a carriage return (ascii 0Dh) or line feed (ascii 0Ah) will generate a fatal error for that statement. String constants may NOT be used in an arithmetic expression. CHARACTER CONSTANTS are a SINGLE ascii character, except line feed and carriage return, enclosed between apostrophes ('). Lower case letters are not converted to upper case. An apostrophe may also be quoted ('''). Character constants may be used in an arithmetic expression (the assembler assigns a zero value to the most significant byte). EXPRESSIONS are a sequence of constants and user defined labels separated by arithmetic or logical operators. During assembly each expression is evaluated in a strict left to right sequence and reduced to a single word (two byte) value. Any overflow during evaluation is ignored. PAGE 6 OPERATORS: [ ] Brackets are used in an expression to control the strict left to right evaluation process, or to make the expression easier to read. Remember that Z80 syntax uses parentheses "( )" to denote memory addressing and are therefore not an integral part of an expression. An expression contained in brackets is treated as a single item. + ADDS the next item to the current value (may also be used as a unary operator). - SUBTRACTS the next item from the current value (may also be used as a unary operator). * MULTIPLIES the current value by the next item. & Logically ANDs the current value with the next item. # Logically XORs the current value with the next item. < SHIFTS the current value left the amount of the next item. High order bits are discarded and low order bits are replaced with zeros. > SHIFTS the current value right the amount of the next item. Low order bits are discarded and high order bits are replaced with zeros. ! Compares the current value with the next item and keeps the LARGER of the two. = Sets the current value TRUE (-1, all bits set) if the current item and next item are equal, otherwise sets the current value equal to zero. ^ Is a unary operator used to create an ascii control character. It must exactly precede (no spaces) the unquoted character. (e.g. ^Z or ^z give a control Z) @ Is a unary operator designed to return the integer value from a memory location at assembly time. Its use should be restricted to very special occasions since the resulting code will function properly only if the same values exist at runtime. Its primary use is to create system specific extensions, or overlays. EXAMPLE: LD HL,(06) ; Runtime BDOS entry LD DE,@6 ; Assembly Time BDOS entry OR A SBC HL,DE ; test runtime compatibility JP NZ,IMPROPER PAGE 7 ? Is a kludged operator for use with MARK and IF directives to provide a primitive library capability that assembles only required functions. MARK symbol = ? will create symbol if it does not exist, otherwise it does nothing. IF? symbol is TRUE only if symbol has been previously defined. EXAMPLE: (main program) MARK CON_INP = ?, PRINT = ?, ...etc INCL B:LIBRARY.C13 (library source) IF? PRINT PRINT MARK CON_OUT = ? (code for print subroutine) ENDIF ; PRINT subroutine IF? CON_OUT CON_OUT (code for con_out subroutine) ENDIF ; CON_OUT subroutine ADDRESSING involves the Z80 registers, memory references and expressions used in the operand field of a assembly source statement and are covered in greater detail in the many books on Z80 assembly language programming. The main inconsistency amongst these texts is the form used to address 8-bit Z80 arithmetic and logic instructions. Some use only a single operand, omitting the A-register from the source statement entirely. Another uses two operands only for those instructions having a 16-bit counterpart and one operand for the remaining instructions. A third method requires two operands for all 8-bit arithmetic and logic instructions. Since chosing one of these technique depends upon personal preference, ZM will recognize and process both the first and third. This means you may chose to use two operands, or a single operand for all 8-bit arithmetic and logic instructions. A record is kept on the particular method used, and if not consistent, will generate a single warning message. NOTE: ZM also recognizes INTEL style port i/o instructions ( IN nn and OUT nn ) as well as their ZILOG counter parts ( IN A,(nn) and OUT (nn),A ) and includes their use when generating the 8-Bit mixed address warning. PAGE 8 DIRECTIVES are commands to direct the assembler during the assembly process and have no meaning to the Z80 processor. EQU assigns the value of an expression to a label. If there is no label, the value will appear on the listing without error, but the value is not retained. label EQU expression EQU expression DEFS and DS define storage by reserving the the number of bytes for storage represented by the expression. If the expression is not resolved, ZM will display an appropriate message and terminate assembly after completing the first pass. DS expression DEFS expression DEFB and DB assemble an expression a byte at a time. The expression may be arithmetic or string. Supports multiple expressions seperated by comas. DB expression, expression DEFB expression, expression DEFW and DW assemble an expression a word at a time (Z80 fashion with LSB first). Supports multiple expressions separated by comas. DW expression, expression DEFW expression, expression DEFM and DM assemble one or more expressions a byte at a time. The expressions may be arithmetic or string, or a combination of both. The length of the assembled code is placed at the current assembly address followed by the code itself. DM expression,expression DEFM expression,expression ORG initializes the assembly address to the value of the expression. A label on this line will be assigned this value. If the expression is not resolved, ZM will display an appropriate message and terminate assembly after completing the first pass. ORG expression PAGE 9 RUN accepts the value of an expression as the logical execution address. An offset is then determined and used to define all subsequent labels and in evaluating the assembly operand "$". This allows assembling code that will be moved from the current physical address to be executed at a different address. Uses include ROM resident code and bank switching requirements. A label on this line will be assigned the assembly address before the RUN evaluation. If the expression is not resolved, ZM will display an appropriate message and terminate assembly after completing the first pass. RUN expression ;execute at expression RUN $ ;execute at physical EXAMPLE: ORG 100h LD HL,LoMem LD DE,HiMem LD BC,CodeLength LDIR JP HiMem LoMem RUN 8000h HiMem ( code to execute at address 8000h) CodeLength equ $-HiMem INCL merges another source file with the current one. The file name can contain only the letters A to Z and numbers 0 to 9. An optional drive identifier may be given. If no file type is specified, a null type is assumed. Once the end of file or END directive is reached, assembly will resume with the statement following the INCL. The included file may also contain INCL directives. ZM will search for the included file on the designated drive, default drive, drive A: and internally defined drive. You will be allowed to change disks if the file cannot be found. Do NOT change the disk that is to receive the .COM or .HEX file as it will cause a CP/M disk write error when ZM attempts to write the file to disk. Prompting continues until the file is found, or a ^C is entered. INCL <.type> END marks the logical end of a source file. Assembly will NOT proceed beyond that point. The END statement is optional. If not used, assembly will continue to the physical end of the file. END PAGE 10 LIST turns the listing ON or OFF only if the "L" option was requested. A non-zero expression enables the listing, and a zero disables the listing. Statements containing errors are always listed with their associated messages regardless of the LIST setting or "L" option. LIST expression IF, ELSE, and ENDIF provide conditional assembly. When the evaluated expression is NOT zero, all statements will be assembled until the corresponding ELSE or ENDIF is reached. The ELSE directive is optional. IF's may be nested seven deep. EXAMPLE: IF expression1 (following statements will assemble only if the expression1 is NOT zero) IF expression2 (following statements assemble only if expression1 is NOT zero AND expression2 is NOT zero) ENDIF (following statements assemble only if expression1 is NOT zero) ELSE (following statements assemble only if expression1 is ZERO) IF expression3 (following statements assemble only if expression1 is ZERO AND expression3 is NOT zero) ELSE (following statements assemble only if expression1 is ZERO AND expression3 is ZERO) ENDIF (following statements assemble only if expression1 is ZERO) ENDIF (assembly resumes in a normal manner) MARK sets a label to the current assembly address or to the value of an expression following an equal sign "=". If the label has been previously defined and not marked, an error will occur. MARK supports multiple labels seperated by commas. MARK'd labels may be used in any desired manner. They differ from normal labels in that they may be reused. The most recently defined value is used when a marked label appears in an expression (see ? operator). MARK label1,label2 = expression, ...etc PAGE 11 DATA exists both as a directive and as a predefined label. The directive assigns the current value of DATA to a label, then reassigns DATA = DATA + expression This allows defining internal data overlays or data areas outside the physical program. Using DATA without a label will cause a fatal error (missing data). (See user defined sysbols for additional information). label DATA expression MSG evaluates an expression similar to a DEFB and displays it on the console. The expression used must contain all necessary screen control characters, including carriage return and line feed. A dollar sign ($) is the only character that may not appear in the evaluated text. No text will appear afterward, and no error will be generated. GET Accepts 1 to 80 characters from the console and appends them to the end of the current statement. The statement is then assembled as usual. Remember to leave any necessary spaces or puntuation at the end of the incomplete statement. Use MSG to provide the necessary prompting. MSG 'ENTER PRINTER SELECTION:', cr, lf, lf MSG '1. Epson mx-80/100', cr, lf MSG '2. Okidata 82a', cr, lf MSG '3. Anderson Jacobson', tab GET MARK PRINTER = IF Printer =1 (epson code assembles here) ENDIF IF Printer =2 (okidata code assembles here) ENDIF IF Printer =3 (anderson code assembles here) ENDIF (normal program code continues here) PAGE 12 PREDEFINED USER SYMBOLS DATA is a progressive counter used with the DATA directive. It is NOT altered between passes, therefore it MUST be initialized with the MARK directive before it is used. EXAMPLE: ORG 100H MARK DATA, LOOP CALL INITIALIZE DB 'Initial Program signon message$' DB 'Additional text for "TYPE .COM"', 1AH FCB2 DATA 33 COUNT DATA 2 ORG DATA ! $ FCB2 overlays the beginning of the program at 100h and COUNT is assigned 121h. The assembly address is then adjusted to the larger value of "$" or "DATA". IX and IY are used to evaluate memory references using their respective index registers. They must always be defined using a negative value. EXAMPLE: FLAGS DEFB 0 ;One byte flag variable IX EQU -$ ;<--<< IX BASE ADDRESS <--<< TEMP DEFW 0 IX has been defined as the current assembly address. SET 0,(IX+FLAGS) will assemble correctly and is the same as SET 0,(IX+FLAGS-BASEX) used with the following: EXAMPLE: FLAGS DEFB 0 ;One byte flag variable BASEX EQU $ ;<--<< IX BASE ADDRESS <--<< TEMP DEFW 0 NOTE: Loading the index register must use the negative of these symbols. LD IX,-IX ;Initialize IX base position NOTE: Since the predefined symbols IX and IY are initially zero, NOT using them will cause assembly to take place in the usual manner. If you do use them, remember they are redefinable and affect only those expressions FORWARD of themselves. Also realize that the beginning of the file is AFTER its END during the second pass. If you plan on using ANY redefinable symbol, but expect them to be zero at the beginning, MARK THEM BEFORE YOU SET THE ORIGIN or EQUATE THEM TO ZERO ! PAGE 13 _ _ _ _ _ _ _ _ _ _ _ _ _ E R R O R S _ _ _ _ _ _ _ _ _ _ _ _ _ There are three types of errors: Terminal, Fatal and Warning: TERMINAL errors terminate the program! All Terminal errors are displayed on the console and control is immediately returned to CP/M. Fatal errors result in the offending source statement not being processed. NO CODE IS GENERATED! WARNINGS are provided when the integrity of the assembled code is questionable. In other words, what you got, might not be what you wanted! Warning and Fatal error messages are always displayed with the offending source statement, even if the "L" option was not selected. The format includes the current file name if it has not yet been displayed. The offending statement is then printed, followed by a line of carats (^) to indicate those points that caused ZM to choke. The appropriate warning and fatal error messages are then lsited. Finally, the current statement number, which matches WordStar's FL number, or ED.COM's line number, is printed. Any relationship between the carats and the ordering of error messages is purely coincidental. EXAMPLE: SOURCE FILE: JUNK.PDQ db tab,'LINE OF TEXT',0D,0Ah, ^ ^ ^ -- WARNING -- 17: BAD NUMBER 15: UNDEFINED LABEL *** FATAL *** 1: MISSING INFORMATION - Line No 1263 - _______________________________________________________________ TERMINAL ERRORS: Assembly stops and control is returned to CP/M. USE: ZM