The Code Machine instruction manual ©1986 by Picturesque Converted to text by Gerard Sweeney (www.the-tipshop.co.uk) for World of Spectrum (www.worldofspectrum.org), 26/01/05. I do NOT give permission for this text reproduction to be used/stored on "commercial" or profit-making medium such as CD-ROMs. Frankly, we in the Speccy community are all sick of leechers making money out of our hard work. Note that I was unable to read the last three parts of "blocked" text on the lower section of page 18, so have hazarded a guess that they say (BC) (DE) and (HL) respectively. I'm sure the Speccy scene would appreciate it if you could correct this, if required. The page breaks (---------) do not appear in the original manual. They're there purely to display where each page ends. Best viewed with a non-proportional font. ------------------------------------------------------------------------------- THE CODE MACHINE ©1986 by Picturesque All rights reserved. This book and the accompanying computer program are copyright. No part of either this book or the accompanying computer program may be reproduced, copied, lent, hired, or transmitted by any means without the prior written consent of the publishers. Published by: Picturesque, 6 Corkscrew Hill, West Wickham, Kent BR4 9BB ------------------------------------------------------------------------------- CONTENTS INTRODUCTION SECTION 1 - THE MONITOR Loading and Customising Access to the Monitor Prompt and Cursor Command Modes MONITOR COMMANDS: M - Display contents of memory location X - Escape $ - String entry I - Insert D - Delete A - Area relocate F - Fill an area with a given value P - Print Hex dump Z - Disassembler N - Number conversion Y - Return to Basic Example program for running and debugging commands B - Breakpoint J - Jump and Execute K - Break restore R - Register display C - Breakpoint Continue T - Trace (Single Step) S - Search The MONITOR in practice Summary of MONITOR commands SECTION 2 - THE ASSEMBLER Loading and Customising The Editor Keyboard Screen Display Entering a line Editor Commands LIST EDIT AUTO NEW RETURN to Basic RENUM DELETE COPY Comment lines ------------------------------------------------------------------------------- The Assembler The Object Buffer Numbers ASCII Characters Arithmetic Labels EQU DEFL Label Slicing JR/DJNZ Assembler Directives ORG END DEFB DEFW DEFS DEFM PRNT Assembler Commands ASSEMBLE CLEAR CONTINUE label Data storage commands Cassette routines SAVE VERIFY LOAD Microdrive commands Network commands RS232 commands Assembly from Cassette or Microdrive Saving a section of Source Code Loading a section of Source Code Verifying a section of Source Code Assembling a multi-section Source Code File Error Messages Summary of ASSEMBLER commands SECTION 3 - USING "EDITAS" AND "MONITOR" TOGETHER APPENDIX A - Z80 MNEMONICS ------------------------------------------------------------------------------- INTRODUCTION CODE MACHINE is a full feature Machine Code programming development package consisting of an Editor/Assembler and a separate Monitor/Disassembler Both programs are entirely self-contained, and are written entirely in Machine Code. The Editor/Assembler (called "EDITAS") will allow you to enter and edit Source Code listings (mnemonics and label names); to produce Object Code (the actual Machine Code); to print your Machine Code listings onto a printer; and to Save and Load Source Code or Object Code. The Monitor/Disassembler (called "MONITOR") gives you all the commands you need to test and debug your Machine Code programs, as well as facilities to investigate the inner workings of your Spectrum. You will find that both programs are very quick and easy to operate, which makes CODE MACHINE an ideal programming aid for beginners and for experienced Machine Code programmers alike. If you are new to Machine Code programming, you will need to purchase a book to teach you how to write in Machine Code - and there are several available to choose from. Machine Code is not an easy language to write, and it is beyond the scope of this manual to teach the subject, but, used in conjunction with a good book, CODE MACHINE will help you to understand how Machine Code works, and where you are going wrong. ------------------------------------------------------------------------------- SECTION 1 The MONITOR DISASSEMBLER Version 3.1 Loading Connect your Spectrum to a T.V., cassette recorder, and ZX printer if you own one, as described in the Sinclair manual, and switch on. The MONITOR loads from the cassette in the same way as a Basic program. Set the volume control to about half volume and set the tone control to maximum treble. Type LOAD "". Put the cassette into your player with Side A uppermost. Start the cassette in play and press ENTER. As with all commercially recorded cassettes, you may find that you have to experiment until you find the optimum replay level for this tape. Make a note of the volume setting you find successful, for future use. The chances of a bad load are reduced if you observe the following:- 1) Regularly clean the record/replay head of your cassette recorder, using one of the proprietary cleaning kits. 2) Clean the rubber pinch wheel and the capstan spindle that it makes contact with. 3) Use a cleaning kit supplied with a liquid cleaner that you apply with a cotton wool swab. This type is far more effective than the cleaning cassette type. 4) Disconnect the 'Mic' lead to the cassette recorder when loading. The program loads in two parts and auto-runs. You should follow the screen messages for starting and stepping the cassette. The MONITOR is fully relocatable in memory and the basic loader will first ask you to supply a loading address. Type in this address and press ENTER, OR If you want to load the MONITOR to the highest available area of memory, then type 0 and press ENTER. RAMTOP is set to one byte below the load address, and the machine code is loaded into memory. The lowest address that you can normally load to is around 27700, and the highest is 57778. Unpredictable results will occur if you try to load to a much lower or higher address. Once loaded, the MONITOR can be customised to work with the following range of Printer interfaces: 1). ZX Printer 2). RS232 via Interface 1 3). Kempston E Centronics 4). DK'tronics Centronics 5). Micro Peripherals Centronics 6). Euroelectronics LPRINT 7). Tasman type A Centronics 8). Tasman type B Centronics 9). Morex Centronics 2 ------------------------------------------------------------------------------- Enter the number of the option that you require and press ENTER. If you select Centronics options 4). to 9). you will need to restart the cassette again to load in the correct printer routine. You will then be asked to state whether your printer gives an automatic Line Feed after a Carriage Return. If it does, select option 1, otherwise select option 2 and the Monitor's print routines will be set to send a separate Line Feed, (If in doubt about this you should refer to the operating instructions supplied with your Printer. It is usually possible to select this feature by means of switches inside your printer). Having customised your program for your printer, you will then be given the option of making a copy of the customised program onto a cassette or onto a Microdrive Cartridge. (Microdrive Cartridges are NOT supplied). If you intend Saving onto Microdrive, you should make sure that you have a Formatted Cartridge with at least 11K of spare capacity available BEFORE you start customising the program. The customised copy is saved in two parts: a Basic loader and the machine code; and the copy is also fully relocatable on subsequent loading. It does not however offer the printer options or the save options again. If the Basic loader stops with an error, or if your Spectrum crashes, you have almost certainly supplied a load address that is too low. If the Basic is intact, you can restart it with GOTO 10 followed by ENTER, but it is safer to switch off and start again. |-----------------------------------------------------------------------------------------------| | WARNING | | | | THIS PROGRAM IS COPYRIGHT and ONE COPY ONLY may | | be made for your OWN PERSONAL USE. | | | | It is illegal to sell copies or to give copies to friends. | |-----------------------------------------------------------------------------------------------| The basic loader program of the customised MONITOR is saved with the name of "MONITOR" and it will auto-run. It should be loaded from cassette with LOAD "MONITOR" or LOAD "" To load from Microdrive, use LOAD *"m";n;"MONITOR" where n is the drive number. Having successfully loaded, the MONITOR will display the address that you must use to access it from Basic. You should make a note of this address so that you can access the MONITOR from Basic later. At the end of the loading sequence you will be returned to Basic so that you can load your own Basic or machine code, or load the Assembler. Remember that RAMTOP is set BELOW the MONITOR. You can move RAMTOP to a higher value with the Basic CLEAR command, but if you do, you run the risk of corrupting the MONITOR with Basic commands. NB. For the purposes of the examples in this section of the manual, it has been assumed that the Monitor has been loaded to the highest available part of memory. 3 ------------------------------------------------------------------------------- Access to the Monitor Access the MONITOR using the address shown at the end of the loading sequence The MONITOR will display Press BREAK for Monitor on the bottom line of the screen. On pressing the break key (shifted or unshifted) the screen is cleared, and the prompt and cursor appear at the bottom of the screen. The MONITOR uses its own internal stack to make its use transparent to your machine code program. These functions will be explained more fully later. Prompt and Cursor The prompt (>) indicates that the MONITOR is waiting to be put into a command mode. It does not appear at the start of every line of the display, but only appears when a command routine has ended, and the MONITOR is watting for a new command instruction. The flashing cursor is visible for the majority of the time, and indicates a request for a keyboard entry,and shows where the result of that keyboard entry will be displayed on the screen. Command Modes The range of commands offered by the SPECTRUM MONITOR are as follows:- M Display a memory location and its contents, and change its contents. X Escape from a command mode to the start of the MONITOR, (operates on all command modes except R and K.) A Move an area of RAM to a new location. F Fill a specified area of RAM with a specified byte value. I Insert up to 255 bytes into a machine code routine. D Delete up to 255 bytes from a machine code routine. J Jump to a specified address, and start executing the routine there. B Set a Breakpoint in a machine code routine, to return control to the MONITOR. K Restore codes after a Breakpoint has been passed. R Display the contents of the CPU registers. C Continue operation of a routine after a Breakpoint. Y Return to Basic. P Hex dump to Printer. $ Text entry. Z Disassemble any area of memory into Z80 mnemonics either to the screen, or to both the screen and the ZX Printer. N Number conversion. Hex to Decimal or Decimal to Hex. T Trace (or Single Step) with front panel display. S Search for HEX or ASCII values in memory. All command codes are accessed by a single keystroke denoted by the letter in the left hand column above. All keyboard entries are checked for validity, and at any given time, only the permitted keyboard entries are accepted by the MONITOR; any other key press is rejected and the keyboard is scanned again. All numeric inputs and displays are Hex to facilitate the entry of Z80 Op. Codes. The number conversion routine simplifies access to Hex addresses. 4 ------------------------------------------------------------------------------- All references to addresses and their contents in these instructions will be in Hex, and will be shown as a two or four figure number, without the suffix 'H'. Each command will now be dealt with in detail, with examples, to clarify its operation. M - Display contents of memory location The screen should still only show the prompt and cursor in the bottom left corner. Type M An inverse M (blue letter on a white square) will appear immediately to the right of the prompt, and the cursor will move along the bottom line by one character space. Now type in the Hex value of the address that you wish to inspect, say 6000. (You can use the MONITOR to inspect or change any memory location in RAM or ROM, although you cannot alter the ROM values.) The address appears on the screen as you type it in, and as soon as you have typed the fourth digit, a two character Hex number appears on the screen to the right of the address, showing the Hex value of the contents of that memory location. >M6000 00 - The cursor has now moved on, leaving a space after the two contents digits. Now type FF. >M6000 00 FF - This has loaded the Hex value FF into memory location 6000. The value is loaded into the location automatically after you type the second digit. Now type ENTER. >M6000 00 FF 6001 00 - The original line with the prompt has scrolled up one line, and 6001 00 is now displayed on the bottom line. At all times, the MONITOR operates with a scrolling screen, and new information is always displayed on the bottom line. Typing ENTER displays the next memory location and its contents. To enter a value in this new address, enter the two Hex digits, or type ENTER again for the next memory location. Now let's check that FF really has been loaded into address 6000. Type M >M6000 00 FF 6001 00 M - The screen has scrolled up one line, and the inverse M has reappeared on the bottom line. 5 ------------------------------------------------------------------------------- Typing M after a Hex address, data entry, or ENTER, allows you to re-enter the M command routine at the start. To re-enter the M command in the middle of typing a Hex address, type X, to escape, and M to enter the M command. Now type 6000 >M6000 00 FF 6001 00 M6000 FF - The contents of 6000 are shown as FF. To summarise the M command so far you can sequentially step through memory locations using ENTER and change the value of the contents of each address, or, by typing M again, you can define a new starting address. To re-enter the M command with a partly typed address on the screen, type X to escape the prompt, and then type M to enter the M command. Now type 00 to clear the contents of address 6000. You will notice that the cursor is still visible on the bottom line of the screen to the right of the 00 just entered. Although address 6000 now contains the value 00, (the value was changed immediately you typed the second 0) you can change it again if you wish. So, if you enter an incorrect value, and realise what you have done before you press ENTER, you can correct your mistake without having to specify the address again. In fact, you can make only two attempts at entering a value before the routine returns you to the prompt and cursor, when you will have to type M to re-enter the M command. Remember, that in the M command, ENTER only has the effect of stepping on to the next memory location, whereas in other commands (where applicable) ENTER causes the operation to be executed. Imagine that you have just entered a machine code routine from, say 6000 to 6200, and you realise that you need to change the value of one byte somewhere near the middle of the routine, but you do not know the precise address. You could spend a long time guessing addresses and looking at their contents, or repeatedly pressing ENTER until you find the right byte. But if you type M, to re-enter the M command, and look at the contents of an address somewhere near the beginning of the routine, then press ENTER, and hold it pressed, after about 1 1/2 seconds the screen will start scrolling quite fast, and will rapidly display successive locations until you release ENTER. In this way you can quickly scan through a routine until you find the byte you are looking for. To effect the alteration, having released ENTER, you will again have to type M xxxx to re-enter the M command at the correct address, and then change the contents of that address. The 'M' command, (and $ command, described below are the only commands that use the repeating key facility. X - Escape The X command allows you to escape from a command mode and returns you to the monitor key scan routine. Type X 6 ------------------------------------------------------------------------------- The screen will scroll, and the prompt and cursor will reappear on the bottom line of the screen. You can now enter any of the MONITOR commands. All command routines, with the exception of R (display registers) and K (breakpoint restore), will accept X as an escape command at any time up to the point of execution. $ - String Entry This command operates in a similar fashion to the 'M' command, but allows you to enter text directly from the keyboard. It is by no means a word processor, but it offers a much simpler method of text entry than by converting letters to their character codes, and entering the codes individually with the 'M' command. The command takes the form: '$aaaa' where $ is the command mode, and aaaa is the starting address of the text block. Let us enter a simple message into a free area of RAM. Type $ (Symbol shift and '4') to enter the $ command. An inverse $ will appear on the bottom line of the display. Type 6100 The address is displayed as normal. Up to the point of entering the last digit of the address, the X command will return you to the prompt. But from now on, this command is slightly different from all the others. As you may well want to type 'X' as a string entry, it cannot now be reserved for the escape command. So in this case only, the escape function is accessed by typing STOP (Symbol Shift and 'A'). The word STOP should serve to remind you of which key to press. As you type in each letter of the message, it is displayed on the screen, to the right of the address and its present contents, and the character code is stored in that address. The screen scrolls automatically, displaying the next address and its present contents. You do not need to press ENTER to access the next address. If there is a valid character code in an address, it will be displayed between the address itself and the cursor, otherwise a question mark is displayed. All upper and lower case letters can be entered by use of the Caps Shift key; also punctuation marks and spaces by the use of the Symbol Shift key. The only exception is '$' which is reserved as the command mode. Graphics, user defined characters, and keywords and expressions such as ** cannot be entered directly. Inverse characters must be created by accessing the colour attributes part of the memory relating to the particular screen location. In other words, any single character that appears on a key top and that can be accessed by a single key press or by one level of shift can be entered. Any character normally accessed by the use of the GRAPHICS or EXTENDED modes will have to be entered by using the 'M' command to enter the Hex character code. Now type in the following message: This is "Spectrum MONITOR". 7 ------------------------------------------------------------------------------- (Use Symbol Shift and P for the " marks). Having typed it in, (mistakes included) now review the message: Type $ (Symbol Shift and 4) and re-enter the $ command. Type 6100 the start address. Type ENTER and hold it pressed until the whole message is on the screen. If the message is correct, you can now type STOP (Symbol Shift and A) and return to the prompt. If you have made a typing error, or if you want to put another message at the new starting address, type $, to re-enter the $ command at the beginning, in the same way that the 'M' command is re-entered. You will have to enter the new address before making your correction, or starting your new message. The repeating keyboard with the fast scrolling screen works as in the 'M' command, to allow you to review a message quickly. Remember that, having entered the starting address, the escape command is accessed by typing STOP (Symbol Shift and A). I - Insert If, having written a machine code routine, you find it necessary to add extra instructions in the middle of that routine, the Insert command (I) allows you to insert up to 255 bytes at any point, and automatically moves up memory a specificed area of RAM by the number of bytes you wish to insert. Insert command takes the form 'I aaaa bbbb nn' where I is the Insert command mode, aaaa is the Hex address of the first byte of the insertion, bbbb is the Hex address of the highest byte in RAM of the block of memory to be moved, and nn is the number of bytes to be inserted, in Hex. Example Type X to restore the prompt and cursor to the bottom line, and then, using the M command, enter the following consecutive values into memory: 6000 00 6001 01 6002 02 6003 03 etc. . . . . 600A 0A 600B 0B 600C 0C 6000 0D 600E 0E 600F 0F 8 ------------------------------------------------------------------------------- (The values entered into these locations are purely for a demonstration o1 the Insert and Delete commands, and, if run, will cause the ZX SPECTRUM to crash). In the above example, the start of the imaginary routine is 6000 and the end is 600F. We will now insert 5 bytes, the first new byte to be at 6004. Type X to restore the prompt and cursor. Type I to get into the Insert mode. Type 6004 the address of the first byte of the insertion. Type 600F the address of the highest byte to be moved. Type 05 the number of bytes to be inserted (Hex). At any time up to this point, you can type X to escape from this command mode, as no change to RAM has occurred yet. Indeed, if you make a typing error at any time, you must type X, and start the command again. If you have entered the Insert example correctly, you can now type ENTER to effect the insertion. The screen will scroll up one line, and the prompt and cursor will return to the bottom line. The insertion has been completed. Using the M command, check through the 21 locations from 6000. Addresses 6004 and 6008 inclusive will now contain the value 00. and 6009 to 6014 will contain the values 04 through to OF. When using the Insert command, any absolute addresses in the remainder of the routine that referred to the area that has been relocated, will have to be changed to maintain correct operation of the routine. D - Delete This command has the opposite effect to Insert, and takes the form 'D aaaa bbbb nn', where the D is the Delete command mode, aaaa is the address of the first byte to be deleted, bbbb is the address of the highest byte to be moved down RAM, and nn is the number of bytes to be deleted. Assuming that the result of the Insert example is still in memory, let us now move the area of RAM from 6009 to 6014 back to its original place. Type X to restore the prompt and cursor. Type D to enter the Delete command. Type 6004 the start of the area to be deleted. Type 6014 the end of the area to be moved. Type 05 the number of bytes to be deleted (Hex). Type ENTER to effect the deletion. The prompt and cursor will reappear on the bottom line, and the deletion will be complete. Now check through addresses 6000 to 6014. using the M command. The contents of these locations will be as they ware before the Insert example, and locations 6010 to 6014 will have been loaded with the value 00. Again, any absolute addresses relating to the area of RAM that has been moved by Delete, will now need to be changed. 9 ------------------------------------------------------------------------------- A - Area Relocate The 'A' command block moves a specified area of RAM, and takes the form: 'A aaaa bbbb cccc' where A is the Area Relocate command, aaaa is the present start address, and bbbb is the present end address of the area to be moved, and cccc is the new starting address. Assuming that the example used for the I and D commands is still in memory, let us now move the whole area from 6000 to 600F up memory, to start at 6200. Type X to restore the prompt and cursor. Type A to enter the Area Relocate mode. Type 6000 the start address of the area to be moved. Type 600F the end address of the area to be moved. Type 6200 the new start address. Type ENTER to effect the move. The screen scrolls up one line, and the prompt and cursor return to the bottom line. The move is complete. Using the M command, check that addresses 6200 to 620F have been loaded with the same values as those still remaining in addresses 6000 to 600F. This routine will allow you to move up or down memory, from any original starting address to any new starting address, even if the new area overlaps the original area. The original area (unless over-written by the move) is not changed. Try moving the area from 6000 to 600F to a new start address of 6008 and then move it back again. A word of warning: Most MONITOR commands that allow you to alter the values in memory locations, will operate on the area of RAM containing the MONITOR routines. Always check carefully that you are not about to corrupt the MONITOR, which occupies an area of memory almost 8K long from the load address. (See memory maps for exact length). F - Fill an area with a given value The Fill routine allows you to enter the same byte value into a given area of RAM, and takes the form: 'F aaaa bbbb xx', when aaaa and bbbb are the start and end addresses respectively of the specified area, and xx is the value to be entered. Type X to restore the prompt and cursor. Type F to enter the F command. Type 6020 the start address. Type 6100 the end address. Type AA the value to be entered (Hex). Type ENTER to effect the Fill. The screen scrolls, and the prompt and cursor appear on the bottom line of the screen. The fill is complete. Now use the M command, with ENTER kept pressed, to verify that each byte from 6020 to 6100 inclusive has a value of AA. 10 ------------------------------------------------------------------------------- P - Print Hex Dump This command allows you to produce a Hex Dump of any section of memory onto the screen or your Printer. It takes the form 'P aaaa bbbb' where P is the command name, aaaa is the Hex address of the first byte to be printed, and bbbb is the Hex address of the last byte you want printed. The display is produced thus: 0000 F3 AF 11 FF FF C3 CB 11 0008 2A 5D 5C 22 5F 5C 18 43 0010 C3 F2 15 FF FF FF FF FF Each line shows the Hex contents of eight successive locations, with the Hex address of the first byte shown in the left hand column. The routine will only print complete lines, and if the end address that you specify is part of the way along a line, it will print up to the end of that line. If the prompt is not visible on the bottom line of the screen, type X, otherwise access the command by typing P followed by the address from which you wish to start the display. If you want to define the address at which the display will stop, enter that Hex address following the start address, otherwise press ENTER. You will then be asked to select Print options for this command. Respond with: N if you require a screen output. / (Symbol Shift + V) if you requires Printer output. This will direct the printer output to the ZX Printer or via a Centronics Interface, depending on the way the program was initially customised. * (Symbol Shift + B) If you require the output via the RS232 facility of Interface 1. (If Interface 1 is not connected, this will produce a Basic error 'i', and leave you in Basic). To use a Printer with the Interface 1 RS232, use the Basic FORMAT command to set the Baud Rate for your printer. The Monitor uses the X type of RS232 output, sending a Carriage Return and a Line Feed. (See Sinclair's Microdrive Manual). For screen output, 16 lines of screen information are displayed, whereupon you can press ENTER to display the next 16 lines, or press X to escape. When using a Printer option, it is recommended that you define an end address, as the printer option will continue operating until the end address is reached, or until the BREAK key (with Caps Shift) is pressed. The end address defaults to FFFF Hex If it is not specified. Pressing the BREAK key (with Caps Shift) will give a basic error message and leave you In Basic; ONLY if you are using the ZX Printer or RS232. Breaking out of a Centronics Printer routine returns you to the main Monitor prompt. Z - Disassembler This command will disassemble any part of RAM or ROM, either to the screen or to the Printer. It provides a display that includes the Hex address of the first byte of the instruction, the hex values of the bytes that relate to that instruction and the Z80 mnemonic for that instruction. The full set of Z80 mnemonics can be disassembled. The command takes the form: 'Z aaaa bbbb' where 'Z' is the command mode, 'aaaa' is the Hex starting address and 'bbbb' is the Hex end address of the part of memory you wish to disassemble. Type Z to access the command Type 0000 the start address (e.g. start of ROM). 11 ------------------------------------------------------------------------------- You can now either type in an end Hex address where you want the disassembly to stop, or you can press ENTER to achieve an open-ended disassembly in the same way that the P command operates. You will be given the same Screen/Printer options as described in the P command above. Again the end address defaults to FFFF Hex if it is not defined. If you attempt to disassemble any part of Spectrum Monitor, an error message 'INVALID ADDRESS' is displayed. The disassembly will appear as follows: >Z0000 0020 PRINTER? (N / *) 0000 F3 DI 0001 AF XOR A 0002 11FFFF LD DE,FFFF 0005 C3CB11 JP 11CB 0008 2A5D5C LD HL,(5C5D) 000B 225F5C LD (5C5F),HL 000E 1843 JR 0053 0010 C3F215 JP 15F2 0013 FF RST 38 0014 FF RST 38 0015 FF RST 38 0016 FF RST 38 0017 FF RST 38 0018 2A5D5C LD HL,(5C5D) 001B 7E A,(HL) 001C CD7D00 CALL 007D ENTER for more; X For END 16 lines of disassembly will be displayed when using the screen only, followed by the message: ENTER for more; X for end. Pressing ENTER will display the next 16 lines, unless the end address is reached, when the prompt and cursor will be returned. Typing 'X' in response to the above message will also return the prompt and cursor. If you are disassembling to a Printer, the routine continues uninterrupted until it reaches the end address. The printer can be stopped early by pressing CAPS SHIFT and BREAK. If a Centronics Printer option was selected on customising the MONITOR, BREAK will return you to the Monitor's prompt and cursor. If you are using a ZX Printer or an RS232 printer, the BREAK key will return you to Basic. You will then need to re-access the Monitor using the address shown at the end of the loading sequence. All disassembled addresses and values are in Hex. Relative jumps show the address to which the jump will go, with the offset value shown in the Hex coding (or that instruction. N - Number Conversion This routine will convert Hex numbers to Decimal or vice versa. Type N The Number command. The screen will display: NUMBER H/D? 12 ------------------------------------------------------------------------------- Type H (for Hex) or D (for Decimal) to indicate the number system of the number you wish to convert. Type H to convert a Hex number to a Decimal. The screen will scroll, and show 'H' (followed by the cursor). Now enter four Hex digits. (You must enter leading zeros when entering a Hex number). Type 4000 Type ENTER The display will now show: H4000 = 16384 with the prompt and cursor on the bottom line. To convert from Decimal to Hex, Type D instead of H in response to "NUMBER H/D?", and enter your decimal number, without leading zeros. Again type ENTER to produce an answer Y - Return Printed on the 'Y' key is the keyword RETURN, and by pressing mis key, followed by ENTER, when the prompt and cursor alone are visible on the bottom line of the screen, a return to Basic is effected so that you can use any of the Basic commands. As the MONITOR does not have its own Save and Load commands, you will need the Return command to use the Basic Save and Load. using the MONITOR 'Return' command will reset the stack, and enable the Z80 Interrupts, but will not affect the Basic listing or the variables. Example program for running and debugging commands To demonstrate the next live Monitor commands, use the M commands to enter the following short program at 6000 Hex, or at any other convenient location. If you have loaded the MONITOR into memory at the highest available address (by entering 0 as the load address on loading), then you should find that the memory locations at 6000H are not being used and are free for this example. Do not worry if there are already some values in memory as you type in this example. 6000 010000 LD BC,0000 ; Clear BC 6003 110000 LD DE,0000 ; Clear DE 6006 210000 LD HL,0000 ; Clear HL 6009 03 INC BC ; BC = BC + 01 600A 13 INC DE ; DE = DE + 01 600B 23 INC HL ; HL=HL + 01 600C C9 RET ; Return Start 6000 End 600C 13 ------------------------------------------------------------------------------- Having entered Hex codes, go back to 6000 and check that the codes are correct. (Type M 6000 and check the contents of each location). It is recommended that you would normally Save a machine code program before running it in case it crashes, which it is certainly likely to do unless you are an experienced machine code programmer. In this case, there is no real point in Saving the program, but if you wish to do so. refer to the section on "The Monitor in practice". The last line of the routine is a return instruction which it is usual to use at the end of a machine code routine, to return you to Basic. When you are satisfied that you have entered the above program correctly, type 'X' to restore the prompt and cursor. B - Breakpoint This command allows you to temporarily interrupt a machine code program at any point, and return control to the MONITOR, so that you can inspect the values in the CPU registers, and in RAM, and make corrections as necessary. It takes the form: 'B aaaa', where B is the Breakpoint command mode, and aaaa is the address of the instruction that the break will replace, (aaaa must be the address of the first byte of a multi-byte instruction). The opcodes in the three addresses aaaa aaaa + 1 and aaaa + 2 are automatically saved in data bytes within the MONITOR and these locations are then loaded with a CALL instruction to the entry point of the MONITOR. It must be a CALL to maintain correct operation of the stack. On entering the MONITOR at this address, the values in the CPU registers are stored in data bytes within the MONITOR; the Stack Pointer is set to the MONITOR Stack; the message "Press Break for Monitor" is displayed on the bottom line of the screen, in addition to the screen display your program has created. The MONITOR will now wait until you press 'Break' when it will display the prompt and cursor on the bottom line of the screen. You will now be able to use any of the MONITOR commands to check or alter the routine, before returning control to the routine at the point at which the break occurred. As the MONITOR uses its own integral Stack, separate from the Program Stack, there is no danger of over-writing the Program Stack during a Breakpoint. Before running the example just entered, enter a Breakpoint at address 6009. This will have the effect of stopping the program after the registers BC, DE and HL have been cleared, but before they are incremented. If the prompt is not visible on the bottom line, type X, otherwise. Type B the breakpoint command mode Type 6009 the breakpoint address There is no need to type ENTER, as the Breakpoint is set after typing the fourth digit. The screen will scroll, and the prompt will appear on the bottom line. You are now in a position to run the routine up to the breakpoint. 14 ------------------------------------------------------------------------------- J - Jump and execute The Jump command allows you to jump out of the control of the MONITOR to the starting address of any routine that you write, and it takes the form: 'J aaaa' where J is the Jump command mode, and aaaa is the start address of your program. You can run your machine code programs either with the MONITOR 'J' command, or by returning to Basic and using the USR function. Either way, the MONITOR commands are available to you after the Breakpoint. In this example, we will use the 'J' command. Type X to restore the prompt and cursor. Type J to enter the Jump command. Type 6000 the start address. Type ENTER The screen is cleared and the routine will run, and then return to the MONITOR, with the "Press Break for Monitor" message. i) the screen is cleared. ii) the Stack Pointer is set to the program Stack. iii) the start address is put into the Program Counter, and the program is executed. The MONITOR uses its own integral Stack, which is set on entry to the monitor routine, therefore the program Stack, which is set by the Basic initialisation routines when the ZX Spectrum is switched on, must be reset before your program can be run. Item (ii) above does this for you. The use of two stacks helps make the MONITOR invisible to your machine code program. Having run, the program will have encountered the Breakpoint at address 6009, and have displayed "Press BREAK for Monitor". Press the BREAK/SPACE key (shifted or unshifted) to access the MONITOR. The first operation after a Breakpoint should always be to replace the correct byte values to the addresses where the break occurred. K - Break Restore This command restores the correct values into the three bytes overwritten by the Breakpoint command. Type K The screen will show K 6009 and will scroll up one line, displaying the prompt on the bottom line. There is no need to type ENTER. Using the M command, verify that the original codes have been replaced in addresses 6009 to 600B Only one Breakpoint can be entered at any time, so a Break Restore (K) command must be executed before the next Breakpoint command is keyed immediately after a Breakpoint has been encountered. 15 ------------------------------------------------------------------------------- If you enter an incorrect breakpoint with the B command, type K immediately afterwards to restore the original values to the incorrect breakpoint address, and then re-type the Breakpoint. The K command can only restore the last entered Breakpoint. Let us now inspect the CPU registers, to make sure that the program is working as we expect. R - Display values in CPU registers. If the prompt is not visible on the bottom line of the screen, type X, otherwise Type R The screen scrolls up. automatically displaying the CPU register contents thus: > IR 3F24 SZ H PNC A'F' 00 01000100 B'C' 1721 D'E' 369B H'L' 2758 SZ H PNC AF 0F 01010100 BC 0000 DE 0000 HL 0000 IX 03D4 IY 5C3A SP FF42 PC 6009 > There is no need to type ENTER. As you will see, the Program Counter contains 6009, the address at which the Breakpoint occurred. The BC, DE and HL register pairs will all contain 0000. In this example, these are the only registers that we are interested in. The FLAGS registers are shown in BIT form, with the purpose of each flag indicate above. If a flag is SET, a 1 is indicated, and if it is reset, a 0 is shown. Each time the MONITOR is accessed, the current Register values are stored. If these values are not correct, you can change them before continuing. To do this, please read the section on The REGISTER POINTER in the description of the TRACE command. Any changes to the cpu register values stored in RAM during a Breakpoint only take effect after a Jump (J) or Breakpoint Continued (C) command has been executed. Having a) encountered one Breakpoint, b) restored the correct values after the break, and c) verified that the CPU registers have their correct values, we will now enter another Breakpoint, and continue the routine. 16 ------------------------------------------------------------------------------- If the prompt is not visible on the bottom line of the screen, type X, otherwise, Type B 600B This will set a new Breakpoint after the BC and DE register pair have been incremented, but before the HL pair is incremented. C - Breakpoint Continue This command allows you to continue from a Breakpoint, and is executed by typing C followed by ENTER. You can Escape to the monitor by typing X before ENTER. The program being run will continue as if the Breakpoint had never occurred. The screen is cleared; the program Stack is reset; and the CPU registers are re-loaded from their data block before the Breakpoint address is put into the Program Counter, and execution is resumed. Type C Type ENTER The routine wilt run on until it reaches the next Breakpoint, and display "Press BREAK tor Monitor". Type K to restore the bytes occupied by the Breakpoint. Type R to display the registers. You can now verify that the Program Counter contains 600B, the BC and DE register pair contain 0001, having been incremented, and the HL pair still contains 0000. When a routine encounters a Breakpoint, it returns control to the MONITOR with a CALL operation, the return address being stored on the Program Stack, for use by the Breakpoint Continue (C) command. Having encountered a Breakpoint and studied the CPU registers and/or memory locations, one of two situations will occur: 1) Everything will be as you expect, and the program is correct to that point. In this case, you would normally restore the Breakpoint bytes ('K' command) and use the Breakpoint Continue ('C' command) to continue the program to a new Breakpoint or 2) An error will become evident, in which case you would track down the error and correct it, and then, leaving the current Breakpoint set, use the 'J' command to re-run the program up to the same Breakpoint, to check that your correction is successful. The Program Stack operation of the MONITOR allows you to do this providing that, at the Breakpoint, there have been an equal number of PUSHes and POPs, or CALLS and RETs. If the Program Stack is not balanced at the Breakpoint, you will have a cumulative stack imbalance every time you use the 'J' command after a Breakpoint (but not if you use the 'C' command). In this case to restore the Stack to normal once you have traced an error, RETURN to Basic ('Y' command) and re-access the monitor from the beginning, then use the 'J' command to run your program up to the Breakpoint again. 17 ------------------------------------------------------------------------------- Having set a Breakpoint in a routine, you can either use the 'J' command to run the routine, or you can use the RETURN command to go back to Basic, and run the machine code via the USR function. For example, if you have written some machine code as part of a Basic program, which is accessed by the USR function in the Basic program, you can set a Breakpoint using the MONITOR then return to Basic and run the Basic program. When the Breakpoint is reached in the machine code, the MONITOR will be accessed as shown above, and the Breakpoint Continue command will allow the machine code to resume, and eventually return to the Basic program that called it. The MONITOR has been carefully designed to allow this free interchange between Basic and machine code, without upsetting the Stack. T - Trace (or Single Step) The Trace command allows you to execute Machine Code in ROM or RAM one instruction at a time, or in certain specified blocks. But at ALL times, the execution of the Machine Code is strictly under the control of the Trace command, and a crash is almost impossible. Commands such as LDIR (a self repeating block move) can cause a crash by overwriting the Monitor, as can any instruction that writes into memory. Altering the value of the Stack Pointer can also overwrite the Monitor, and reference to the memory map of the new Monitor should help to avoid mistakes. The comprehensive screen display throughout the Trace command gives a permanent display of the CPU register contents, a Disassembly of the current and next instructions, the contents of the last five stack locations, and the contents of specified memory locations. The display Is formed as shown below. STEP 2D28 4F LD C , A IR 3F4C STACK CZ H PNC 0009 A'F' 00 01000100 000D B'C' 1721 10ED D'E' 369B 6C5D H'L' 2756 *3365 CZ H PNC AF 0F 01010100 BC 770F (BC) C3 CB 71 2A A4 DE 5D15 (DE) 00 00 6A 7C 00 HL 2D2B (HL) FD 21 3A 5C AF IX 03D4 IY 5C3A SP FDD3 PC 2D28 M0000 F3 AF 11 FF FF C3 CB 11 2A The Trace command is accessed from the Main Monitor by typing T (when the prompt and cursor are visible on the bottom line of the screen) followed by the 4-digit Hex address of the instruction from which a single stepping is to start. If you do not specify a Hex address, but press ENTER Immediately after typing T, the Trace command is accessed, and the address shown against PC in the register display is used as the starting address. To return to the Main Monitor from the Trace command, type X. The screen will clear, and the Main Monitor's prompt and cursor will appear on the bottom screen line. All register values are passed between the Main Monitor and the Trace command, and you can therefore use all the available commands of the Monitor to debug your machine code. 18 ------------------------------------------------------------------------------- The Trace command contains its own set of commands which are separate from the main Monitor commands, and allow control over a) executing instructions singly; b) running on to a Breakpoint (not the same as a Breakpoint set by the main Monitor); and c) skipping to the end of a subroutine. Any section of code that will only operate correctly when run at full speed (e.g. timing loops, sound output or interfaces to external equipment) will not operate correctly in the Trace command as each instruction is decoded and executed separately. The main Monitor commands for setting a Breakpoint and running the code should be used instead. To demonstrate the trace command, enter the following short routine using the M command in the main Monitor to enter the Hex code shown in bold type. (If you have already accessed the Trace command, type X to exit the main Monitor before entering the example program). 6400 0005 ORG 6400H 6400 212C64 0010 LD HL,642CH 6403 113412 0015 LD DE,1234H 6406 7A 0020 LD A, D 6407 CD1064 0025 CALL 6410H 640A 7B 0030 LD A,E 640B CD1064 0035 CALL 6410H 640E 00 0040 NOP 640F 00 0045 NOP 6410 4F 0050 LD C,A 6411 E6F0 0055 AND 0F0H 6413 1F 0060 RRA 6414 1F 0065 RRA 6415 1F 0070 RRA 6416 1F 0075 RRA 6417 CD2164 0080 CALL 6421H 641A 79 0085 LD A,C 641B E60F 0090 AND 0FH 641D CD2164 0095 CALL 6421H 6420 C9 0100 RET 6421 C630 0105 ADD 30H 6423 FE3A 0110 CP 3AH 6425 3802 0115 JR C,+2 6427 C607 0120 ADD 7 6429 77 0125 LD (HL),A 642A 23 0130 INC HL 642B C9 0135 RET 642C 00 0140 DEFB 0 642D 00 0145 DEFB 0 642E 00 0150 DEFB 0 642F 00 0155 DEFB 0 0160 END 19 ------------------------------------------------------------------------------- The code from 6400 to 640D converts the value held in the DE register pair into four ASCII character codes representing that value, and puts the four character codes into memory at 642C (this location held in HL). The code starting at 6410 and at 6421 are subroutines called during this process. Having entered the code, type X to restore the main Monitor Prompt and then type T followed by 6400. The Trace display will be formed in a similar fashion to that shown above. The STEP mode is automatically selected, and is shown at the top of the screen. Below that is a disassembly of the next instruction to be executed. The Register display shows the current register contents (which could be anything as no instructions have been executed yet). The Stack display shows the last five pairs of bytes on the Stack, with the last value placed on the Stack indicated by the *. The M display line at the bottom of the screen gives a window onto memory locations, and the starting address can be changed at any time by typing M followed by a four digit Hex address. In the example above, it would be useful to see a display of the memory that will eventually contain the four ASCII characters, so type M642C. The M display is updated as soon as the fourth digit is entered and you do not need to press ENTER. While in the Trace command, the address of the next instruction can be changed at any time by typing S followed by the new Hex address followed by ENTER. This restores STEP mode and updates the display ready for execution of the next instruction at the new address. To execute the first instruction (LD HL,642CH) simply press ENTER. The display will now update and show 642C in HL. Alongside that value are shown the contents of the bytes at and immediately following that address. You will see that the disassembly of the first instruction has scrolled up one line, and that the next instruction (LD DE,1234H) is displayed on the second disassembly line. The upper of the two Disassembly lines is always the instruction just executed, and the lower is always the instruction about to be executed. Continue pressing ENTER and STEP through the whole routine, stopping when the NOP instruction at address 640E is displayed on the second disassembly line, and observe the effect on the display of each instruction. The register display of the PC value will ALWAYS show the address of the NEXT instruction to be executed, and the Stack display will only change when the Stack is used (in this case the CALL and RET instructions). At any time you can exit from the Trace command back to the main Monitor by typing X. The screen will clear and the normal Monitor Prompt will be displayed at the bottom of the screen. You may find that you have to press X more than once to do this. For example, if you are in the process of typing in a command within the Trace facility, the first X will clear that command and the second X will access the main Monitor. You may have found that single stepping through the two subroutines became tedious after you had stepped through them once, and proved that they did work. To speed up this process the Trace command contains two functions that can be used to automatically step through sections of your program that have already been proved. They are: (i) BREAKPOINT Do not confuse this Breakpoint function with the BREAKPOINT command in the main Monitor. Setting a Breakpoint while in the Trace command does not alter your program, as it does in the Main Monitor. The Breakpoint address is stored, and after each instruction is executed by the 20 ------------------------------------------------------------------------------- Trace command, the address of the next instruction in your program is compared with the Breakpoint address. If the program address is not equal to the Breakpoint, the next instruction is decoded and automatically executed, until the program address is equal to the Breakpoint address, whereupon the whole display is updated and the STEP mode is accessed. To use the above example to demonstrate the use of the Breakpoint, type X to access the main Monitor and use the M command to write 00 into the four memory locations from 642C Hex. (You do not need to do this to use the Breakpoint, but in this example it will help to clarify what is happening by clearing the ASCII codes already written there). Re-enter the Trace command by typing T6400 and then type B640E, followed by ENTER. This has put the Trace command into BREAKPOINT mode and this is displayed at the top of the screen. Pressing ENTER again will cause the program to be executed under the control of the Trace command until the Breakpoint is reached. The display is then fully updated and STEP mode accessed. While the program was being executed, the only part of the display to be updated was the value of PC in the Register display. Should you have set a Breakpoint at an address that for some reason is never reached (perhaps a conditional instruction that has jumped elsewhere) the constantly changing PC value will indicate that the command is still running. In this case you can escape by pressing CAPS shift and BREAK together, which will access the STEP mode again and update the display showing the address at which the Break occurred. You may find that this leaves unwanted addresses or register contents on the program stack, and an incorrect value for SP in the register display. This will not affect the operation of the Monitor as it uses its own stack. The simplest way to restore the Stack Pointer to its normal value (usually as set by Basic) is to return to Basic (Key Y) and then to re-access the Monitor with the address shown at the end of the loading sequence. (ii) SKIP to RET This function can be accessed at any time while in the STEP mode. Type R and press ENTER. The top line of the display will now show STEP SKIP to RET. Pressing ENTER again will cause the Trace command to execute your program automatically, and stop (in the STEP mode) when it has executed the RET instruction associated with the next CALL instruction. While the subroutine is being executed, the display of the PC register value is the only part of the display to be updated. On completion of the subroutine the whole display is updated and the normal STEP mode is accessed. To demonstrate, type S6400 (assuming that you are still in the TRACE command) followed by ENTER. The display will update and you will be ready to single step from address 6400. Press ENTER three times to execute the first three instructions of the example program. The next instruction will now be CALL 6410. Press R followed by ENTER, to access the SKIP to RET mode. Press ENTER again, and the subroutine at 6410 will be executed in its entirety, including the two CALL instructions within it, and the display will update showing the LD A, E instruction at 640A as the next instruction on the second disassembly line, and the original CALL on the line above. The normal STEP mode will also be indicated at the top of the screen. 21 ------------------------------------------------------------------------------- You can now continue stepping through the program using the ENTER key. So press ENTER to execute the LD A,E, and then press ENTER again to execute the CALL 6410. The next instruction will be shown as LD C,A at address 6410 and is the first instruction in the subroutine. If you now press R and ENTER to access the SKIP to RET mode, a second press on ENTER will execute the program up to the RET associated with the next CALL. The next CALL is at address 6417 (CALL 6421), and execution will stop showing LD A, C at address 641A as the next instruction. Follow this through by referring to the program listing to clarify what has happened. If you use the SKIP to RET function, and a RET instruction is found before a CALL instruction, that RET instruction will cause automatic execution to stop and the STEP mode to be accessed. This can be demonstrated by single stepping through the example program using the ENTER key in normal STEP mode, until an instruction in the subroutine at 6421 is shown as the next instruction. Using the SKIP to RET mode at this point will automatically execute the program until the RET at 642B. The routine will stop in the STEP mode, showing the next instruction as being the one following the CALL that called the subroutine. To summarise SKIP to RET, automatic execution continues up to and including the RET instruction associated with the next CALL, OR to the next RET if a CALL is not encountered in the meantime. In the same way as the Z (Disassemble) command in the main Monitor gives an 'INVALID ADDRESS' error if you try to disassemble the main Monitor, you cannot single step through the Monitor program, the same error message being displayed. If this error condition occurs while you are in the Trace command, an automatic exit to the main Monitor is made, and the main Monitor's Prompt is shown at the bottom of the screen. REGISTER POINTER You will notice that an inverse video (>) is displayed immediately to the left of the register contents column. This is the Register Pointer and is used to enable the contents of a register pair to be easily changed from the TRACE command. The point can be moved up or down by using the cursor control keys (6 for down and 7 for up). To alter the contents of a register, move the Pointer until it indicates the required register pair, and then press the 1 key. The current value is shown on the bottom line of the Trace display. You can now either press ENTER to restore the same value or type in a 4 digit Hex number to change the register value. This facility only operates in the STEP mode of the Trace command and can easily be used while debugging software using the main Monitor. Access the Trace command by typing T followed by ENTER. All register values are passed to the Trace command, and after making your register alterations, exit to the main Monitor by typing X. Again, all register values are passed back to the main Monitor. If your program uses routines that must be run at full Machine Code speed to operate (e.g timing loops or sound output), you will need to escape from the Trace command by typing X and use the main Monitor commands to run those routines properly. All the register values are passed back to the main Monitor, and you can then set a normal Breakpoint (using the main Monitor B command) and use the C (Continue) command to continue executing your program in real time from the point at which the Trace stopped. 22 ------------------------------------------------------------------------------- Having encountered the Breakpoint, use K to clear the Breakpoint, and access the Trace command by typing T followed by ENTER. All the Register values and the address of the next instruction are passed back to the Trace command ready for you to continue Single Stepping from the address shown against PC in the register display. S - Search This command will search for up to 5 consecutive Hex bytes or 10 consecutive ASCII characters, and display the address of the first byte of the sequence each time it occurs. Type S followed by a Hex start address, plus an optional Hex end address. If no end address is given and ENTER is pressed after the start address, then FFFF is assumed as the end address. Having entered a start address and an end address/ENTER, select H (Hex) or $ (ASCII) option to define what is to be searched for. Pressing H will allow up to 5 Hex values (2 digits each) to be specified. Do not press ENTER between each value, but only when all values are entered. The Search starts automatically after the fifth value. Pressing Symbol Shift + 4 ($) will allow up to 10 ASCII characters to be defined. Again ENTER starts the search if less than 10 characters are defined. If more than 16 locations are found to be successful, the Search stops and waits for ENTER before continuing. The Monitor in Practice Length and location of the Monitor To enable the most effective use to be made of the relocatable feature of the Monitor, a memory map will help to explain memory usage: |<-----------Total Loading Length--------->| | | | |<------Actual length------>| | ____________________________________________________________ | . | | . Relocate | | MONITOR . | | . Code | | . | __________|___________________________.______________|______ | | Load Address Total loading length = 1CA5 Hex = 7333 Actual length = 17D1 Hex = 6097 When the MONITOR is loaded a short Basic program is first loaded which is used to get the loading address. RAMTOP is set to one byte below this, and the MONITOR code is loaded in, complete with its relocation tables. The relocator is automatically accessed, and you are returned to Basic after you have noted the entry address. Having relocated, the area shown above as "Relocate Code" is overwritten with zeros and is available for your own machine code if you wish. 23 ------------------------------------------------------------------------------- The following is an explanation of the operations of the MONITOR which affect all commands and which have not been covered so far. Also included are some general precautions when using machine code. 1) The MONITOR display is created using the screen colours defined by the Spectrum's System Variable ATTR-P and can be changed by returning to Basic (Key Y) and using INK, PAPER and BORDER commands. 2) The loudspeaker will emit a short Beep when a key is pressed. The length of the Beep has been adjusted to give an easily audible sound, without slowing down the response time of the keyboard. The System Variable PIP does not affect the MONITOR'S keyboard Beep. 3) As has been explained earlier, the MONITOR uses its own internal Stack except when a program is running. The program Stack is reset from 'SP' in the stored Register data area whenever a 'J' (Jump) or 'C' (Break Continue) command is executed. When the 'Y' (Return) command is used, the program Stack is cleared and reset to its normal Basic starting point as defined in the System Variable ERR SP. 4) All the commands of the MONITOR operate even if the Z80 Interrupts have been disabled by the machine code you are testing. (Normally, disabling the Interrupts will stop the Spectrum keyboard from being read). Using the 'J' or 'C' commands to execute machine code programs does not alter the Interrupt status, but the Return (Y) to Basic command automatically enables the Interrupts to ensure that the keyboard is scanned in Basic. 5) In addition to the precautions shown on Page 180 of the Sinclair manual advising you not to use the I or IY registers in machine code programs, it is recommended that, if you need to use the alternative BC, DE and HL register pairs and wish to return to Basic after your machine code program, you should save the values held in the alternative registers at the start of your program, and reload them before returning to Basic. 6) The Spectrum MONITOR does not have its own Save and Load routines because the Basic Save and Load routines in the Spectrum allow you to record machine code programs onto cassette. Having written your machine code, you would use the Number Conversion (N) command to convert your Hex start and end addresses into Decimal, calculate the length of your program, and use the Return (Y) command to return to Basic to Save and Verify your machine code. 24 ------------------------------------------------------------------------------- Summary of Commands M aaaa nn ENTER Memory Location and contents in Hex. aaaa = address. nn = new contents value. ENTER = next location (repeating) 'M' re-enters command. X Escape to prompt, and wait for new command, I aaaa bbbb nn Insert. aaaa = address 1st. byte insertion bbbb = address highest byte to be moved nn = no. of bytes to be inserted Type ENTER to execute D aaaa bbbb nn Delete. aaaa = address 1st byte deletion bbbb = address highest byte to be moved nn = no. of bytes to be deleted Type ENTER to execute. A aaaa bbbb cccc Area Relocate. aaaa = present start address bbbb = present end address cccc = new start address Type ENTER to execute. F aaaa bbbb xx Fill aaaa = start address of area to fill bbbb = end address of area to fill xx = value to be loaded into area Type ENTER to execute. Z aaaa bbbb/ENTER Disassembler. aaaa = address start of disassembly bbbb = address end of disassembly (or ENTER for open-ended option, where bbbb = FFFF hex) Print options: N = Screen / = ZX Printer or Centronics Printer * = RS232 via Interface 1 BREAK stops printer early. Y Return. Returns to Basic and resets the Basic stack Pointer. Type ENTER to execute. J aaaa Jump. aaaa = start address of program Type ENTER to execute. 25 ------------------------------------------------------------------------------- B aaaa Breakpoint. aaaa = address of Breakpoint Executes automatically on typing 4th address digit. K Break Restore. Executes automatically, and restores last entered Breakpoint. R Register Display. Executes automatically, displaying values in CPU registers. C Breakpoint Continue. Type ENTER to execute. Continues program execution after a Breakpoint. $ aaaa letter/ENTER String Entry. aaaa = address of 1st byte of string Letter = character from keyboard ENTER = next location (repeating) '$' re-enters command. Typing a letter automatically increments address. P aaaa bbbb/ENTER Print Hex Dump. aaaa = address first byte to print bbbb = address of last byte to print (or ENTER for open-ended option, where bbbb = FFFF hex) Print options: N = Screen / = ZX Printer or Centronics Printer * = RS232 via Interface 1 BREAK stops printer early N H/D, Number Number Conversion. H/D = Hex or Decimal number Type ENTER to execute. T aaaa/ENTER Trace (Single Step). aaaa = address from which Trace starts Typing ENTER in place of aaaa starts Trace from address in PC in Register Display. S aaaa bbbb/ENTER Hex or ASCII Search. aaaa = start address bbbb = end address (or ENTER for open-ended search where bbbb = 0FFFF Hex) 26 ------------------------------------------------------------------------------- SECTION 2 The EDITOR ASSEMBLER Version 3.1 Loading Connect your Spectrum to a T.V., cassette recorder and Printer (if you own one) and to ZX Microdrives via Interface 1 (if you own these) as described in Sinclair's operating instructions, and switch your computer on. The ASSEMBLER is recorded on Side B of the program cassette, so place the cassette in your player with Side B uppermost and type LOAD "". Start the cassette in PLAY and press ENTER on your Spectrum. The program loads in two parts and auto-runs. If you should have difficulty in loading, please refer to the section on loading the MONITOR for some tips on reliable loading. You should follow the screen prompts for starting and stopping the cassette. The ASSEMBLER is relocatable in memory, and automatically locates itself immediately below the current RAMTOP without asking you to specify a load address. This allows it the maximum amount of memory to work with, and still lets you have other code in your Spectrum at the same time (e.g. the MONITOR). RAMTOP is unchanged and is ABOVE the ASSEMBLER. Once loaded the ASSEMBLER can be customised to work with the following range of printer interfaces. 1). ZX Printer 2). RS232 via Interface 1 3). Kempston E Centronics 4). DK'tronics Centronics 5). Micro Peripherals Centronics 6). Euroelectronics LPRINT 7). Tasman Type A Centronics 8). Tasman Type B Centronics 9). Morex Centronics. Type in the number of the option that you require and press ENTER. If you select options 4). to 9). you will be asked to start the cassette again to load in the correct printer routine. If you are using a Centronics Interface option you will then be asked to state whether your printer gives an automatic Line Feed after a Carriage Return. If it does, select option 1, otherwise select option 2, and the Assembler's print routines will be set to send a separate Line Feed. (If you are in doubt about this, you should refer to the operating instructions supplied with the Printer. It is usually possible to select this feature by means of switches inside your printer). Having customised the Assembler for your printer, you will then be given the option of making a copy of the customised program onto a cassette or onto a Microdrive Cartridge. (Microdrive cartridges are NOT supplied). If you intend to Save the program onto Microdrive Cartridge, you should ensure that you have a Formatted Cartridge available BEFORE you start customising, the program. The cartridge should have at least 15K spare capacity. 27 ------------------------------------------------------------------------------- The customised copy is saved in two parts; a Basic loader and the machine code. The copy is fully relocatable but it does not offer the printer options or the save options again. |-----------------------------------------------------------------------------------------------| | WARNING | | | | THIS PROGRAM IS COPYRIGHT and ONE COPY ONLY may | | be made for your OWN PERSONAL USE. | | | | It is illegal to sell copies or to give copies to friends. | |-----------------------------------------------------------------------------------------------| The Basic loader of the customised ASSEMBLER is saved with the name "EDITAS" and will auto-run. It should be loaded from cassette by: LOAD "EDITAS" or LOAD "" To load from Microdrive, use: LOAD *"m";n;"EDITAS" where n is the drive number. Having successfully loaded, the ASSEMBLER will display the address that you must use to access it from Basic. You should make a note of this address in case you return to Basic while you are using the program. At the end of the loading sequence the ASSEMBLER is entered and will display a message at the bottom of the screen asking you whether you wish to use NEW TEXT or to CONTINUE with some existing text As there will be no text (listing) in the Text Buffer yet, type N in response to this. The message will disappear, and a cursor (a white square) will appear in the bottom left corner of the screen. The Editor At all times, the EDITOR/ASSEMBLER writes new information to the bottom of the screen, and screen scrolling is automatic, with no "Scroll?" messages. The normal screen colours used are INK 7: PAPER 1 i.e. white characters on a blue screen. This can be changed by altering the screen colours with Basic commands INK, PAPER and BORDER. To do this, return to Basic, change the Basic screen colours and re-access the Assembler. The whole program writes to the screen using a special routine that produces 40 characters to a line, therefore characters do not relate to the standard character locations, and for this reason, the cursor does not flash, but simply shows where the next character typed in will appear on the screen. Keyboard As the number of commands accessible from the ASSEMBLER is much smaller than the number accessible from Basic, the Keyboard operates in a simplified manner. EXTENDED mode is not available, nor is the GRAPHICS mode, or CAPS LOCK mode. The ASSEMBLER knows when lower case letters may be required, and displays capital letters at all other times. Wherever possible the ASSEMBLER commands are accessed by the same keys as the equivalent keywords in Basic. These command names are as follows, and are printed in white letters on the key tops and are only accessible when the screen cursor is at the left hand end of the bottom line. 28 ------------------------------------------------------------------------------- LIST on Key K EDIT on Key 1 with Caps Shift SAVE on Key S LOAD on Key J NEW on Key A CLEAR on Key X RETURN on Key Y Other ASSEMBLER commands that have no Basic equivalent or are not Basic keywords are as follows, and are also only accessible with the cursor at the left end of the line:- RENUM use Key N VERIFY use Key V AUTO use Key + with Symbol Shift ASSEMBLE use Key R COPY use Key C DELETE use Key D Cursor control functions are accessible wherever the Cursor is positioned, and are:- <- on Key 5 with Caps Shift -> on Key 8 with Caps Shift DELETE on Key 0 with Caps Shift ENTER on Key ENTER All other alpha-numeric keys operate as normal, giving the appropriate letter or number. Use of the Symbol Shift with a key will give the red symbol shown on that key top, providing it is a single character symbol, i.e."!" is available from key 1 plus Symbol shift, but using Key "U" plus Symbol shift will produce no result as 'OR' is not a single character symbol. Symbols normally accessed by the use of the Extended mode in Basic are not accessible from the ASSEMBLER. The only time you will need to use CAPS SHIFT to access a capital letter is when you are entering a message line in the ASSEMBLER. At all other times, the ASSEMBLER automatically displays capital letters. Screen Display The 40 column screen display of the ASSEMBLER is divided into fields. This produces an ordered form of listing that is very easily readable. The cursor control functions automatically recognise the boundaries between fields, making entry of a line into the text buffer a simple operation. It is suggested that you read through the section on 'entering a line' and experiment until you are familiar with the way the fields and cursor controls operate. Entering a Line The machine code program that you wish to write is entered into a listing in a similar fashion to a Basic listing. Only one instruction per line is allowed, and the line must contain a line number between 0 and 9999, and the operation name along with the relevant operand(s). A full list of Z80 mnemonics in the correct form for the ASSEMBLER is shown in Appendix A. The program line may also contain a LABEL name that will identify that instruction in the program. The screen display is divided into 4 fields as shown below, starting at the left hand end of the line:- 29 ------------------------------------------------------------------------------- Line number - 1st 4 characters plus one space Label name - Next 6 characters plus one space Operation name - Next 4 characters plus one space Operands - remainder of line Use the "<-" and "->" cursor to move along the bottom line. With an empty line, the cursor will jump to the beginning of each field. Use the "<-" cursor control to ensure that the cursor is at the left hand end of the line and type in a line number, say 10. As you type each character, it is displayed, and the cursor moves 1 location to the right. Having entered the number, type SPACE. The cursor will move to the start of the next field, the LABEL field. The SPACE key has several different functions depending upon the cursor position in the line, and these will be explained later. Its main function when entering a line is to advance the cursor to the start of the next field, clearing any characters it passes. The cursor will move to the start of the Operation Field. Pressing space a third time has no effect, as every line you enter must have an operation name, and the cursor waits for a name to be entered. All programs you write must start with a definition of the address from which the program is to be assembled. This is called the ORIGIN, and is abbreviated to ORG. Type in ORG as the operation. Type SPACE, and the cursor will now move to the start of the Operand Field. The ORG operation now requires the address that will be the address of the first byte of the assembled program. For this example, enter 6000H. This represents the Hex address 6008 (= 24567 decimal). For more information on ORG, see the section on Assembler Directives, and for more about numbers, see page 16. The bottom line of the screen should now be:- 0010 ORG 6000H Before entering this line into the listing, use the "->" and "<-" controls to move the cursor around the line. Unlike the Basic line editor, this cursor sits over each character, not between characters. When the cursor is over a character, pressing an alpha-numeric key will replace the original character with the one typed in, and move the cursor 1 location right. The "->" and "<-" controls move the cursor to the next character left or right, within a field, ignoring any spaces. If a field is empty, the cursor moves to the appropriate end of that field. To DELETE a character, move the cursor to the character to the right of the one to be deleted, and type Caps Shift and 0 exactly as you would in the Basic Editor. The character to the left of the cursor is deleted and the cursor moves into the deleted location. The rest of the line is not moved. Now, move the cursor to the R in ORG and press SPACE. The RG of ORG is erased and the cursor moves to the beginning of the next field. To erase the last character in a field, place the Cursor over the character and press SPACE. Now use "<-" to move the cursor left. It moves to the O remaining from ORG. Move the cursor to the extreme left end of the line, over the first character of the line number, and press SPACE. The whole line is deleted. Press SPACE again and nothing happens, as the cursor is now waiting for a line number or command name (keyword.) 30 ------------------------------------------------------------------------------- Re-type the whole ORIGIN line again, and experiment with the cursor control keys, the SPACE and DELETE keys until you are familiar with the operation of these functions. When you are ready re-type the ORIGIN line again, and this time press ENTER. The screen will scroll, and the cursor will appear at the left end of the bottom line. The line has been entered into the listing. At the time of entering a line into the listing, checks are carried out on the contents of the line to ensure that each field ends with at least one space. The spaces are essential for the ASSEMBLER to recognise the various parts of the line. If they do not appear in the line when you press ENTER, the line is not entered, and the cursor appears over the unwanted character. Most lines that you enter will be less than 40 characters in length, but some, particularly message lines, will be longer and the cursor functions will allow any line to go over 40 characters in length, with the cursor stopping about three quarters of the way along the second line. Again the last character must be a space. Appendix A shows a complete list of mnemonics in the form that the ASSEMBLER will recognise, and it is important that you enter them in this form. Using the four fields into which the screen is divided, always enter a line number; enter a label name (maximum 6 characters) or leave the label field blank; enter the operation name (LD CALL RET etc.) into the operation field; and enter any operands into the last field. Where an operation has two operands, they must be separated by a comma, e.g. 0020 LD A,20H Please note that: (i) Some of the arithmetic operations (ADD, ADC, SUB, SBC, AND, XOR, OR,) have a slightly different form from that approved by Zilog. Where the first operand is A, (the Accumulator) this ASSEMBLER does not require it to be stated. Only where the first operand is not A, must both be stated. e.g. Use ADC B in place of ADC A, B But use ADD HL, DE as normal The JP(IX) JP(IY) and JP(HL) instructions can be written with or without the brackets. (ii) There are a number of instructions that will be recognised by the ASSEMBLER, that are not published by Zilog. These have been found by experiment and are mainly operations on the individual halves of the IX and IY register pairs. The form used is XH and XL for the MSC and LSB halves respectively. Similarly use YH and YL. One extra arithmetic function is SLL, which shifts the byte to the left, puts BIT 7 into the CARRY and puts 1 into BIT 0. Flag conditions are the same as SRL. Unlike the Basic line editor, which maintains a listing on the screen, the EDITOR/ASSEMBLER simply scrolls the screen as you enter a line, and if you enter lines out of order, they will remain on the screen in the order you entered them. You can, of course, call up a listing in numeric order, by using the LIST command. Editor Commands As you have seen, the cursor control functions "->", "<-", SPACE and DELETE, along with ENTER, take effect wherever the cursor position is in the line. All other commands are only accessible when the cursor is at the left hand end of the line. 31 ------------------------------------------------------------------------------- (i) LIST Move the cursor to the left hand end of the line and press the K key (Keyword LIST). The word LIST will appear on the screen. Pressing ENTER will produce a listing to the screen in numeric order, starting with the lowest line number. Ten lines of the program are displayed whereupon the listing will temporarily stop. Subsequent blocks of ten lines of listing are displayed by pressing SPACE, until the end of the program is reached. After each block of ten lines, any other command may be used before continuing with the listing. You can specify a line number after LIST, and the listing will start from that line number, or the next line, if that line numbers does not exist. LIST/ If you have a Printer, you can produce a listing on the Printer by entering an oblique (Symbol shift and V) after the Keyword LIST. This will produce a Printer listing from the beginning of the program, through to the end, without stopping. To LIST to the Printer from a given line number to the end of the listing, enter the line number after the oblique. This produces a listing output to the ZX Printer or a Centronics Printer, depending upon how you customised the printer options on loading the program. LIST* By typing a star (Symbol Shift + B) after the command LIST, the listing is directed to the RS232 output of Interface 1. This uses the "t" type of output (see Sinclair's Microdrive manual) and automatically sends a Carriage Return and a Line Feed at the end of each line of the listing. If Interface 1 is not connected, a return to Basic is made with 'Error i'. (See page 29 to re-access the Assembler). Whenever you use the RS232 output, always make sure that you set the Baud Rate to the correct value tor your Printer. To do this, return to Basic and use the FORMAT command as described in Sinclair's manual. LIST NAME If you have renumbered your Source Code during editing and are unsure of the current line number of a particular part of the listing, you can LIST from a nearby label LIST command. The Editor will search for the definition of that label name in the label field and list on from that line. If the label name is not defined in the listing, no screen listing is produced. You can add an oblique or a star before the label name to List to a printer; e.g. LIST *NAME. (NOTE label names should not start with an oblique or a star as this could start the printer in error.) (ii) EDIT Move the cursor to the left hand end of the line and type Caps Shift and 1. EDIT is displayed on the screen. Pressing ENTER will display the first line of the listing at the bottom of the screen. Unlike Basic, there is no program cursor to identify the EDIT line, so to EDIT a specific line, simply enter the line number after the EDIT command, and press ENTER. You can now edit the line, and re-enter it into the listing by pressing ENTER. To delete a line from the listing, type in the line number only, and press ENTER. (iii) AUTO Move the cursor to the left hand end of the line and press Symbol Shift and the key with '+' on it (Key K). AUTO will be displayed on the bottom line. This command gives you the Auto line numbering facility where a new line number is automatically displayed each time you enter a line. 32 ------------------------------------------------------------------------------- Two values can be specified, the first being the step value between successive line numbers, and the second, the starting line number. The command form is:- AUTO x,y where x = the step value between 1 and 99 y = the starting line number x and y must be separated by a comma. EXAMPLE a). AUTO 5,1000 will start numbering at line 1000 giving line numbers increasing in steps of 5. EXAMPLE b). AUTO 10 will fix a step value of 10, and carry on producing new line numbers from the last used Auto line number If Auto line numbering is about to produce a new line number in excess of 9999, the AUTO facility is aborted to avoid overwriting the start of the listing. When a new line number has been displayed on the screen, the cursor is left at the start of the Label field. If you do not wish to enter a label name, press SPACE once to move the cursor to the start of the operation field. To stop the Auto facility, use DELETE to erase the current line number. When the cursor reaches the left hand end of the line, you can access any other command, and the Auto facility is cancelled. Re-entering Auto again without specifying any values will use the last step value specified with the line number following the last one produced by Auto. (iv) NEW This command clears the Text Buffer of a listing, clears the Label Table, and resets the EDITOR/ASSEMBLER to the same state it was in when you first loaded it from tape. With the cursor at the left hand end of the bottom line, press the 'A' key (Keyword NEW) and press ENTER. The message you saw when you first loaded the program into your Spectrum will appear. If you typed NEW by mistake, you can now enter 'C', and nothing will be lost. If you want to erase the entire program, Type 'N'. (v) RETURN This command allows you to return to Basic. Press the 'Y' key (Keyword RETURN) which displays RETURN, followed by ENTER, and you will see the normal "0 OK" error message from Basic. To re-enter the ASSEMBLER from Basic use the address shown at the end of the loading sequence. The NEW/CONTINUE? message will be displayed again. Responding with 'N' has the same effect as NEW, but 'C' will change nothing. This allows you an interchange with Basic without upsetting the listing you have typed in. 33 ------------------------------------------------------------------------------- vi) RENUM Allows the Source Code line numbers to be renumbered. Press the 'N' key (with the cursor at the left hand end of the line). RENUM will be displayed. The command form is: RENUM x, y, z where RENUM is accessed from the 'N' key. x = the step value y = the line number in the listing from which to start renumbering z = the new value to be given to line y (the routine actually gives a new value of z +x to the line y). EXAMPLE a). RENUM 2,1000,2000 will give a step value of 2, and renumber from the existing line 1000, giving that line a new number of 2002. Subsequent line numbers, through to the end of the listing, will be renumbered in steps of 2. EXAMPLE b). RENUM2,1000 will renumber from line 1000 to the end of the listing in steps of 2. EXAMPLE c). RENUM 2 will renumber the whole listing in steps of 2. In all cases, if the RENUM parameters would create a line number greater than 9999, the step value is reduced by 1 and the renumber is executed again automatically. In Example b). if the step value has reached 1 and a line number greater than 9999 would be produced, the whole listing is renumbered in steps of 1. If, in Example a), the step value reaches 1 and a line number greater than 9999 would be produced, the value of z is reduced and the renumber is attempted again with a step value of 1 until it is successful. In all cases, renumbering is effective from the chosen line in the listing through to the end of the listing. (vii) DELETE This command allows you to delete a block of lines from your Source Code listing. Move the cursor to the left hand end of the line and press the 'D' key. DELETE will be displayed. The command form is:- DELETE x,y where DELETE is accessed from the D key x is the first line number y is the last line number. Press ENTER, and the block of lines from x to y INCLUSIVE will be deleted. If the second line number is less than the first then no deletion takes place. (viii) COPY This lets you COPY a block of lines from one part of your listing to a new location. The original block of lines is not deleted, move the cursor to the left hand end of the line and press the 'C' key. COPY will be displayed. 34 ------------------------------------------------------------------------------- The command form is:- COPY x,y,z Where COPY is accessed from the 'C' key x is the first line number of the block to copy, y is the last line number of the block to copy. z is the point in the listing to copy to. Press ENTER and the block will be copied. The listing is not renumbered and you will have duplicate line numbers. There are certain conditions attached to the values of x,y,z to ensure that the listing is not corrupted. These are:- If z is between x and y then no copying takes place. If x is greater than or equal to y then no copying takes place. If line y exists it is included in the copy. If line z exists the block is inserted after it. If line z does not exist the block is copied to where line z would be. Comment Lines Comments can be inserted into your listing, in a similar way to a REM line in Basic. Enter the Line Number; move the cursor to the start of the Label Field and enter a semi-colon. Using the "->" cursor control, move the cursor to the start of the operand field and enter your comment, enclosed in quotes, exactly as you would enter a message line. (See DEFM on page 41). The semi-colon identifies the line as a comment, and the Assembly routine ignores the whole line. Important The whole of the EDITOR/ASSEMBLER, and its Buffers and Tables are below RAMTOP, and are not protected from Basic. The Basic command NEW will erase the ASSEMBLER from memory. The main functions of the EDITOR have now been described and although its operation is different in some respects from the Basic line editor, you should become familiar with it fairly quickly. The remainder of the commands mentioned in the section relating to the keyboard are described in the next part of the Manual, which explains the operation of the ASSEMBLER. The Assembler The ASSEMBLER converts the mnemonics entered in the listing into the Hex code that the CPU can understand. The mnemonics in the listing are called the Source Code and the assembled Hex code is known as the Object Code. The ASSEMBLER makes two passes through the listing. The first pass checks for correct syntax; calculates the values of the Labels and creates a table of those values: and creates an outline Object File. The second pass calculates fully all the numeric and Label operands, and calculates the offsets for relative jumps. It is not possible to separate the two passes. The results of the second pass are displayed either to the screen or to a Printer. 35 ------------------------------------------------------------------------------- This section of the manual will describe the use of Labels and Assembler Directives. It will also describe the commands not yet dealt with. It is advisable to read the whole section before using the ASSEMBLER. The Assembler resides at the top of the memory. The size and location of all the tables and buffers created by the Assembler is transparent to the user, thus simplifying the program's operation. As you enter a line into the Assembler listing, the line is stored in its correct place in the Text Buffer, and this buffer expands downwards below the Assembler as the listing increases in size. The Object Buffer To allow you to Assemble code that could ultimately reside in any part of memory, and also to give the Assembler the maximum amount of working space at all times, the Assembled code is ALWAYS stored in the Object Buffer, irrespective of the ORIGIN location specified in your Source code. _____________________________________________________________ | | | | > < Code | | U | | ROM | & | |Buffer> < |EDITAS| D | | | Vars | | > < | | | |_______|______|_____|______>_____________<______|______|___| ^ | | | |___<<<<<<<<<<<<<<___| Assembled Source Code stored in Object Buffer The Assembler will calculate all addresses during assembly based on the ORIGIN address supplied in the Source code; the code is simply stored in the Object Buffer, ready for Saving when the Assembly process is complete. The Machine Code produced by the Assembler is designed to run at the memory location given in the ORG command, which is not normally the Object Buffer area, and the machine code would be loaded back to the correct location using the Basic Load command. At that stage, the Editor Assembler would not be required in memory, thus freeing a large part of the memory for your own program. Each time the ASSEMBLER is accessed from Basic it detects the highest memory location that Basic is using and stores that value, plus 256, to use as the start of the Object Buffer. The ASSEMBLER also defines a label with the name of # and gives this value to it. Every time that you assemble a piece of code you will always find this label shown at the end of the label table. You will not normally need to use the # label, but it can be useful if you are working with both the ASSEMBLER and the MONITOR in memory together. See Section 3 of this manual for further information. If the Text Buffer or Label Table are in danger of overwriting the Object Buffer, the ASSEMBLER will show an error message MEMORY FULL. If this occurs you will have to split your Source Code into more than one section, and details about this are in the Section on Assembly from Cassette or Microdrive. 36 ------------------------------------------------------------------------------- Numbers The ASSEMBLER will accept Decimal or Hex numbers, and will default to Decimal. Numbers must start with a numeric digit, i.e. 0 to 9, and Hex numbers must have a suffix H. If Hex number starts with a letter (A to F) it must be preceded by a zero, or the ASSEMBLER will treat it as a Label, i.e. D000 Hex must be written 0D000H, and FF Hex as 0FFH. Decimal numbers need no suffix. Decimal numbers between 0 and 65,535 are evaluated to their corresponding Hex value. Decimal numbers greater than 65,535, up to 99,999 are evaluated, but the carry produced is ignored, (i.e. 65,536 is evaluated to 0000 Hex and -1 is evaluated to FFFF Hex). ASCII Characters Single ASCII characters are accepted as operands, providing that the character is entered within normal quotes (Symbol shift and P). This type of operand is accepted by all operations that can accept a numeric operand, except the ASSEMBLER directives ORG and END. When you type the first quote, the ASSEMBLER automatically produces lower case letters unless you use the Caps Shift. Example:- LD A, "a" produces the code 3E 61. Arithmetic Addition and Subtraction within an operand is allowed. The sum or difference of Label values, numeric values or ASCII characters in any combination is accepted. Examples:- (i) LD A, "A"+ 20H produces the code 3E 61 (ii) LD HL, LB2 - LBL1 calculates the difference between Labels, (iii) LD DE, START +100H adds a fixed offset to a Label. Labels In Assembly language programming, Labels are used to identify points in the program. Whereas in Basic you would GO TO a line number, in Assembly language, you would JP (jump) to a Label name. The line numbers in your Source code listings are only there to maintain the correct order of the instructions and to allow editing. All Labels have a two byte, 16 Bit value. Label names can be defined with a maximum of 6 characters. They must start with a non-numeric character and cannot contain spaces. All register names and abbreviations for conditions are reserved names, and cannot be used as a Label name, as the Assembler will try to evaluate them as a register or condition. The first character of a label name must not be a semi-colon, or it will be recognised as a comment line, nor must it be a '/' or '*' as these always start a label name with a LETTER. Ordinary Labels Label names put into the Label Field and followed by a operation other than EQU or DEFL are given the value of the current program address for that instruction. They are not re-definable, and can only be defined once in a program. An ordinary label used as an operand must be defined somewhere in the program listing, but can be defined in a line after it is used as an operand. This allows forward jumps to a Label name. Any Label can be used as an operand, providing that its value is within the limits for that operation. There are two special types of Label that are defined by the use of ASSEMBLER directives EQU and DEFL. The Label values are defined by you as constants or variables. 37 ------------------------------------------------------------------------------- EQU This Assembler Directive assigns a value to a Label name. (See page 23 for an explanation of Assembler Directives). It does not put any code into the Object Buffer. Once a Label is assigned a value by EQU, it cannot be re-defined. Any numeric value, ASCII character or other Label name is accepted as an operand, but if a Label name is used as an operand, it must already have been defined in a previous line in the listing. The Label name is put into the Label field; EQU is put into the operation field and the operand in the operand field. A special operand for use with EQU and DEFL only is $. i.e. LABEL EQU $. This gives the label a value equal to the current program address. DEFL This Assembler Directive also allows you to define the Label value, but it also allows you to re-define the value as often as you wish within a program. At each new definition, the previous value is lost. A Label is only re-definable if its first definition in line order in the listing is by DEFL. Subsequent definitions can be by DEFL or EQU, but it remains re-definable. You cannot change an existing ordinary Label into a redefinable one. Having established a Label name using DEFL, you cannot use the same name for an ordinary Label to identify part of the program. It can only be redefined by DEFL or EQU. Example: 0010 ORG 7000H 0020 LBL1 DEFL "A" 0030 LD A,LBL1 0040 ; 0050 ; **** **** *********************** 0060 ; 0070 ; "Rest of program" 0080 ; 0090 ; **** **** *********************** 0100 ; 0110 LBL1 DEFL LBL1+20H 0120 LD A,LBL1 In the above example, line 20 sets LBL1 to the ASCII value of "A" which is 41 H, and uses that value in line 30. Later in the program, LBL1 has 20 H added to it, which gives the ASCII value of "a", which is used in line 120. When using other Label names as operands with EQU and DEFL, those Label names must have been previously defined in the listing. As EQU and DEFL Labels are not strictly part of the program, and do not appear in the assembled code, they have no address related to them, and so during the assembly display, their value is shown in the left hand column, where you would expect to see an address. At the end of the Assembly procedure, a table of Label values is produced, and DEFL labels are flagged by an asterisk Label Slicing All labels are stored as a 16-BIT value even if they are defined as having a value of 255 or less. If their value is 255 or less, then the Assembler will treat them as either 8-BIT or 16-BIT, depending upon the instruction with which they are used. 38 ------------------------------------------------------------------------------- e.g. If a label, LBL1 is defined as having a value of 80H, it will be stored as 0080H, and could be used as an 8-BIT value, by LD A,LBL1 or as a 16-BIT value by LD HL,LBL1 If its value is defined as greater than 255, it will always be treated as a 16-BIT number. It is possible to access the high and low bytes of a label value separately by preceding the label name when it is used as an operand by < to access the HIGH byte, or by > to access the LOW byte. EXAMPLE A label has been defined thus: LBL1 EQU 5CB0H The instruction LD A,LBL1 will take the LOW byte of the label, and is equivalent to LD A,0BOH The direction in which the < or > is pointing indicates which byte is taken. The label does not have to be defined by EQU, and any label can be 'sliced' in this way. It is important to remember that ALL label names should start with a LETTER. Never start a label name with '<' or '>' as the Assembler will produce errors when that label name is used as an operand. All Source Code files saved from previous issues of our Assembler will Load into the new version and will assemble correctly, but you should check that there are no labels defined that start with '<' or '>'. JR/DJNZ The relative offsets for these two jump instructions can be specified in a number of ways, and the following example clearly shows all the possible forms of defining the offset. The jump must be within the limits + 127 and -. 5DDB 0010 ORG # 5DDB 1802 0020 JR LOOP 5DDD 3E01 0030 LD A,1 5DDF 0602 0040 LOOP LD B,2 5DE1 18FC 0050 JR LOOP 3DE3 1820 0060 JR 32 5DE5 1820 0070 JR 20H 5DE7 1820 0080 JR +32 5DE9 1820 0090 JR +20H 5DEB 18FC 0100 JR 0FCH 5DED 18FC 0110 JR 252 5DEF 18FC 0120 JR -4 5DF1 18FC 0130 JR -4H 5DF3 10EA 0140 DJNZ LOOP 5DF5 10EE 0150 DJNZ 0EEH 5DF7 10EE 0160 DJNZ 238 5DF9 10EE 0170 DJNZ -18 5DFB 10EE 0180 DJNZ -12H 5DFD 1020 0190 DJNZ 32 5DFF 1020 0200 DJNZ 20H 5E01 1020 0210 DJNZ +32 5E03 1020 0220 DJNZ +20H 0230 END LOOP 5DDF # 5DDB 39 ------------------------------------------------------------------------------- Assembler Directives These are not operation names recognised by the CPU and are included to simplify the process of writing machine code. They are used by the ASSEMBLER, at assembly time, to create messages, data bytes, etc. They are entered into the listing, with a line number, by writing the Directive name into the operation field. They can be identified with labels and all require an operand except END. EQU and DEFL have already been dealt with. Two of these Assembler Directives are compulsory in every program you write: namely ORG and END. An error message is produced if either is missing. ORG Defines the address of the first byte of the assembled code. It must be defined in the listing before any other instruction. Comment lines can preceed it, but it is good practice to define it in the first line you enter. The Hex code produced by the ASSEMBLER is written in the Object Buffer from where it is Saved to cassette. Label # defines the start of this Buffer, and is set by the ASSEMBLER. The operand for ORG can be a number; a Label, so long as it has already been defined; or Label #. Only ONE ORG per program is allowed. If a program is assembled with ORG #, the code in the Object Buffer is correctly assembled for the Buffer addresses, and can be run there. Any other ORG address will produce code in the Object Buffer designed to run from a different address. END This signifies the end of the program. Although there may be lines of program listing after the END statement, the ASSEMBLER will ignore them. DEFB Assigns a value to the single byte at the current assembly address. The value must be less than 256 (0100H) and the operand can be a number, a single ASCII character, or a Label with a value less than 256. It is useful for defining data bytes within a program. Multiple operands are allowed, separated by commas, e.g. DEFB 10,0E3H,255,3CH The assembled value of each operand is displayed to the screen or printer at assembly time (if screen or printer output is requested). The first operand value is displayed in the normal position along with the program address and the line from the listing. The second and subsequent operand values are displayed on the next line. DEFW Assigns a value to the next two bytes at the current assembly address. The value is stored with the LSB first, followed by the MSB; i.e. in the normal way for a two byte value. It is also useful for defining data bytes within a program. Multiple operands are allowed, separated by commas, e.g. DEFW 40000,7C80H,3CH,LBL2 40 ------------------------------------------------------------------------------- The assembled value of each operand is displayed to the screen or printer at assembly time (if screen or printer output is requested). The first operand value is displayed in the normal position along with the program address and the line from the listing. The second and subsequent operand values are displayed on the next line. DEFS This creates a number of blank bytes from the current assembly address. The space created has its byte values set to 0. Its operand can be a number of a label name, providing that the label has been defined in a previous line in the listing. DEFM Allows messages to be entered into the listing as a string of ASCII characters. DEFM calculates the Hex code for each character, and puts that code into the current Object Buffer address. The operand must be a string of ASCII characters enclosed within quotes. When you type the first quote into the listing, the EDITOR automatically displays lower case characters unless CAPS SHIFT is pressed. When the cursor is positioned between string quotes, lower case letters are automatically produced. The first character of the operand must be a quote. A message line can extend over nearly two lines, giving you a maximum message length of 47 characters. PRNT Allows screen or printer output to be turned on and offer within an assembly pass. PRNT is entered into the listing (in the operation field) at the points where the display is required. It does not affect the machine code that the ASSEMBLER produces. If, for example, you have altered part of a listing, and require a print out of the section that has been altered, you can enable screen or printer output for that part of the Assembly process only, without sacrificing the increased speed of having no output for most of the assembly process. PRNT S turns on screen output from the next line in the listing. PRNT / directs the Assembly output to the ZX Printer or a Centronics printer depending upon how the program was originally customised. PRNT * directs the Assembly output to the RS232 printer output of Interface 1. It uses the "t" type of output. PRNT OFF turns off the Print facility. The operands S,/,*,OFF must be placed in the operand field in the Source Code. Use ASSEMBLE (followed by ENTER) to give no screen or printer output until the PRNT directive requests it. Commands Those commands used by the EDITOR have been dealt with on Page 9. The remaining commands are as follows, and are only accessible when the cursor is at the left hand end of the line:- 41 ------------------------------------------------------------------------------- Assemble Use Key R (Keyword RUN), and ASSEMBLE is displayed on the screen. The first pass of the assembler does not produce an output to either the screen or printer. The second pass can be displayed to the screen, the printer, or neither. The last case will give the fastest assembly. 1). Assembly with no display: Type R (ASSEMBLE) and press ENTER. Assuming there are no errors, there will be a pause, with no screen output, related to the length of the program, and the assembly will end with a display to the screen of a table of the Labels and their values, with DEFL labels flagged by an asterisk. Assemble/ 2). Assembly with display to the Printer: Type R, and then type in an oblique (Symbol Shift and V) and press ENTER. The second assembly pass will be sent to your printer (ZX or Centronics depending upon how the program was customised). Assemble* 3). Assembly with display to RS232 printer via Interface 1: Type R and then type * (Symbol Shift + B) and press ENTER. This uses the "t" type of RS232 output, automatically producing a Line Feed after a Carriage Return. If Interface 1 is not connected, a return to Basic is made with Error i. Assemble S 4). Assembly with screen display: Type R, and then type S and press ENTER. The second pass of the Assembly will be displayed to the screen, and will show the assembly address, the Hex code, plus all the information contained in the listing. The screen display will continue scrolling, through to the end of the assembly, but can be PAUSED at any time by pressing the M key (Keyword PAUSE), to allow you to read the assembled listing. Assembly will continue when the M key is released. PAUSE also operates when using the Printer, and printing continues when the M key is released. If you start an Assembly pass, and then decide that you do not want it to continue, press CAPS SHIFT and BREAK together. The Assembly process will stop and the Assembler's normal cursor will reappear on the bottom screen line. Pressing CAPS SHIFT and BREAK while a load from cassette or Microdrive is taking place, or while the ZX Printer or RS232 link is in use will return you to Basic. If a Centronics printer is in use, the normal Assembler cursor is displayed. Clear Clears the Text Buffer, but leaves the Label Table intact. If you are assembling a long program in sections, the labels produced by one part will probably be required in subsequent parts. Having entered and assembled one part, and Saved the Text Buffer and Object Buffer, CLEAR will empty the Text Buffer, but retain all the Labels, and protect them. (Only the ASSEMBLER command NEW will delete these labels). The next part of the listing can be entered and assembled. Any new labels are added to the table, but each time the new listing is assembled, the Label Table is cleared of the current labels, the old labels being unaffected. Labels carried 42 ------------------------------------------------------------------------------- over in this way retain their original status, i.e. if a label is first defined by DEFL as being re-definable it will remain so in subsequent listings, but if it is re-defined by the current listing, the original value will be lost the first time the current listing is assembled. If the original value is required by the current listing it is advisable to create a new label to retain the original value. This only applies to re-definable labels. Use of CLEAR after "MEMORY FULL" error If you get a Memory Full error while using the ASSEMBLER, you will need to assemble your program in more than one part. Normally in this situation you would use the process described in the section on Assembly from Cassette or Microdrive as this makes the assembly process automatic and produces one single piece of finished Object Code, however, a program can be broken down into small parts, each being assembled and then Saved separately by the ASSEMBLER. If the END instruction of one part is given a label name to identify its program address, that label name can be used by the ORG of the next part, to ensure that the program address of the start of the next part follows on from the end of the previous one. Use the CLEAR command to clear the Text Buffer (having first assembled the code and Saved the Text and the Code) before entering or Loading the next part. Having Saved all the parts of the program, return to Basic and Load them all back into the memory: they will join up to form one complete program which you can Save from Basic as a single program. N.B. Each section of the program can only access labels that are defined in that section or that have been defined in a previous section and retained by the use of the CLEAR command. Example of two part listing: 0010 ; ********** 0020 ; "PART ONE" 0030 ; ********** 0040 ; 7000 0050 ORG 7000H 7000 3E47 0060 LD A,"G" 7002 BE 0070 CP (HL) 0080 ; 0090 ; "Remainder " 0100 ; 0110 END1 END END1 7003 # 5DDB 0010 ; ********** 0020 ; "PART TWO" 0030 ; ********** 0040 ; 7003 0050 ORG END1 7003 12 0060 LD (DE),A 7004 C9 0070 RET 0080 ; 0090 ; "Remainder " 0100 ; 0110 END2 END END2 7005 END1 7003 # 5DDB 43 ------------------------------------------------------------------------------- Continue Strictly, this is not a command, but is one of the responses to the message displayed when you enter the ASSEMBLER from Basic (by typing C). It changes nothing, and allows you an interchange with Basic without destroying any of the Buffers or Tables set up by the ASSEMBLER. The other option on entry from Basic is N (NEW) and this has the same effect as NEW (See Page 12). label The label table display at the end of an assembly pass can be inhibited, and can be called up independently of an assembly pass. The label table is always created by an assembly pass and this command only controls its display. Press key L when the cursor is at the left hand end of the line and the command label is displayed. Pressing ENTER will display the current label table (unless it has been inhibited). label 0 Press zero after key L, followed by ENTER. The label table display will be inhibited. label 1 Press 1 after key L, followed by ENTER. The label table display will be enabled and the current table displayed on the screen. label/ Press / (Symbol Shift + V) after key L, followed by ENTER. The current label table will be printed onto the ZX Printer or a Centronics printer depending upon how the Assembler was initially customised. If the label table has been disabled, nothing will happen. label* Press * (Symbol Shift + B) after key L, followed by ENTER. If the label table is enabled, its display will be directed via the RS232 link on Interface 1. It uses the "t" type output as described in ASSEMBLE*. You can interrogate the label table to find the value given to any specific label by pressing key L as above, and then typing the name of the label. The value in Hex of that label will be displayed on the screen. e.g. LABEL LBL1 will display the value of LBL1. Data Storage Commands It is possible to Save the contents of both the Text Buffer and the Object Buffer directly from the ASSEMBLER; to Verify both Buffers against a Saved copy; and to Load a Text file into the Text Buffer. The Assembler, running in a Spectrum fitted with Sinclair's Interface 1, will allow data storage on cassette and Microdrive, and the transfer of both the Text Buffer and the Object Buffer into another Spectrum via the Network, or to another computer via the RS232 link. The syntax of all these commands has been maintained as close to those required by Basic as possible. Although the Microdrive command syntax is a little cumbersome, it was felt to be better to retain the syntax that users will be familiar with. In all cases, any file name must be specified within quotes (Symbol Shift + P) and contain a maximum of ten characters. Both Buffers are Saved as blocks of CODE, and there is no need to specify start addresses or their length as the ASSEMBLER calculates this for you. 44 ------------------------------------------------------------------------------- The command SAVE is accessed from the S key with the cursor at the left hand end of the line. The command LOAD is accessed from the L key with the cursor at the left hand end of the line. The command VERIFY is accessed from the V key with the cursor at the left hand end of the line. Important It is possible to Load a Text Buffer file from cassette or Microdrive Via Basic, but this will corrupt the Label Table and prevent the ASSEMBLER working correctly. Text files must be loaded through the ASSEMBLER. Object Buffer files are designed to be loaded back into your Spectrum via the Basic command LOAD "" CODE. When you do this, be aware that you can overwrite the ASSEMBLER, and you should refer to the memory maps in this book if you subsequently want to use the ASSEMBLER. Cassette Routines SAVE 1). Text Buffer The command form is SAVE "name" T where T indicates the TEXT Buffer. Press ENTER and the familiar "Start tape..." message is displayed. Proceed as you would for a Basic Save. On completion, the Assembler's cursor is returned on the bottom screen line. 2). Object Buffer The command form is SAVE "name" C where C indicates your machine CODE. Again the "Start tape..." message is displayed when you press ENTER, and the procedure is as above. The Object Buffer is Saved with the correct Header information for the location specified by your ORG in the listing, with the block of code being Saved from the Object Buffer. The resulting cassette will Load back via the normal Basic LOAD "" CODE into the correct part of memory as defined by ORG. VERIFY The command form for Verifying both the Text Buffer and the Object Buffer is VERIFY "" or VERIFY "name" The ASSEMBLER knows whether to Verify Text or Code, and you do not specify which. As in Basic, VERIFY "" will Verify the next file on the cassette, and VERIFY "name" will only Verify that named file. The ident BYTES: and the filename are displayed at the bottom of the screen. If successful, the Assembler's cursor will reappear, otherwise the Basic error 'R. Tape loading error' will appear, and you will be left in Basic. Re-enter the ASSEMBLER, assemble your program-again if you were Verifying the Object Buffer, and SAVE again. It is recommended that you do not return to Basic between Saving an Object File and Verifying it, as the address of STKEND, and therefore the address of the Object Buffer will fail, and you will need to re-assemble your program. 45 ------------------------------------------------------------------------------- LOAD The Assembler will ONLY Load a TEXT Buffer file. If you try to Load and Object Buffer file, it is ignored after the header has been checked. Similarly, if you try to Load a cassette Saved from Basic, it will be ignored. As with Verify, you can specify a filename after LOAD, or not, in which case the Text file will be loaded. 1). LOAD "name" N where N represents NEW. The existing Text Buffer and Label Table are both deleted (as in NEW) before the new Text Buffer is loaded from cassette. The N need not be specified, (i.e. LOAD "name" has the same effect). 2). LOAD "name" C where C represents CLEAR. The existing Text Buffer is deleted and the existing Label Table is protected, as in the CLEAR command. The new Text file is then loaded. 3). LOAD "name" A where A represents APPEND. The existing Label Table is cleared to a null table containing only the label #. The new Text file is Appended to the end of the existing Text Buffer. Having Appended a Text File, you should renumber the whole listing to allow editing of the full listing, and remove unwanted ORG and END Directives at the junction of the two files. If you do not renumber, the ASSEMBLER will correctly assemble the total program, even if there are duplicate line numbers. Microdrive Commands Syntax is identical to Basic. Any drive number can be specified, (although the examples given use Drive 1) and there is the normal limit of ten characters for the file name. When saving, Source Code is denoted by the letter T after the file name, and Object Code by the letter C as in the normal cassette commands. Loading from the Microdrive can also use the suffix N (for New), C (for CLEAR) and A (for APPEND) as described in the cassette commands. If none of these suffixes is used, NEW is assumed, and the existing Source Code and Label Table are deleted. Microdrive commands, CAT, FORMAT and ERASE are not accessible directly from the ASSEMBLER. To use these commands, return to Basic (Key Y) and use them from Basic. Microdrive and Network commands used from BASIC will overwrite part of the Object Buffer, as basic creates their Channel areas. If you use these commands from Basic and re-access the Assembler, then re-assemble your program before Saving the Object Buffer. When using these commands from within the Assembler, the Object Buffer is automatically moved. The following Microdrive, Network and RS232 commands have basically the same effect as the cassette commands, and the same general conditions apply. a). SAVE *"m";1;"name" T will save the current Text Buffer file (indicated by the letter T) to Drive 1 with the file name "name". b). SAVE *"m";1;"name" C will save the current Object Code (indicated by the letter C) to Drive 1 with the file name "name". 46 ------------------------------------------------------------------------------- c). LOAD *"m";1;"name" will load the file with name "name" into the Text Buffer. If the file "name" was saved as Code from the Object Buffer, an error 'Wrong File Type' is displayed. d). VERIFY *"m";1;"name" will verify the file "name" against the Source or Object Code as appropriate. When saving Source or Object Code, the file name "name" must not exist on the Cartridge being used. If the name does already exist, the following message is displayed. File already exists: OVERWRITE? (Y/N) If you do not wish to overwrite the existing file, press CAPS SHIFT and N and save again with a new file name. If you do wish to overwrite the existing file, press CAPS SHIFT and Y. The original file is first erased, and then the new file is automatically saved. In doing this, the Drive will run for approximately 15 seconds. When loading Source Code from Microdrive, an error message will appear if the named file is not to be found on that Cartridge: File does not exist: Retry/Cancel (R/C) If you know that the correct file is on another Cartridge you should insert that Cartridge into the same drive and press R whereupon the ASSEMBLER will try to load the file again. If you have entered the wrong file name in your command or wish to stop the load for any reason, you should press C which abandons the load. Network Commands a). SAVE *"n";1T will save the Text Buffer (T for Text) via the Network to Station 1. Any Station number between 1 and 64 can be used, and Station 0 denotes the Broadcast function. Syntax is identical to Basic and you should refer to the Sinclair Microdrive Manual for further information relating to the Network, and defining station numbers. b). SAVE *"n";1C saves the Object Code (C for Code) via the Network to Station 1. Again, any Station number is valid, and Station 0 is the Broadcast function. NB. If you have assembled the Source Code with ORG # or with an ORG address that is close to the value held in the STKEND in the receiving Spectrum, the receiving Spectrum will almost certainly crash, as the Code saved via the Network will overwrite the Network channel area in the receiving Spectrum. c). LOAD *"n";1 This will only load a valid Source Code via the Network from another Spectrum that is running the Assembler, and is in the process of Saving its Source Code onto the Network. Station numbers must be correct. If the received data is not a valid Source Code file, an error "Wrong File Type" will appear. Suffixes N (New), C (Clear) and A (Append) can all be added after the Station number. With no suffix, NEW is assumed. 47 ------------------------------------------------------------------------------- d). VERIFY *"n";1 This will Verify, via the Network, either a Source Code file or an Object Code file as appropriate. The second Spectrum will need to SAVE *"n" to the appropriate Station number. RS232 Commands Save/Load/Verify commands via the RS232 link of Interface 1 all use the "b" type of data transfer as described in the Sinclair Microdrive Manual. The information is not suitable for display on a line printer. (Use LIST* and ASSEMBLE* for printer output). These Save/Load/ Verify commands are included for those users who have linked two computers via the RS232, or who are using peripheral equipment such as a modem. As normal with the "b" format, a Line Feed is not sent automatically with a Carriage Return. a). SAVE *"b"T This saves the Source Code via the RS232 link. b). SAVE *"b"C This saves the Object Code via the RS232 link. c). LOAD *"b" This will only load a valid Source Code file into the Text Buffer. An error "Wrong File Type" is produced if the incoming data is not valid. The suffixes N (New) C (Clear) and A (Append) can all be added after the "b". With no suffix NEW is automatic. d). VERIFY *"b" will verify the data incoming via the RS232 link with either the Source Code or Object Code as appropriate. Before using any of the RS232 commands, ensure that the Baud rate is set correctly for both your Spectrum and the communicating equipment. To set the Baud rate of your Spectrum, return to Basic (Key Y) and use the Basic FORMAT command as described in the Sinclair Microdrive Manual. Assembly from Microdrive or Cassette To overcome the problems of writing very large programs, where there is insufficient memory for the total Source Code and Object Code in memory together, it is possible to store the Source Code in sections on cassette or Microdrive, and to assemble the sections into one long Object Code file. A maximum of ten sections of Source Code is permitted, each with the same file name that also includes an identifying section number. The first section must contain an ORG directive, and the last section must contain an END directive. Intermediate sections must contain neither. Labels in any section can be accessed from any other section, exactly as if the whole Source Code was in memory at the same time. The principle of the operation is that each section of the Source Code is loaded into the Text Buffer in turn, with the Assembler executing the first of the two assembly passes on each section. Then each section of Source Code is again loaded into the Text Buffer for the second assembly pass. Therefore, with a limited size of Text Buffer, a very large Object Code buffer can be created. 48 ------------------------------------------------------------------------------- For maximum effectiveness, each section of the Source Code should be around 750 lines in length, which will allow a maximum Object Code length of around 15K to be created. The total Source Code storage requirements for such a situation would be around 95K which is more than can be stored on one Cartridge. You should store the Source Code on more than one Cartridge and when the ASSEMBLER gives you the message File does not exist: Retry/Cancel (R/C) change the Cartridge and press R to continue. When using a Microdrive to store the sections of Source Code, the multiple assembly process is automatic, and the normal options of assembly output to the screen or printer or neither are available. If a cassette recorder is used, prompting messages are displayed on the screen, indicating when to start, stop or rewind the tape to access the correct section. Each section of the Source Code on the cassette does not need to follow on immediately from the last, as the assembly process allows you time to wind the cassette to the correct location before continuing. Saving a Section of Source Code The Save commands for cassette or Microdrive are virtually identical to the normal Save commands. The only difference is the section number specification. The Save commands are: SAVE "name"#n for cassette SAVE *"m";1;name"#n for Microdrive (any drive number) where the file name "name" is limited to 8 characters. # indicates the Save as part of a multi-section Source Code file, n is the section number. The file name Saved with the Source Code is always 10 characters long, and the ninth and tenth characters are always #n. The first section MUST be #0, and in subsequent sections the value of 'n' MUST be incremented by 1. If the resulting sections do not contain consecutive section numbers, the assembly will fail. It is therefore essential that you keep track of the section numbers used, and always use the next section number when Saving a new section. The file name "name" must be identical for each section. It is a good idea to put the Filename and Section number in a comment line at the beginning of each Section as it is very easy to forget which Section you are working on. This reminder will reduce the possibility of overwriting the wrong Section on the Microdrive after editing. Loading a Single Section of Source Code Alterations to any section of Source Code can be made by loading that section, and subsequently Saving it again with the SAME file name and the SAME section number. (You have the option to overwrite a Microdrive file that already exists if you wish). To Load a section, the command is: LOAD "name"#n for cassette LOAD *"m";1;"name"#n for Microdrive (any Drive number). 49 ------------------------------------------------------------------------------- As with SAVE, # identifies a section of multiple section Source Code file, and n is the section number. When loading from cassette, the file name "name" and the section number need not be specified; simply use LOAD "". Verifying a Section of Source Code Providing that the section of Source Code you wish to Verify has been Saved, and is still the current section in the Text Buffer, enter: VERIFY "name"#n for cassette VERIFY*"m";1;"name"#n for Microdrive (any drive number). Assembling a Multi-Section Source Code File a). From cassette:- Enter the command ASSEMBLE #"name" and press ENTER. The screen display will ask you to "Set tape to start #0 ENTER". Wind the cassette to the start of section 0 and press ENTER. You will then be asked to "PLAY TAPE". When that section has loaded, you will be asked to "STOP TAPE" and press ENTER. This initiates the first assembly pass of section 0, and when that is completed, the above process is repeated for all subsequent sections. The whole process is then repeated for the second assembly pass, with messages displayed on the screen at all times to indicate what is going on. b). From Microdrive:- Enter the command ASSEMBLE #"m";1;"name" and press ENTER (any Drive number can be specified). The Drive specified in the command will operate, and the whole Assembly process is automatic. Screen messages are displayed to indicate which section is currently being assembled. The full assembly listing can be output to the screen, ZX Printer (or Centronics printer if that option was chosen on customising) or via the RS232. To use these facilities, type S or / or * respectively, after the command ASSEMBLE, and before the #. E.g. ASSEMBLE S#*"m";1;"name" will Assemble from Microdrive 1, the Source Code with the file name "name", and display the whole assembled listing to the screen. ASSEMBLE *#"name" will do ths same assembly from cassette, and will output the full Assembly listing to the RS232 link ("t" type output). 50 ------------------------------------------------------------------------------- In general terms, after the command ASSEMBLE enter the type of output required (enter nothing if no output is required), then enter the '#' character to indicate a multi-section Assembly, and then define the loading parameters using the same syntax as the LOAD command. If you have stored your Source Code sections on more than one Microdrive Cartridge the ASSEMBLER will stop with the message File does not exist: Retry/Cancel (R/C) each time it cannot find a Section. You should then change the Cartridge in the same Drive a press R to continue. ALWAYS wait for that message to appear before changing Cartridges. To help explain the multi-section Assembly process, try the following short example. 1) Type in the following Source Code: 0010 ORG # 0020 START LD A, 2 0030 CALL 1601H 0040 LD HL,MSG 0050 LD B,LEN and Save with the command Save "test"#0 for cassette SAVE *"m";1;"test"#0 for Microdrive 2) NEW the Source Code and enter part two: 0010 LOOP LD A,(HL) 0020 PUSH HL 0030 PUSH BC 0040 RST 16 0050 POP BC and Save with the command SAVE "test"#1 for cassette Save *"m";1;"test"#1 for Microdrive 3) NEW the Source Code and enter part three: 0010 POP HL 0020 INC HL 0030 DJNZ LOOP 0040 RET 0050 MSB DEFM "A multi-part Assembly" 0060 LEN EQU $-MSB 0070 END and Save with the command SAVE "test"#2 for cassette SAVE *"m";1;"test"#2 for Microdrive 51 ------------------------------------------------------------------------------- 4) Type in the command ASSEMBLE S#"test" for cassette ASSEMBLE S#*"m";1;"test" for Microdrive which will execute the multi-part Assembly and display the results on the screen as follows:- 5E0A 0010 ORG # 5E0A 3E02 0020 START LD A,2 5E0C CD0116 0030 CALL 1601H 5E0F 211E5E 0040 LD HL,MSG 5E12 0615 0050 LD B,LEN 5E14 7E 0010 LOOP LD A,(HL) 5E15 E5 0020 PUSH HL 5E16 C5 0030 PUSH BC 5E17 D7 0040 RST 16 5E18 C1 0050 POP BC 5E19 E1 0010 POP HL 5E1A 23 0020 INC HL 5E1B 10F7 0030 DJNZ LOOP 5E1D C9 0040 RET 5E1E 0050 MSG DEFM "A multi-part Assembly" 0015 0060 LEN EQU $-MSG 0070 END LEN 0015 MSG 5E1E LOOP 5E14 START 5E0A # 5E0A At Assembly time, you may well get an Assembly error such as "Jump out of range". If this happens, amend the appropriate section of listing (if it is not the section currently in the Text Buffer, use LOAD "name"#n or LOAD *"m";1;"name"#n to Load the correct section) and Save the amended listing with the appropriate Save command for that section. Ensure that the file name and section number are correct for that section, and overwrite the original section. If you are in any doubt about overwriting the original section, Save it onto cassette or another Microdrive Cartridge first. Having Saved the amended section, start the Assembly process again with the appropriate ASSEMBLE # command. It is recommended that when using Microdrive you work with two Cartridges, and update each one alternately. In this way you will always be able to refer back to the previous listing, and will have it available should you damage one Cartridge. Error Messages When using the EDITOR to enter a listing, the only error message you are likely to encounter is MEMORY FULL. It is displayed if the line you are about to enter will cause the Text Buffer and the Object Buffer to overlap. The remaining Error Messages only appear at Assembly time, and are followed by an automatic display, in the EDIT Mode, of the line that contains the error. The cursor will be at the right hand end of the line, as if you had just EDITed the line. You must now correct the error and press ENTER to re-insert the line into the listing before continuing. Error messages and their causes are as follows: 52 ------------------------------------------------------------------------------- INVALID ORG (i) If the first line of the program (excluding comment lines) is not a definition of ORG. (ii) If there is more than one line in the program that defines an ORG. The line containing the second occurrence is displayed at the bottom of the screen. INVALID NUMBER If a Decimal number contains a non-numeric character, or if a Hex number contains an invalid character. INVALID OP (i) If an operation name is not recognised (ii) If a numeric operand has a value out of range for the particular operation (e.g. loading a single register with a Label whose value is greater than 255). (iii) If an invalid mnemonic is entered, (e.g. if there is an incorrect number of operands). LABEL NOT DEFINED (i) If an operand is not a recognised register or condition and no label of that name has been defined. (ii) If a Hex number does not commence with a number. (iii) If EQU, DEFL or DEFS have an operand that is a label which has not been defined in a previous line of the listing, or in a previous section. (These directives cannot refer forward to labels. LABEL ALREADY DEFINED If a Label name is defined more than once and the first definition is not DEFL. The line containing the second definition is displayed. NO END INSTR. If there is not a line containing the END instruction. JUMP OUT OF RANGE If a relative jump (JR or DJNZ) is asked to jump to an address with an offset of more than +127 or -128. MEMORY FULL (i) On entry of a line into the listing if that line will cause a Text Buffer and Label Table to over-write the Object Buffer (ii) On Assembly, if the Object Buffer would overwrite the Label Table and Text Buffer when the current line being assembled is entered into the Buffer. PRINTER OFF LINE If you are using a Centronics Printer and the Printer is OFF LINE (most printers can be taken off line to manually advance the paper) the BUSY signal from the printer will be SET to prevent data being sent. If the printer is BUSY for more than about one second, the Assembler assumes it is OFF LINE and produces this error, while still checking the BUSY signal. As soon as the printer's BUSY signal is cleared, the Assembler starts sending data. Pressing CAPS SHIFT+BREAK will return the Assembler's cursor. 53 ------------------------------------------------------------------------------- Microdrive/Network/RS232 Errors Microdrive full There is not sufficient room on the Cartridge for the file being Saved. Drive WRITE PROTECTED Attempting to Save a Microdrive where the Cartridge's Write Protect tab has been removed. Wrong FILE type Attempting to Load into the Text Buffer a file that is not a valid Source Code file. (i.e. Object Code or Basic program). Memory full Can appear when Saving to Microdrive or Network. Because of the extra Channel space created for Micro- drive or Network use, the Assembler temporarily moves the Object Buffer up memory while these commands are executed. If there is not enough space to do this without overwriting buffers, the error message is shown. A program could Assemble without error, and then display this message when Saved. Delete comment lines, or use 'Assembly from Microdrive or Cassette' to remedy. Summary of Commands and Forms All commands are executed by pressing ENTER. All references to the ZX Printer include a Centronics Printer depending on how the program was initially customised. LIST (Key K) Lists Source Code to screen from start. 10 lines displayed. Space gives next 10 lines. LIST nn Lists Source Code to screen from Line nn, for 10 lines. Space gives next 10 lines. LIST / (Key K + Lists to ZX Printer only, from start of Source Code, through to Symbol Shift the end of the listing, without stopping. BREAK stops, but and Key V) leaves you in Basic. LIST /nn List to ZX Printer from line nn to end of listing. BREAK as above. LIST * (Key K + List to RS232 Printer from start of Source Code through to the Symbol Shift end of the listing without stopping. BREAK stops but leaves and Key B) you in Basic. List * nn Lists to RS232 Printer from Line nn to end of listing. BREAK as above. LIST LABEL List Source Code from definition of label LABEL. EDIT (Caps Shift + Displays the first line of listing at bottom of screen, ready for Key 1) Editing. EDIT nn Displays Line nn as above. 54 ------------------------------------------------------------------------------- AUTO (Symbol Shift Selects Auto line numbering adding last specified Step value and '+') to last AUTO line number displayed. AUTO nn Selects Auto Line Numbering from line nn. AUTO x,y Selects Auto line Numbering with x = step value (1 to 99) y = line number to start from RETURN (Key Y) Return to Basic. NEW (Key A) Gives Entry message. If 'N' typed in response, Source Code is cleared and Label Table cleared completely. If 'C typed, nothing is changed. CLEAR (Key X) Clears the Source Code Buffer, but retains and protects the current Label Table. ASSEMBLE (Key R) Assembles Object Code with no screen or printer output. Key M will PAUSE the Label Table screen display only. CAPS SHIFT + BREAK stops early. ASSEMBLE S (Key R + Assembles Object Code and displays assembled code to Key S) screen. Key M will PAUSE. ASSEMBLE / (Key R + Assembles Object Code and displays assembled code to ZX Symbol Shift + Printer only. Key V) Key M will PAUSE. ASSEMBLE * (Key R + Assembles Object Code and displays assembled code to Symbol Shift + RS232 printer via Interface 1 RS232 link. Key B) Key M will PAUSE. label (Key L) Displays the current Label Table to the screen, providing the display is enabled. Key M will PAUSE. label 0 (Key L + Key 0) Disables the Label Table display. label 1 (Key L + Key 1) Enables the Label Table display, and displays table to screen. label / (Key L + Prints current Label Table to the ZX Printer, providing it is Symbol Shift + enabled. Key V) label * (Key L + Prints current Label Table to RS232 printer via Interface 1, Symbol Shift + providing it is enabled. Key B) label NAME Prints value of NAME to screen. 55 ------------------------------------------------------------------------------- COPY x,y,z (Key C) Copies lines x to y inclusive to new location at line z. DELETE x,y (Key D) Deletes lines x to y inclusive. RENUM x,y,z Renumbers Text Buffer listing, where x = Step value (1 to 99) y = the existing Line Number (actually z = z + x) Cassette commands: SAVE "name"C (Save on Key S) Saves Object Code to cassette from Object Buffer. "name" is file name: max 10 characters. SAVE "name"T Saves Text (Listing) to cassette. "name" is file name: max 10 characters. VERIFY "name" (Verify on Verifies named file. ASSEMBLER knows whether it is a Key V) Source Code or Object Code. VERIFY "" Verifies first file from cassette with appropriate buffer. LOAD "name" (Load on Key J) Displays file name with ident. 'BYTES': If file is Source Code Loads named file into Source Code buffer, and clears Label Table completely. LOAD "name"N As above. LOAD "name"C Displays file name with ident. 'Bytes': If file is Source Code loads named file into Source Code buffer, and retains and protects Label Table as in CLEAR. LOAD "name"A Displays file name with ident. BYTES: If file is Source Code, Appends new file to that in Text Buffer and clears Label Table. LOAD "" As LOAD "name", but loads 1st Source Code File from tape. LOAD ""N As LOAD "name"N but loads 1st Source Code File from tape. LOAD ""C As LOAD "name"C but loads 1st Source Code File from tape. LOAD ""A As LOAD"name"A but loads 1st Source Code File from tape. Microdrive/Network/RS232 commands: SAVE *"m";d;"name"T Saves current Text Buffer file to Drive d with filename "name" SAVE *"m";d;"name"C Saves current Object Buffer to Drive d with filename "name". 56 ------------------------------------------------------------------------------- LOAD *"m";d;"name"N If file is valid Source Code, deletes existing Text Buffer and Label Table and Loads file into Text Buffer. (Suffix N is optional) LOAD *"m";d;"name"C Deletes existing Text Buffer, protects current Label Table, and Loads file into Text Buffer. LOAD *"m";d;"name"A Appends new file to end of current Text Buffer and deletes current Label Table. VERIFY *"m";d;"name" Verifies file "name" against Text Buffer or Object Buffer as appropriate. SAVE *"n";sT Saves the current Text Buffer file to Station number s. SAVE *"n";sC Saves the current Object Buffer to Station numbers. LOAD *"n";sN If incoming data is a valid Source Code file, deletes existing Text Buffer and Label Table and Loads incoming data into Text Buffer. (Suffix N is optional) LOAD *"n";sC If incoming data is a valid Source Code file, deletes existing Text Buffer, protects current Label Table and Loads incoming data into Text Buffer. LOAD *"n";sA If incoming data is a valid Source Code file, Appends incoming data to end of current Text Buffer and deletes current Label Table. VERIFY "n";s Verifies incoming data against Text Buffer or Object Buffer as appropriate. SAVE *"b"T Saves current Text Buffer to RS232 output of Interface 1. SAVE *"b"C Saves current Object Buffer to RS232 output of Interface 1. LOAD *"b"N If incoming data is valid Source Code, deletes existing Text Buffer and Label Table and Loads data into Text Buffer (N is optional). LOAD *"b"C If incoming data is valid Source Code, deletes existing Text Buffer and protects current Label Table, and Loads data into Text Buffer. LOAD *"b"A If incoming data is valid Source Code, Appends incoming data to end of current Text Buffer and deletes current Label Table. VERIFY *"b" Verifies incoming data against Text Buffer or Object Buffer as appropriate. 57 ------------------------------------------------------------------------------- SECTION 3 Using "EDITAS" and "MONITOR" together While you are developing a machine code program it can be useful to have both the ASSEMBLER and the MONITOR in memory together. This will let you assemble and test your code without spending a lot of time loading and reloading our software. The most convenient way to achieve this is shown in the memory map below. ___________________________________________________________ | | | | > < | | | | | |Screen| |Object> < Source | | M |U| |ROM| & |Basic| >>> SPARE <<< |EDITAS| O |D| | | VARS | |Buffer> < Code | | N |G| | | | | > < | | | | |___|______|_____|______>___________<________|______|___|_| ^ ^ | | | | (STKEND)+256 RAMTOP First load the customised copy of the Monitor and force it to reside as high as possible in memory by giving a load address of 0. This will leave RAMTOP underneath the MONITOR. (Don't forget to note down the address for access from Basic). Then you can load the ASSEMBLER which will load and relocate itself underneath the MONITOR. Access between the two programs is by returning to Basic and accessing the other program. The ASSEMBLER will obviously have less space available to it than if it was in memory alone, but you should still be able to assemble around 6K to 7K of code. If you now use ORG # in your Source Code, the Object Code produced by the ASSEMBLER in the Object Buffer will be correctly assembled to run there (the # label has the address of the start of the Object Buffer). Assemble the code and note down the value of the # label. Access the MONITOR and test your code in the Object Buffer (having first saved the Source Code from the ASSEMBLER). If you find an error in your program you can re-enter the ASSEMBLER and make the necessary corrections, then re-assemble and continue testing with the MONITOR. When you are sure that your program is error free, go back to the ASSEMBLER once more and change the ORG address to the memory location where your code will ultimately live, and re-assemble it. You can now save the Object Code to cassette or Microdrive ready for use on its own. 58 ------------------------------------------------------------------------------- APPENDIX A Z80 MNEMONICS A full list of Z80 Mnemonics acceptable to the ASSEMBLER ADC A,(HL) BIT 3,(HL) DEC (IY+5) LD (HL),H ADC A,(IX+5) BIT 3,(IX+5) DEC A LD (HL),L ADC A,(IY+5) BIT 3,(IY+5) DEC B LD (HL),32 ADC A,A BIT 3,A DEC BC LD (IX+5),A ADC A,B BIT 3,B DEC C LD (IX+5),B ADC A,C BIT 3,C DEC D LD (IX+5),C ADC A,D BIT 3,D DEC DE LD (IX+5),D ADC A,E BIT 3,E DEC E LD (IX+5),E ADC A,H BIT 3,H DEC H LD (IX+5),H ADC A,L BIT 3,L DEC HL LD (IX+5),L ADC A,20H BIT 4,(HL) DEC IX LD (IX+3),32 ADC HL,BC BIT 4,(IX+5) DEC IY LD (IY+5),A ADC HL,DE BIT 4,(IY+5) DEC L LD (IY+5),B ADC HL,HL BIT 4,A DEC SP LD (IY+5),C ADC HL,SP BIT 4,B DI LD (IY+5),D ADD A,(HL) BIT 4,C DJNZ 2EH LD (IY+5),E ADD A,(IX+5) BIT 4,D EI LD (IY+5),H ADD A,(IY+5) BIT 4,E EX (SP),HL LD (IY+5),L ADD A,A BIT 4,H EX (SP),IX LD (IY+5),32 ADD A,B BIT 4,L EX (SP),IY LD (0584H),A ADD A,C BIT 5,HL) EX AF,A'F' LD (0584H),BC ADD A,D BIT 5,(IX+5) EX DE,HL LD (0584H),DE ADD A,E BIT 5,(IY+5) EXX LD (0584H),HL ADD A,H BIT 5,A HALT LD (0584H),IX ADD A,L BIT 5,B IM0 LD (0584H),IY ADD A,32 BIT 5,C IM1 LD (0584H),SP ADD HL,BC BIT 5,D IM2 LD A,(BC) ADD HL,DE BIT 5,E IN A,(C) LD A,(DE) ADD HL,HL BIT 5,H IN B,(C) LD A,(HL) ADD HL,SP BIT 5,L IN C,(C) LD A,(IX+5) ADD IX,BC BIT 6,(HL) IN D,(C) LD A,(IY+5) ADD IX,DE BIT 6,(IX+5) IN E,(C) LD A,(0584H) ADD IX,IX BIT 6, (IY+5) IN H,(C) LD A,A ADD IX,SP BIT 6,A IN L,(C) LD A,B ADD IY,BC BIT 6,B INC (HL) LD A,C ADD IY,DE BIT 6,C INC (IX+5) LD A,D ADD IY,IY BIT 6,D INC (IY+5) LD A,E ADD IY,SP BIT 6,E INC A LD A,H AND (HL) BIT 6,H INC B LD A,I AND (IX+5) BIT 6,L INC BC LD A,L AND (IY+5) BIT 7,(HL) INC C LD A,32 AND A BIT 7,(IX+5) INC D LD A,R AND B BIT 7,(IY+5) INC DE LD B,(HL) AND C BIT 7,A INC E LD B,(IX+5) AND D BIT 7,B INC H LD B,(IY+5) AND E BIT 7,C INC HL LD B,A AND H BIT 7,D INC IX LD B,B AND L BIT 7,E INC IY LD B,C AND 32 BIT 7,H INC L LD B,D BIT 0,(HL) BIT 7,L INC SP LD B,E BIT 0,(IX+5) CALL C,0584H IN A,(32) LD B,H BIT 0,(IY+5) CALL M,0584H IND LD B,L BIT 0,A CALL NC,0584H INDR LD B,32 BIT 0,B CALL NZ,0584H INI LD BC,(0584H) BIT 0,C CALL P,0584H INIR LD BC,0584H BIT 0,D CALL PE,0584H JP 0584H LD C,(HL) BIT 0,E CALL PO,0584H JP HL LD C,(IX+5) BIT 0,H CALL Z,0584H JP IX LD C,(IY+5) BIT 0,L CALL 0584H JP IY LD C,A BIT 1,(HL) CCF JP C,0584H LD C,B BIT 1,(IX+5) CP (HL) JP M,0584H LD C,C BIT 1,(IY+5) CP (IX+5) JP NC,0584H LD C,D BIT 1,A CP (IY+5) JP NZ,0584H LD C,E BIT 1,B CP A JP P,0584H LD C,H BIT 1,C CP B JP PE,0584H LD C,L BIT 1,D CP C JP PO,0584H LD C,32 BIT 1,E CP D JP Z,0584H LD D,(HL) BIT 1,H CP E JR C,2EH LD D,(IX+5) BIT 1,L CP H JR NC,2EH LD D,(IY+5) BIT 2,(HL) CP L JR NZ,2EH LD D,A BIT 2,(IX+5) CP 32 JR Z,2EH LD D,B BIT 2,(IY+5) CPD JR 2EH LD D,C BIT 2,A CPDR LD (BC),A LD D,D BIT 2,B CPIR LD (DE),A LD D,E BIT 2,C CPI LD (HL),A LD D,H BIT 2,D CPL LD (HL),B LD D,L BIT 2,E DAA LD (HL),C LD D,32 BIT 2,H DEC (HL) LD (HL),D LD DE,(0584H) BIT 2,L DEC (IX+5) LD (HL),E LD DE,0584H 59 ------------------------------------------------------------------------------- LD E,(HL) RES 0,C RL D SET 2,H LD E,(IX+5) RES 0,D RL E SET 2,L LD E,(IY+5) RES 0,E RL H SET 3,(HL) LD E,A RES 0,H RL L SET 3,(IX+5) LD E,B RES 0,L RLA SET 3,(IY+5) LD E,C RES 1,(HL) RLC (HL) SET 3,A LD E,D RES 1,(IX+5) RLC (IX+5) SET 3,B LD E,E RES 1,(IY+5) RLC (IY+5) SET 3,C LD E,H RES 1,A RLC A SET 3,D LD E,L RES 1,B RLC B SET 3,E LD E,32 RES 1,C RLC C SET 3,H LD H,(HL) RES 1,D RLC D SET 3,L LD H,(IX+5) RES 1,E RLC E SET 4,(HL) LD H,(IY+5) RES 1,H RLC H SET 4,(IX+5) LD H,A RES 1,L RLC L SET 4,(IY+5) LD H,B RES 2,(HL) RLCA SET 4,A LD H,C RES 2,(IX+5) RLD SET 4,B LD H,D RES 2,(IY+5) RR (HL) SET 4,C LD H,E RES 2,A RR (IX+5) SET 4,D LD H,H RES 2,B RR (IY+5) SET 4,E LD H,L RES 2,C RR A SET 4,H LD H,32 RES 2,D RR B SET 4,L LD HL,(0584H) RES 2,E RR C SET 5,(HL) LD HL,0584H RES 2,H RR D SET 5,(IX+5) LD I,A RES 2,L RR E SET 5,(IY+5) LD IX,(0584H) RES 3,(HL) RR H SET 5,A LD IX,0584H RES 3,(IX+5) RR L SET 5,B LD IY,(0584H) RES 3,(IY+5) RRA SET 5,C LD IY,0584H RES 3,A RRC (HL) SET 5,D LD L,(HL) RES 3,B RRC (IX+5) SET 5,E LD L,(IX+5) RES 3,C RRC (IY+5) SET 5,H LD L,(IY+5) RES 3,D RRC A SET 5,L LD L,A RES 3,E RRC B SET 6,(HL) LD L,B RES 3,H RRC C SET 6,(IX+5) LD L,C RES 3,L RRC D SET 6,(IY+5) LD L,D RES 4,(HL) RRC E SET 6,A LD L,E RES 4,(IX+5) RRC H SET 6,B LD L,H RES 4,(IY+5) RRC L SET 6,C LD L,L RES 4,A RRCA SET 6,D LD L,32 RES 4,B RRD SET 6,E LD R,A RES 4,C RST 0 SET 6,H LD SP,(0584H) RES 4,D RST 8H SET 6,L LD SP,HL RES 4,E RST 10H SET 7,(HL) LD SP,IX RES 4,H RST 18H SET 7,(IX+5) LD SP,IY RES 4,L RST 20H SET 7,(IY+5) LD SP,0584H RES 5,(HL) RST 28H SET 7,A LDD RES 5,(IX+5) RST 30H SET 7,B LDDR RES 5,(IY+5) RST 38H SET 7,C LDI RES 5,A SBC A,(HL) SET 7,D LDIR RES 5,B SBC A,(IX+5) SET 7,E NEG RES 5,C SBC A,(IY+5) SET 7,H NOP RES 5,D SBC A,A SET 7,L OR (HL) RES 5,E SBC A,B SLA (HL) OR (IX+5) RES 5,H SBC A,C SLA (IX+5) OR (IY+5) RES 5,L SBC A,D SLA (IY+5) OR A RES 6,(HL) SBC A,E SLA A OR B RES 6,(IX+5) SBC A,H SLA B OR C RES 6,(IY+5) SBC A,L SLA C OR D RES 6,A SBC A,32 SLA D OR E RES 6,B SBC HL,BC SLA E OR H RES 6,C SBC HL,DE SLA H OR L RES 6,D SBC HL,HL SLA L OR 32 RES 6,E SBC HL,SP SRA (HL) OTDR RES 6,H SCF SRA (IX+5) OTIR RES 6,L SET 0,(HL) SRA (IY+5) OUT (C),A RES 7,(HL) SET 0,(IX+5) SRA A OUT (C),B RES 7,(IX+5) SET 0,(IY+5) SRA B OUT (C),C RES 7,(IY+5) SET 0,A SRA C OUT (C),D RES 7,A SET 0,B SRA D OUT (C),E RES 7,B SET 0,C SRA E OUT (C),H RES 7,C SET 0,D SRA H OUT (C),L RES 7,D SET 0,E SRA L OUT (32),A RES 7,E SET 0,H SRL (HL) OUTD RES 7,H SET 0,L SRL (IX+5) OUTI RES 7,L SET 1,(HL) SRL (IY+5) POP AF RET SET 1,(IX+5) SRL A POP BC RET C SET 1,(IY+5) SRL B POP DE RET M SET 1,A SRL C POP HL RET NC SET 1,B SRL D POP IX RET NZ SET 1,C SRL E POP IY RET P SET 1,D SRL H PUSH AF RET PE SET 1,E SRL L PUSH BC RET PO SET 1,H SUB (HL) PUSH DE RET Z SET 1,L SUB (IX+5) PUSH HL RETI SET 2,(HL) SUB (IY+5) PUSH IX RETN SET 2,(IX+5) SUB A PUSH IY RL (HL) SET 2,(IY+5) SUB B RES 0,(HL) RL (IX+5) SET 2,A SUB C RES 0,(IX+5) RL (IY+5) SET 2,B RES 0,(IY+5) RL A SET 2,C RES 0,A RL B SET 2,D RES 0,B RL C SET 2,E 60 ------------------------------------------------------------------------------- SUB D SUB 32 XOR A XOR E SUB E XOR (HL) XOR B XOR H SUB H XOR (IX+5) XOR C XOR L SUB L XOR (IY+5) XOR D XOR 32 Extra Z80 Instructions There are a number of Z80 instructions that are not published or documented by Zilog, but which appear to work on all Z80s. They have been found by experiment on some of the apparently missing Hex code sequences. They are mainly operations on the individual halves of the IX and IY register pairs. EDITAS will accept these instructions in the forms shown below, but the MONITOR will decode them to their HL equivalents. Generally, the MSB of IX is called XH and the LSB is called XL; the MSB of IY is YH and the LSB YL. There is one extra arithmetic instruction, SLL, which Shifts the byte to the left by one BIT, puts BIT 7 into the CARRY and SETs BIT 0. The flag results for SLL are as for SRL The extra instructions are:- SLL (HL) LD XL,A SLL (IX+5) LD YL,A SLL (IY+5) LD A,XH SLL A LD A,YH SLL B LD A,XL SLL C LD A,YL SLL D ADD XH SLL E ADD YH SLL H ADD XL SLL L ADD YL INC XH ADC XH INC YH ADC YH DEC XH ADC XL DEC YH ADC YL LD XH,32 SUB XH LD YH,32 SUB YH INC XL SUB XL INC YL SUB YL DEC XL SBC XH DEC YL SBC YH LD XL,32 SBC XL LD YL,32 SBC YL LD B,XH AND XH LD B,YH AND YH LD B,XL AND XL LD B,YL AND YL LD C,XH XOR XH LD C,YH XOR YH LD C,XL XOR XL LD C,YL XOR YL LD D,XH OR XH LD D,YH OR YH LD D,XL OR XL LD D,YL OR YL LD E,XH CP XH LD E,YH CP YH LD E,XL CP XL LD E,YL CP YL LD XH,B LD YH,B LD XH,C LD YH,C LD XH,D LD YH,D LD XH,E LD YH,E LD XH,XL LD YH,YL LD XH,A LD YH,A LD XL,B LD YL,B LD XL,C LD YL,C LD XL,D LD YL,D LD XL,E LD YL,E LD XL,XH LD YL,YH 61 -------------------------------------------------------------------------------