NoICE - Debugger for 8 Bit Microprocessors (v2.5) (copyright (c) 1992 to 1995 by John Hartman) 1. INTRODUCTION NoICE is a PC-hosted debugger for use with a variety of microprocessor targets. It is intended to replace the hex monitor programs often used for such debugging, but is much more powerful. The debugger consists of a target-specific DOS program, NOICExxx.EXE, and a target-resident monitor program. The two programs communicate via RS-232, at user selectable baud rates from 300 to 57600. Processors currently supported are the Z80/Z180, Z8, 8051, 80(1)96, 6809, 68HC11, 68(HC)05, 65(C)02, and M50740/M38000. The PC-hosted approach has a number of advantages over a simple hex monitor: The target-resident monitor is simple and small: less than 1024 bytes for most versions. The simplicity of the monitor eases the process of porting to new hardware platforms. The PC has a more flexible display than the generic terminals used by most hex monitors. NoICE maintains a number of windows containing register, source, and other data. Because the size of code on the PC does not penalize the target, a wide variety of features may be added. NoICE includes: * Source level debug (currently, assembly language files only) * A disassembler. * A file viewer for files of any size, in ASCII or hex. * Memory display and editing, including loading of Intel Hex and Motorola S1 record files. * A virtually unlimited number of breakpoints. * Hardware-free single step using automatically inserted breakpoints. * Definition of symbols, which may be used in expressions and by the disassembler. * The ability to record and play back files of commands. * On-line help NoICE may be operated via pull-down menus, using either mouse or keyboard, or via a command line. Keyboard commands are generally similar to those of traditional hex monitors. Command keywords are case insensitive. The function keys provide single-key invocation of common commands. Other commands must be terminated with a carriage return. Until carriage return is pressed, the command may be edited. Figure 1-1 shows the NoICE screen display for the Z80. Other processors are similar. The top line is the "menu", from which selections may be made using the mouse or ALT-keys. Below the menu is the "register window", in which processor registers are displayed. Immediately below the register window is the "source window", in which source code or disassembled processor instructions are displayed. Below the source window is the "data window", which is used for output which does not appear in either the source or the register window. The bottom line of the screen shows function key definitions (which are also mouse-sensitive), and the line above it is the command entry line. ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ File View Memory Symbols Break Run Processor Options ³ ³ A BC DE HL IX IY PC SP FL AF' BC' DE' HL' I IFF PG ³ ³ 01 0000 0000 0000 0000 0000 000B 0000 .....V.C 0000 0000 0000 0000 00 0 00 ³ ³ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ(RESET)ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄij ³ 0000 F3 DI ³ ³ 0001 C3AC00 JP 00AC ³ ³ 0004 00 NOP ³ ³ 0005 00 NOP ³ ³ 0006 00 NOP ³ ³ 0007 00 NOP ³ ³ 0008 F5 PUSH AF ³ ³ 0009 3E01 LD A,01 ³ ³ 000B C3BB01 JP 01BB ³ ³ 000E 00 NOP ³ ³ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ File monz80.l line 201 ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄij ³ 198 ; Interrupt RST 08. Used for breakpoint. Any ³ ³ 199 ; may be used instead by changing the code belo³ ³ 200 ; breakpoint instruction in the status string T³ ³ 201 ; be used, then CALL may be used instead. Howe³ ³ 202 ; the placement of breakpoints, since CALL is a³ ³00000008 f5 203 push af ³ ³00000009 3e01 204 ld a,1 ;state =³ ³0000000b c3Wwww 205 jp INT_ENTRY ³ ³> ³ ³F1=help F2=dump F3=disasm F4=view F5=go F6=break F7=step F8=next F10=menu ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ Figure 1-1 NoICE Screen Display 1.1. NoICE Target Requirements NoICE requires a small monitor program running on the target processor. The resources used by this monitor are similar to those required by "classic" hex debug monitors such as BUFFALO for the 68HC11, or Steve Kemplin's MONPLUS for the 8051: * Enough EPROM to hold the monitor (about 1024 bytes; smaller than most stand-alone monitors). * Enough RAM to hold the monitor's data (32 to 256 bytes, depending on the number of processor registers and the desired communications buffer size). * A UART to communicate with the PC host (or an input bit, an output bit, and the appropriate user-provided bit-banging serial code). * Enough RAM to hold the program to be downloaded and debugged. If the processor distinguishes between code and data space (e.g., the 8051 or the Z8), then hardware external to the processor is required to allow the program space to be read and written by the processor. On the 8051, this will require circuitry to OR together PSEN and RD, and to connect WR. * A "bash button" connected to a non-maskable interrupt is useful, but is not required. * Special hardware to support single step operation is NOT required. As provided on the distribution disk, the monitors run with interrupts disabled. This is generally the best way to run a monitor, as it essentially "freezes time" while the monitor is running. User code can use interrupts by enabling them as appropriate. Interrupts will be disabled by the monitor upon breakpoint or other entry, and will be restored to their pre-entry states before the user code is resumed. Since the EPROM containing the monitor will generally reside in the portion of the processor address space where the interrupt vectors and/or interrupt handler entrypoints reside, most of the monitors re-direct the interrupts to an area of the download RAM. The location of this area is determined by equates within each monitor. There are two basic schemes: "ROM at the bottom" processors such as the Z80 and 8051 begin execution at address zero after reset. Interrupts cause calls to reserved locations in low memory. In order for the NoICE monitor to take control after reset, it must reside in low memory. The monitor contains code to route interrupts other than reset through the lower portion of the download RAM, beginning at an address defined as USER_CODE in the monitor source. The layout of this region of USER_CODE is identical to the "real" reset and interrupt region. Thus, a user program may be debugged by locating or ORGing it to begin at USER_CODE, and may be burned into EPROM by locating or ORGing it at zero. Typically, only this single equate needs to be changed between debug and EPROM versions. Refer to the source file for your target monitor for the exact details of the routing process. "ROM at the top" processors such as the 6809, 6805, 68HC11, and M38000 begin execution by fetching an address from an interrupt vector table at address 0FFFxH after reset. The addresses of interrupt handlers are stored in the same vector table. In order for the NoICE monitor to take control after reset, it (or at least a reset vector to it) must reside in high memory. The monitor contains code to route interrupts other than reset through a user vector table in download RAM, beginning at an address defined as USER_VECTORS in the monitor source. The layout of USER_VECTORS is identical to the "real" reset and interrupt vectors. Thus, a user program may be debugged by locating or ORGing it to begin at USER_CODE, with vectors at USER_VECTORS, and may be burned into EPROM by locating or ORGing the vectors at 0FFFxH. Typically, only this equate, and perhaps the location of the code, needs to be changed between debug and EPROM versions. Refer to the source file for your target monitor for the exact details of the interrupt routing process. When the monitor is first started, it initializes the interrupt region of download RAM to point to default interrupt handlers within the monitor. Thus, if an interrupt occurs for which the user code has not provided a handler, the default handler will cause entry into the monitor as if a breakpoint had been executed. The identity of the interrupt will be displayed by NoICE below the register window as the processor state. Some target monitors do not route certain interrupts which are used by the monitors. For example, SWI (software interrupt) on the 68HC11 is used for a breakpoint instruction. Thus, it passes directly to the monitor. The 68HC11 COP Fail interrupt is not normally routed, as its occurrence is generally considered to indicate a "fatal error". This could be changed if desired by modifying the monitor code appropriately. 1.2. NoICE Host (PC) Requirements NoICE assumes an 80286 or higher processor running DOS 3.3 or later. Most testing was done on a color VGA display, but EGA, CGA, or Monochrome should work as well. NoICE has been successfully run in DOS windows under Microsoft Windows (tm) and IBM Warp (tm). 2. INVOKING NoICE NoICE is invoked via the command line NOICExx COMn=baud LINES=mm @cmdfile where all parameters are optional and order independent. "COMn" specifies the PC serial port to be used, and may be either COM0, COM1, COM2, COM3 (on IRQ4) or COM4 (on IRQ3). "baud" specifies the baud rate, which may be any value between 300 and 57600 baud. Note that the baud rate must match that used by the target monitor. The default if this parameter is omitted is COM1=19200. "COM0" at any baud rate causes NoICE to simulate the target without any communications. Currently, the simulation is very simple, supporting only reading and writing of memory, but not program execution. It is intended to allow a potential user to play with the command set without going through the effort of building a target monitor. The optional parameter "LINES=mm" specifies the number of lines to be used for the display. Legal values for "mm" are 0, 25, 43, or 50. The default if this parameter is omitted is 0. On VGA systems, specifying either 43 or 50 will result in 50 lines. On EGA systems, specifying either 43 or 50 will result in 43 lines. A value of 0 sets the number of lines used by NoICE to the number of lines on the current screen. This may be used in conjunction with custom character sets to give 36 or other non-standard numbers of lines. (The author likes more than 25 lines, but has eyes too bad to use 50 lines. Various public domain and shareware utilities allow the creation and loading of appropriate custom character sets.) The optional parameter "SHOW=1" tells NoICE to display in hex all message bytes sent to and received from the target. This is useful when debugging a new target monitor. The final optional parameter specifies a file of NoICE commands to be executed after NoICE initializes. For example, these might be used to load the file being debugged, and perhaps symbol or line number information. When NoICE is invoked, it looks in the current directory for the configuration file NOICE.CFG. If this file does not exist, NoICE will look for NOICE.CFG in the directory where the NoICE executable (NOICExxx.EXE) resides. If either file is found, the commands contained in the file are executed. Only certain NoICE commands are allowed in NOICE.CFG. These are listed in section 3.1. If command line parameters are specified, they will override any commands from NOICE.CFG. If a parameter is not specified either as a command line parameter or in NOICE.CFG, the defaults are COM1=19200, lines=0, and show=0. 3. COMMAND SUMMARY This section lists the commands in alphabetical order. For more details on the operation and parameter format of each command, refer to the appropriate sections of NOICE.HLP. If you have used a previous version of NoICE, refer to section 19 for a summary of changes from earlier versions. in each command: * curly brackets {} denote optional parameters. * "addr" denotes an address or address expression * "size" denotes a size or size expression * "value" denotes an expression @file Execute commands from "file" ASCII Change viewer to ASCII mode AUTOGEN Abbreviation of AUTOGENERATE AUTOGENERATE value Turn automatic symbol generation on and off B Abbreviation of BREAK BREAK {addr} Insert, delete, or display breakpoints CAPTURE file Capture disassembly, dump, and target output to file CAPTURESPEC filespec Set filespec for CAPTURE command CASE value Turn symbol case sensitivity on and off CHECK addr size Abbreviation of CHECKSUM CHECKSUM addr size Compute byte checksum on region CLEARSYMBOLS Delete all symbols COM0 rate Use simulated target COM1 rate Use COM1 at "rate" baud COM2 rate Use COM2 at "rate" baud COM3 rate Use COM3 at "rate" baud COM4 rate Use COM4 at "rate" baud COPY addr1 size addr2 Copy memory from addr1 to addr2 D Abbreviation of DUMP DEF Abbreviation of DEFINE DEFB Abbreviation of DEFBASE DEFBASE name value Define base symbol "name" DEFINE name value Define symbol "name" DELAY time Set delay for command playback DISASSEMBLE {addr} Disassemble beginning at addr DOS Temporary exit to DOS DUMP {addr} {size} Dump block of memory at addr in hex E {addr} {val} Abbreviation of EDIT ECHO {text string} Echo "text string" to data window EDIT {addr} {val} Examine/change memory F {text string} Abbreviation of FIND FIND {text string} Find the string in the view file FILE file {offset} Define the current file for source debug FILL addr size value Fill memory block at addr with value G Abbreviation of GO GO {addr} Begin execution at addr or at PC H Abbreviation of HELP HELP Show help display HEX Change viewer to hex mode I Abbreviation of IN IN addr Read byte from port L Abbreviation of LOAD LINE linum View the specified source line LINE linum addr Define address of source line LINES nlines Set number of screen lines LOAD file {offset} Load Intel or Motorola hex file LOADSPEC filespec Set filespec for Load and Save M Abbreviation of MEM (EDIT) MAINCOLOR val Set color of source and data windows MAINHIGHLIGHT val Set highlight color of main windows MAINSELECT val Set select color of main windows MENU Open the menu bar (select first item) MENUCOLOR val Set color of menu and dialog boxes MENUHIGHLIGHT val Set highlight color of menu and boxes MENUSELECT val Set select color of menu and boxes MEM {addr} {val} Same as "EDIT" MODE val Set source mode (0,1,2) N Abbreviation of NEXT NEXT Step over subroutine NOFILES Delete file and line number information NOVIEW Close the file viewer NV Abbreviation of NOVIEW O Abbreviation of OUT OUT addr val Write byte to port PLAY file Execute commands from "file" PLAYSPEC filespec Set filespec for Play and Record Q Abbreviation of QUIT QUIT Exit to DOS R Abbreviation of REGISTER REC file Abbreviation of RECORD RECORD file Record commands to file REFRESH Refresh file view REG {reg val} Abbreviation of REGISTER REGISTER {reg val} Change register REM {string} Remark (comment) for command files S {addr} Abbreviation of SOURCE SAVE file addr size Save block of memory as Intel hex file SET name value Same as DEFINE SHOW val Control hex display of communications SOURCE {addr} Show source code at beginning at addr ST Abbreviation of STEP STEP Step into subroutines STOP Stop recording commands to file SYM expr Abbreviation of SYMBOL SYMBOL expr Show symbol with value "expr" T Abbreviation of TRACE TRACE file Trace processor execution to file TRACESPEC filespec Set filespec for TRACE and VIEWTRACE commands U Abbreviation of UNASM UNASM {addr} Disassemble beginning at addr V Abbreviation of VIEW VAL Abbreviation of VALUE VALUE expr Show value of "expr" VER Abbreviation of VERSION VERSION Show host and target versions VIEW {file} View file VIEWSPEC filespec Set filespec for View command VIEWTRACE file View trace file VT Abbreviation of VIEWTRACE W Abbreviation of WATCH WATCH addr {len} {f} Watch data at "addr" The following commands may be invoked either by pressing the indicated function key, or by clicking on the function key title with the mouse. F1 Help F2 Dump next block F3 Disassemble next block F4 View file F5 Go F6 List Breakpoints F7 Step F8 Step Over F9 not assigned F10 Menu 3.1. Commands Allowed in NOICE.CFG Only the following commands are allowed in the configuration file NOICE.CFG. CAPTURESPEC filespec Set filespec for CAPTURE command CASE value Turn symbol case sensitivity on and off COM0 rate Use simulated target COM1 rate Use COM1 at "rate" baud COM2 rate Use COM2 at "rate" baud COM3 rate Use COM3 at "rate" baud COM4 rate Use COM4 at "rate" baud DEF Abbreviation of DEFINE DEFB Abbreviation of DEFBASE DEFBASE name value Define base symbol "name" DEFINE name value Define symbol "name" DELAY time Set delay for command playback LINES nlines Set number of screen lines LOADSPEC filespec Set filespec for Load and Save MAINCOLOR val Set color of source and data windows MAINHIGHLIGHT val Set highlight color of main windows MAINSELECT val Set select color of main windows MENUCOLOR val Set color of menu and dialog boxes MENUHIGHLIGHT val Set highlight color of menu and boxes MENUSELECT val Set select color of menu and boxes PLAYSPEC filespec Set filespec for Play and Record REM {string} Remark (comment) for command files SHOW val Control hex display of communications TRACESPEC filespec Set filespec for TRACE and VIEWTRACE commands VIEWSPEC filespec Set filespec for View command SECTIONS 4 THROUGH 11 ARE FOUND IN THE FILE NOICE.HLP 12. ERROR MESSAGES If the syntax of a command is incorrect, or if an error occurs during the execution of a command, an error will be displayed. The possible errors are listed below, along with possible reasons for their occurrences. BAD DATA IN FILE: the file specified for LOAD contains data inconsistent with the assumed file format. BAD RESPONSE FROM TARGET: the target has responded to a request with an incorrect response. This may indicate that the target has unexpectedly been reset, or is otherwise confused. BREAKPOINT OVERLAPS ANOTHER: an attempt was made to insert a multiple byte breakpoint one or more bytes of which would overlap the region where a breakpoint already exists. BREAKPOINT OVERLAPS INSTRUCTION: an attempt was made to insert a multiple byte breakpoint one or more bytes of which would overlap the instruction pointed to by the program counter. This may occur during single-step operation. CAN'T INIT COMM PORT: the communications port specified does not respond to initialization. COMMUNICATIONS ERROR: some communications error has occurred. This may indicate an incorrect baud rate, or connection to a serial device other than a NoICE target. DUPLICATE BREAKPOINT: an attempt was made to insert a breakpoint where one already exists. DUPLICATE LINE NUMBER: an attempt was made to define a line number at an address where one already exists. FATAL ERROR: some error has occurred which terminates NoICE. ILLEGAL DIGIT: a character was encountered during numeric conversion which is not legal in the conversion radix. ILLEGAL SYMBOL: the specified string is not a legal symbol name. ILLEGAL VALUE: the specified value is not legal for the current purpose. NO BREAKPOINT STORAGE: an attempt was made to insert a breakpoint for which insufficient local storage exists. NO FILE SPECIFIED: no file name was specified for a command which requires one. NO RESPONSE FROM TARGET: a timeout has occurred during communications with the target. This may indicate that the target has locked up, or that an incorrect port or baud rate was specified for NoICE. NO SUCH BREAKPOINT: the specified breakpoint does not exist. NO SUCH REGISTER: the specified register name is unknown on this target processor. NO SUCH SYMBOL: the specified symbol is not defined. NO SUCH WATCH: the specified watch does not exist. NO SYMBOL SPECIFIED: a symbol name was not specified for a command which requires one. NO WATCH STORAGE: an attempt was made to insert a watch for which insufficient local storage exists. NOT FOUND SEARCHING BACKWARD: the search target was not found while searching backward in the file. NOT FOUND SEARCHING FORWARD: the search target was not found while searching forwards in the file. OPERAND MISSING: an operator was not followed by an operand or expression. OPERATION ABORTED: the user has aborted a command, such as GO, by pressing Control-Break. OUT OF MEMORY: an operation was aborted due to the lack of allocable memory. This will primarily affect symbol definition when a very large number of symbols are defined. TARGET TYPE MISMATCH: the command has been aborted because the target is of a different type than expected by this NOICExx.EXE. NoICE asks the target for type information as part of its initialization, and when the VERSION command is invoked. If the target responds incorrectly to this poll, or does not respond to it, then NoICE will issue this error when a processor-specific command such as GO or REGISTER is attempted. This may occur if the target is powered off when NoICE is started. In this case, turn the target on and either exit and re-enter NoICE, or use VERSION to poll the target. TARGET WRITE FAILURE: target verification of a write indicates that the write was not successful. Perhaps the specified address is not RAM, or is an I/O device. UNEXPECTED FUNCTION KEY: an unrecognized function key was pressed. UNKNOWN COMMAND: an unrecognized command was entered. UNKNOWN FILE FORMAT: the specified file for LOAD is not in a known format. UNKNOWN OPERATOR: an operator unknown to NoICE was specified. WATCH TOO LONG: an attempt was made to define a watch with a data length longer than 128 bytes. 13. GENERATING SYMBOL FILES The use of symbols and source information can make debugging significantly easier. If there are only a few symbols to define, this may be done by hand, perhaps while viewing the link map and/or assembly listing file to determine symbol values. For large-scale use, however, it is convenient to generate the symbols automatically during the assembly and linking process. In the case of source level debugging, the automatic generation of line number information is the only practical method. While NoICE itself could have been taught to load symbols and line numbers in a variety of formats, this would make the program larger, and would restrict the number of formats supported. Thus, the approach taken was to write small utility programs which process the output of various cross assemblers and linkers. The output of this processing is a NoICE command file containing DEF (define) commands for the symbols to be defined, and FILE and LINE commands for line number definitions. The command file may then be interpreted by NoICE to define the symbols and line numbers. Thus, a new assembler or linker may be supported simply by writing the appropriate utility. The NoICE package includes symbol and line number processing utilities for a number of popular assemblers. The source code for these utilities is provided, in case you wish to customize them, or write a similar utility for use with another assembler. Unlike the remainder of NoICE, these utilities and their source code are public domain, and may be copied and modified at will for any non- commercial purpose. 13.1. AVOSYM and AVOSRC: Avocet AVMAC Avocet (tm) makes a line of cross assemblers which targets most 8 bit microprocessors. All share the same AVLINK linker. Because AVMAC is a relocatable assembler, two actions are required to define source line information. First, the assembly listing file(s) must be processed to define the line numbers relative to the beginning of each memory segment in each file. Second, the link map must be processed to determine the absolute addresses of the segments for each source file. The link map is also processed for global symbol definitions. 13.1.1. AVOSRC: Source Line Processing The NoICE utility AVOSRC.EXE processes an AVMAC listing file into a command file which defines FILE and LINE number information. The command line is: AVOSRC infile {cmdfile} where "infile" represents the listing file output by AVMAC, and "cmdfile" represents the output command file. AVMAC listing files normally have the extension ".PRN". If "cmdfile" already exists, the old file will be deleted and replaced by the new one. If "cmdfile" is omitted, output is to standard output. AVOSRC defines a source file line as "code producing" if the listing file shows an address, a line number, and at least one data value. When AVOSYM detects a code producing line, it generates a NoICE command of the form LINE nnn aaaa where "nnn" is the number of the source line as shown in the listing file, and "aaaa" is the address offset of the line from the base of the current segment. Since AVMAC macro invocation lines are normally ($NOSHOWMACS) listed as comments, and macro expansions are not listed, AVOSRC will not classify macro lines as code producing. AVOSRC relies on being able to detect SEG directives in the listing file in order to generate line number information relative to the appropriate segment. When AVOSYM detects a SEG directive, it generates a NoICE command of the form FILE filename.asm filename_segname where "filename" is the name of the file being processed (without extension), and "segname" is the name of the segment specified in the SEG directive. The value of the symbol "filename_segname" is assumed to be defined by the output of AVOSYM operating on the link map file, as described in the next section. For this reason, when loading under NoICE, the command file(s) produced by AVOSYM must be played before those produced by AVOSRC so that the symbols will be given values before they are used. If these symbols are not defined, an error will result. Since SEG directives which are located inside macros or include files will normally not be seen, AVOSRC will not work correctly in such cases. In most cases, INCLUDE files do not generate "code producing" lines as defined by AVOSRC, but are used to define macros and equates. If an INCLUDE file does produce code lines, then the processing by AVOSRC will depend on whether or not the contents of the INCLUDED file are visible in the listing file. If they are not visible ($NOSHOWINCS), then no line number information will be generated for the lines. If they are visible ($SHOWINCS), then incorrect line number information may be generated. If processing of INCLUDED source lines is desired, AVOSRC could be modified to recognize the INCLUDE directive and build a stack of open INCLUDE files, since these may be nested. This is left as an exercise for the reader... 13.1.2. AVOSYM: Map and Symbol Processing The NoICE utility AVOSYM.EXE processes the AVLINK map file into a command file which DEFINEs symbol and segment information. Use AVLINK with the -SM (show modules) and -SP (show publics) switches to generate an appropriate map. The command line to process the map is: AVOSYM mapfile {cmdfile} {-switches} where "mapfile" represents the map file output by AVLINK, and "cmdfile" represents the output command file. AVLINK map files normally have the extension ".MAP". If "cmdfile" already exists, the old file will be deleted and replaced by the new one. If "cmdfile" is omitted, output is to standard output. Optional switches are as follows: -b defines segment symbols as base symbols (default is non-base symbols) -pNN:LLLL:HHHH defines symbols in the range LLLL to HHHH as page NN (default is non- paged addressing). All values are in hex. The "-p" switch is intended to support paged memory. Since neither AVMAC nor AVLINK have any intrinsic support for paged memory, the user will have to link each overlay page separately, using the "-p" switch to place the symbols from each overlay in their appropriate page. Normally, the map file will contain only public symbols. If desired, some or all source modules can be assembled using the AVMAC with the -AP switch or $ALLPUBLIC directive to make all symbols in the module public. AVOSYM processes three portions of the map file. The first portion shows the start addresses and the lengths of the memory segments. These are labeled "RELOCATED SEGMENTS" and "ABSOLUTE SEGMENTS". AVOSYM generates commands of the form DEF segment_base hexvalue where "segment" is replaced by the name of each segment with a non- zero length, and "hexvalue" is the start address shown in the map for that segment. These symbols are used to define other symbols as described below. The second section of the map contains the names and values of all public symbols. This section is labeled "SYMBOLS -- CLASS 'M'" or "SYMBOLS -- CLASS 'N'". It is present only if the AVLINK -SP switch is used. The third section of the map shows the offset and length of the portion of each segment which is defined by each source file. This section is labeled "MODULE DATA". It is present only if the AVLINK -SM switch is used. AVOSYM defines symbols of the form DEF module_segment segment_base + hexvalue where "module" is replaced by a source file name, "segment" is the name of a segment of that module, and "hexvalue" is the offset shown in the map for that segment. If the AVOSYM -b switch is used, a DEFBASE command is generated instead of DEF. When loading under NoICE, the command file(s) produced by AVOSYM must be PLAYed before those produced by AVOSRC. This is because AVOSYM will define symbols of the form module_segment which specify the base addresses of the segments of each source file. AVOSRC defines its line numbers as relative to these symbols. If these symbols are not defined, an error will result. 13.2. BSOSYM: BSO/Tasking BSO/Tasking (tm) makes a line of cross assemblers which targets most 8 bit microprocessors. All share the same MLINK linker. A linker switch controls the production of a map file, and specifies whether the map file should include only global symbols, or both global and local symbols. In order to include local symbols, the module or modules for which the symbols are desired must be assembled with the appropriate switch to include local symbol information in the object file. The NoICE utility BSOSYM.EXE converts the MLINK map file into a command file which DEFINEs the symbols. The command line is: BSOSYM infile outfile where "infile" represents the map file output by MLINK, and "outfile" represents the output command file. If "outfile" already exists, the old file will be deleted and replaced by the new one. MLINK map files normally have the extension ".MAP". Line number processing for source debug is currently not supported for the BSO assembler. 13.3. DUNSYM: Dave Dunfield Dave Dunfield produces low-cost assemblers (as well as C compilers and other goodies) for a variety of microprocessors. Shareware versions are available on various BBS. Of interest to NoICE users are ASM02 for the 6502, ASM51 for the 8051, ASM05 for the 6805, ASM09 for the 6809, and ASM11 for the 68HC11. The output is not relocatable. The NoICE utility DUNSYM.EXE processes a listing file produced by ASMxx version 1.21 into a command file which contains FILE and LINE commands for source level debug, and DEFINE commands to define the symbols. The command line to assemble and produce a listing file containing a symbol table is: ASMxx sourcefile +f +s The command line to process the listing file is: DUNSYM listfile {cmdfile} where "listfile" represents the listing file output by ASMxx, and "cmdfile" represents the output command file. If "cmdfile" already exists, the old file will be deleted and replaced by the new one. If "cmdfile" is omitted, output is to stdout. Conditional (IF), INCLUDE, and MACRO processing are available using a separate Dunfield program called MACRO. The output of MACRO is assembled, and DUNSYM may be applied to the resultant listing file. Note that the Dunfield version 1.21 assemblers will not accept symbols longer than 9 characters. Longer symbols will cause the assembler to hang, until control-C is pressed. No indication of the problem is given. Thus, these assemblers cannot be used to assemble the NoICE monitors unless the monitor source code is modified to shorten some of the symbols. The Dunfield version 2.4 (1994 copyright) assemblers do not have this restriction. 13.4. METASYM: MetaLink Assembler MetaLink (tm) is a manufacturer of In-circuit Emulators for the 8051. They also offer an 8051 assembler, a version of which (ASM51 version 1.2h) is available as advertising freeware on various BBS as ML-ASM51.ZIP. The output is not relocatable, but it has INCLUDE and MACRO capability, and the price is right. The NoICE utility METASYM.EXE processes a listing file produced by ASM51 version 1.2h into a command file which contains FILE and LINE commands for source level debug, and DEFINE commands to define the symbols. The line numbers printed in Metalinks listing files do not represent the line numbers in the source file if INCLUDE or MACRO is used. Rather, the printed line numbers show aggregate lines as if the INCLUDED file or MACRO expansions were in line. Since we must be able to correlate addresses in the listing file with line numbers in some real file, METASYM must produce a debug file containing this "aggregate source". This is the file on which source debugging occurs. The command line to process the listing file is: METASYM listfile cmdfile debugfile where "listfile" represents the listing file output by ASM51, "cmdfile" represents the output command file, and "debugfile" represents the output debug file. If "cmdfile" or "debugfile" already exist, the old file will be deleted and replaced by the new one. 13.5. MOTSYM: Motorola Freeware Motorola (tm) offers a set of free assemblers for most of their microprocessor line. These are not macro assemblers, and the output is not relocatable, but the price is right. They are available on the Motorola Freeware BBS, and on various other BBS. Of interest to NoICE users are AS5 for the 6805, AS9 for the 6809, and AS11 for the 68HC11. The NoICE utility MOTSYM.EXE processes a listing file produced by ASxx into a command file which contains FILE and LINE commands for source level debug, and DEFINE commands to define the symbols. The command line to assemble and produce a suitable listing file is: ASxx sourcefile -l -s >listfile The command line to process the listing file is: MOTSYM listfile {cmdfile} where "listfile" represents the listing file output by ASxx, and "cmdfile" represents the output command file. If "cmdfile" already exists, the old file will be deleted and replaced by the new one. If "cmdfile" is omitted, output is to stdout The freeware assemblers have neither INCLUDE, MACRO, nor IF. They can, however, assemble multiple source files specified on the command line. In this case, the listing appears as if the files were concatenated before assembly, and the line numbers shown are aggregate line numbers. Thus, this feature should not be used. If it is desired to split the source into pieces, the DOS copy command could be used to concatenate the files before assembly, and MOTSYM applied to the resulting file. 13.6. SAMSYM: PseudoSam PseudoCode corporation offers a set of PseudoSam assemblers for a variety of microprocessor. Shareware and commercial versions are available, with various capabilities. The NoICE utility SAMSYM.EXE processes a listing file produced by PseudoSam Axx into a command file which contains FILE and LINE commands for source level debug, and DEFINE commands to define the symbols. The command line to process the listing file is: SAMSYM listfile {cmdfile} where "listfile" represents the listing file output by Axx, and "cmdfile" represents the output command file. If "cmdfile" already exists, the old file will be deleted and replaced by the new one. If cmdfile is omitted, output is to stdout. 13.7. Z800SYM: Zilog ASM800 Zilog (tm) includes a cross assembler for the Z8, Z80, Z180, and Z800 with various evaluation boards which they sell. Also included are a number of object file processing utilities, including MNM which generates symbol listings. Switches specify the listing format, and whether the symbol file should include only global symbols, or all symbols. The NoICE utility Z800SYM.EXE converts the MNM symbol file into a command file which DEFINEs the symbols. Command lines are: MNM -o symfile file.lnk where "file.lnk" is the MUFOM format output from the linker, and "- o symfile" specifies that the output should be directed to "symfile". The "-l" switch specifies that local symbols should be included. Z800SYM symfile outfile where "symfile" represents the symbol file output by MNM, and "outfile" represents the output command file. If "outfile" already exists, the old file will be deleted and replaced by the new one. Line number processing for source debug is currently not supported for the Zilog assembler. 13.8. SA370NOI: Texas Instruments SA370 Assembler Texas Instruments offers a free assembler for the TMS370 called SA370. The output is not relocatable, but it has INCLUDE capability, and the price is right. A companion simulator is also available. The NoICE utility SA370NOI.EXE processes a listing file produced by SA370 into a command file which contains FILE and LINE commands for source level debug, and DEFINE commands to define the symbols. The line numbers printed in SA370 listing files do not represent the line numbers in the source file if INCLUDE files are used. Rather, the printed line numbers show aggregate lines as if the INCLUDED file were in line. Since we must be able to correlate addresses in the listing file with line numbers in some real file, SA370NOI must produce a debug file containing this "aggregate source". This is the file on which source debugging occurs. The command line to process the listing file is: SA370NOI listfile cmdfile {debugfile} where "listfile" represents the listing file output by SA370, "cmdfile" represents the output command file, and "debugfile" represents the output debug file. If "cmdfile" or "debugfile" already exist, the old file will be deleted and replaced by the new one. If “debugfile” is not specified, then the line numbers will be relative to “listfile”. This saves the creation of a debug file, but may be ugly during debugging, as the list file contains redundant address and instruction data information. 14. PROCESSOR SPECIFIC DATA As of the date of this document, NoICE supports the following processors: 14.1. Zilog Z80, Z85C1X, Z180 Family In addition to the basic Z80 instruction set, the enhanced instructions for the Z85C1X and Z180 family are supported. Because of this, the disassembler may show instructions which are not compatible with a given target. For example, the IN0 instruction of the Z180 does not exist on the Z80 or Z85C1X. While the instruction will be disassembled, operation of single-step is not guaranteed for instructions not supported by a given target. Registers supported are A, FL, AF, B, C, D, E, H, L, BC, DE, HL, IX, IY, SP, PC, I, IFF (interrupt enable flip flop), A', FL', AF', B', C', D', E', H', L', BC', DE', HL', and PG if paged memory is used. Except for RESET and the RST instruction used for breakpoint, the standard monitor routes NMI and RSTnn interrupts through a region of RAM which duplicates low memory. This region is initialized with jumps which enter the monitor and report a processor state which names the interrupt. If user code changes the contents of this region, interrupts may be passed to user-specified routines without entering the monitor. If interrupt mode two (vectored) is used, interrupts will be independent of the monitor. Unique processor states are reported in the register window for 0 RESET (RST 0) 1 BREAKPOINT (RST nn) 2 NMI 3 RST 8 4 RST 10 5 RST 18 6 RST 20 7 RST 28 8 RST 30 9 RST 38 10 TRAP (Z180 only) Other processor state values will be shown numerically. While the single byte instruction RST nn is preferred for use as a breakpoint instruction, a three byte CALL may be used with appropriate modification of the target monitor. The monitor is less than 1024 bytes in length, including I/O initialization, and uses 256 bytes or less of RAM. The monitor has been assembled with the Zilog ASM80 assembler shipped with Zilog evaluation boards. Other assemblers may be used if the appropriate changes are made to pseudo-ops and source file formatting. 14.2. Zilog Z8 Family This processor has three separate address spaces: register, code, and external. The target uses the LDC or LDE instructions to read and write code or external memory. Thus, the target must support either the instructions "LDC R,@RR" and "LDC @RR,R", or the LDE equivalents, and the hardware must be designed appropriately. The Zilog Z86C95 evaluation board is so constructed. For simplicity at the PC host, addresses are specified by the user as if there were a single 16 bit address space: Addresses below 0100 hex are regarded as specifying registers. Addresses between 0100 and 04FF hex are regarded as specifying Expanded Register File registers, with the ERF file set selected by address bits 9-8, (ERF sets 0 through 3), the register bank selected by bits 7-4, and the register by bits 3-0. Addresses 500 hex and above access code memory. The low 500 hex bytes of code memory are not accessible via the serial link. This is not regarded as a problem, as this region will typically be where the target monitor resides. If support for external memory as distinct from code memory is desired, it may be implemented by using memory pages. For example, the paged region could be specified as 0000 to 0ffff hex; with page 0 being register memory, page 1 code memory, and page 2 external memory. Suitable modifications of the target monitor would be required, but no changes are required to NOICEZ8.EXE Registers supported are R0 through R15, FL, SP (16 bits), PC, RP, IMR, and PG if paged memory is used. Other locations in register RAM may be examined using NoICE memory or input/output commands. The master interrupt control bit of the actual IMR is cleared upon entry to the monitor, and restored from the IMR register when a user program is executed. In order to preserve proper monitor operation, the actual IMR at address 0fb hex should not be changed using NoICE memory or input/output commands. All such changes should be made to the IMR register. Similarly, the actual RP at address 0fd hex, FL at address 0fc hex, and SP at addresses 0fe and 0ff hex should not be changed using NoICE memory or input/output commands. All such changes should be made to the respective registers, which will be restored to the actual memory locations when the user program is executed.. The target monitor uses a set of 16 registers, which may not be used by the application code. By appropriate modification of the monitor source code, the user may select which set of registers is used. The Z8 unfortunately has no single-byte op-code suitable for use as a breakpoint instruction. Thus, NoICE uses a two byte "CALL @reg" (hex 0D4h) instruction. This has two effects. First, if the application code modifies the register pair containing the call address (R0 and R1 of the monitor's register set), then breakpoint or single-step is likely to jump somewhere more exciting than the monitor's breakpoint entry. Secondly, breakpoints cannot be placed on successive bytes, as the inserted breakpoint instructions would overlap. NoICE will prevent the insertion of a breakpoint which would overlap another. The monitor has been assembled with the Zilog ASM8 assembler shipped with Zilog evaluation boards. Other assemblers may be used if the appropriate changes are made to pseudo-ops and source file formatting. 14.3. Motorola 68HC11 Family Registers supported are A, B, D, X, Y, SP, PC, CC, and PG if paged memory is used. In the standard monitor, interrupts for RESET, CLOCK FAIL, COP, ILLEGAL OP-CODE, SWI and XIRQ enter the monitor and report a processor state which names the interrupt. All other interrupts are routed through RAM vectors. These RAM vectors are initialized to enter the monitor and report a processor state which names the interrupt. If user code changes the contents of a RAM vector, that interrupt will be passed to the user-specified routine without entering the monitor. Unique processor states are reported in the register window for 0 RESET 1 BREAKPOINT (SWI) 2 XIRQ 3 Clock Monitor 4 COP Fail 5 Illegal Op-code 6 IRQ 7 Real Time Clock 8 Timer Capture 1 9 Timer Capture 2 10 Timer Capture 3 11 Timer Compare 1 12 Timer Compare 2 13 Timer Compare 3 14 Timer Compare 4 15 Timer Compare 5 16 Timer Overflow 17 Pulse Accumulator Overflow 18 Pulse Accumulator Edge 19 SPI 20 SCI Other processor state values will be shown numerically. While the single byte instruction SWI is preferred for use as a breakpoint instruction, JSR may be used with appropriate modification of the target monitor. The monitor is approximately 1300 bytes in length, and uses 256 bytes or less of RAM. The monitor has been assembled with the AS11 assembler available from Motorola's Freeware BBS. Other assemblers may be used if the appropriate changes are made to pseudo-ops and source file formatting. 14.4. Motorola 6809 Registers supported are A, B, D, X, Y, U, SP, PC, CC, and PG if paged memory is used. Except for RESET and SWI, interrupts in the standard monitor are routed through RAM vectors. These vectors are initialized to enter the monitor and report a processor state which names the interrupt. If user code changes the contents of a RAM vector, that interrupt will be passed to the user-specified routine without entering the monitor. Unique processor states are reported in the register window for 0 RESET 1 BREAKPOINT (SWI) 2 NMI 3 IRQ 4 FIRQ 5 SWI2 6 SWI3 Other processor state values will be shown numerically. While SWI is preferred for use as a breakpoint instruction, SWI2 or SWI3 may be used with appropriate modification of the target monitor. The initial handler for FIRQ will push all processor registers if they are not pushed by the interrupt. The "E" bit of the stacked processor status register is set so that RTI will act appropriately. The 6809 contains a wide variety of instructions which can affect the program counter. The single-step function supports many, but not all, of these. Unsupported are TFR rr,PC EXG rr,PC EXG PC,rr If the user attempts to step these instructions, a breakpoint will be inserted after the instruction, but not at the location specified by register "rr". The following instructions ARE supported for single-step PULS PC,... PULU PC,... JMP all address modes JSR all address modes The monitor is less than 1024 bytes in length. The monitor has been assembled with the AS9 assembler available from Motorola's Freeware BBS. Other assemblers may be used if the appropriate changes are made to pseudo-ops and source file formatting. 14.5. Motorola 6805, 68HC05 Family Registers supported are A, X, SP, PC, CC, and PG if paged memory is used. Except for RESET and SWI, interrupts in the standard monitor are routed through RAM vectors. These vectors are initialized to enter the monitor and report a processor state which names the interrupt. If user code changes the contents of a RAM vector, that interrupt will be passed to the user-specified routine without entering the monitor. Unique processor states are reported in the register window for 0 RESET 1 BREAKPOINT (BRK) 2 IRQ 3 Timer 4 SCI 5 SPI 6 Reserved 7 COP Other processor state values will be shown numerically. Not all of these interrupt sources may exist on some processors. The monitor is less than 1024 bytes in length. The monitor uses 256 bytes or less of RAM, but requires no page 0 RAM. The monitor has been assembled with the AS5 assembler available from Motorola's Freeware BBS. Other assemblers may be used if the appropriate changes are made to pseudo-ops and source file formatting. 14.6. Rockwell 6502, 65C02 Family Registers supported are A, X, Y, SP, PC, CC, and PG if paged memory is used. Except for RESET and BRK, interrupts in the standard monitor are routed through RAM vectors. These vectors are initialized to enter the monitor and report a processor state which names the interrupt. If user code changes the contents of a RAM vector, that interrupt will be passed to the user-specified routine without entering the monitor. Unique processor states are reported in the register window for 0 RESET 1 BREAKPOINT (BRK) 2 NMI 3 IRQ Other processor state values will be shown numerically. The monitor is less than 1024 bytes in length. The monitor uses 256 bytes or less of RAM, but requires no page 0 RAM. The monitor has been assembled with the Avocet AVMAC (tm) assembler. Other assemblers may be used if the appropriate changes are made to pseudo-ops and source file formatting. 14.7. Mitsubishi M50740 and M38000 Family The Mitsubishi M50740 and M38000 family processors are similar, but not identical, to the 65x02 family. In particular, several of the bit set, clear, and branch instructions have different op-code values between the Mitsubishi and 6502 families. Registers supported are A, X, Y, SP, PC, CC, and PG if paged memory is used. Except for RESET and BRK, interrupts in the standard monitor are routed through RAM vectors. The vectors are initialized to enter the monitor and report a processor state which names the interrupt. If user code changes the contents of a RAM vector, that interrupt will be passed to the user-specified routine without entering the monitor. Unique processor states are reported in the register window for 0 RESET 1 BREAKPOINT (BRK) 2 Timer X 3 Horiz/Vertical (734) 4 Timer 1,2,3 (734) 5 INT1 6 INT2 7 Serial (740) 8 Timer 1 9 INT0 (38000) 10 Serial Rx (38000) 11 Serial Tx (38000) 12 Timer Y (38000) 13 Timer 2 (38000) 14 Counter 0 (38000) 15 Counter 1 (38000) 16 INT3 (38000) 17 INT4 (38000) 18 INT5 (38000) Other processor state values will be shown numerically. Note that not all of these interrupts exist on any one processor. The monitor is less than 1024 bytes in length, including I/O initialization. The monitor uses 256 bytes or less of RAM, but requires no page 0 RAM. The monitor has been assembled with the Avocet AVMAC (tm) assembler. Other assemblers may be used if the appropriate changes are made to pseudo-ops and source file formatting. 14.8. Intel 8051 This processor has several distinct address spaces: on-chip RAM, SFR, on-chip program, off-chip program, and off-chip data. As the 8051 does not have an instruction to write to code memory, the target monitor uses the MOVX instructions to read and write off- chip code or data memory. In order for MOVX to access program memory, PSEN and RD must be combined via external hardware. This may be done to yield a single 64K address space including both program and data memory, or distinct memory banks may be maintained. For simplicity, the supplied target monitor assumes that program and data memory are combined, and maps a single 16 bit address as follows: Addresses below 0100 hex are regarded as specifying oh- chip RAM. Note that the 8051 distinguishes between direct and indirect addressing for RAM locations 80 to 0FF hex: direct addressing accesses Special Function Registers (SFR's), while indirect addressing accesses RAM. The supplied target monitor will access on-chip RAM if memory addresses in the range 80 to 0FF hex are specified. in order to access SFR's, the IN and OUT commands must be used. Addresses 100 hex and above access external program/data memory. The low 100 hex bytes of program/data memory are not accessible via the serial link. This is not regarded as a problem, as this region will typically be where the target monitor resides. If support for external data memory as distinct from program memory is desired, it may be implemented by using memory pages. For example, the paged region could be specified as 0000 to 0ffff hex; with page 0 being register memory, page 1 program memory, and page 2 external data memory. Suitable modifications of the target monitor would be required, but no changes are required to NOICE51. Registers supported are R0 through R7, A, B, PSW, DPTR, SP, PC, and PG if paged memory is used. In addition, register "RB" denotes the register bank bits of the PSW, and register "IE" the interrupt enable SFR. The master interrupt control bit of the actual IE SFR is cleared upon entry to the monitor, and restored from the IE register when a user program is executed. In order to preserve proper monitor operation, the actual IE SFR should not be changed using NoICE memory or input/output commands. All such changes should be made to the IE register. Except for RESET, the standard monitor routes interrupts through a region of RAM which duplicates low memory. This region is initialized with jumps which enter the monitor and report a processor state which names the interrupt. If user code changes the contents of this region, interrupts may be passed to user- specified routines without entering the monitor. Unique processor states are reported in the register window for 0 RESET 1 BREAKPOINT 2 IE0 3 TF0 4 IE1 5 TF1 6 RI & TI 7 TF2 & EXF2 Other processor state values will be shown numerically. Note that not all of these interrupts exist on some members of the processor family. The 8051 unfortunately has no single-byte op-code suitable for use as a breakpoint instruction. Thus, NoICE uses a three byte "LCALL" (hex 012) instruction. This has the effect that breakpoints cannot be placed more closely than three bytes apart, as the inserted breakpoint instructions would overlap. NoICE will prevent the insertion of a breakpoint which would overlap another. Since single-step is implemented using breakpoints, there may be instructions, such as short forward or backward branches, which cannot be stepped due to overlapped breakpoints. The monitor is less than 1024 bytes in length, including I/O initialization. The monitor uses 256 bytes or less of RAM, but requires no on-chip RAM other than the current register bank, the original contents of which are saved while in the monitor. The monitor has been assembled with the PseudoSam ASM51 assembler. Other assemblers may be used if the appropriate changes are made to pseudo-ops and source file formatting. 14.9. Intel 80196 NoICE96 supports both the 8096 and the 80196 instruction sets. The monitor contains no 80196-specific instructions, and only a few 80196-specific Special Function Register references. It should be easy to modify it for use on an 8096. However, no testing has been performed on an 8096. The 80196 contains 256 bytes of directly addressable "Register File". This contains both Special Function Registers and general purpose RAM. Of these, the NoICE register window displays PC, SP, PSW, and PG if paged memory is used. Other locations in the Register File may be displayed in the register or data window using the WATCH command. The standard monitor supports horizontal windowing, but does not support vertical windowing. Support for vertical windowing may be added to the monitor by the user, if desired. However, since direct and indirect addressing will access different physical locations when vertical windowing is in use, the user must decide which form of address is to be used when the target "read memory" and "write memory" commands are used. In addition, use of direct addressing would require the use of self-modifying code. Except for RESET, the standard monitor routes interrupts through a region of RAM which duplicates the layout of memory at address 2000h. This region is initialized with vectors to default handlers which enter the monitor and report a processor state which names the interrupt. If user code changes the contents of this region, interrupts may be passed to user-specified routines without entering the monitor. Unique processor states are reported in the register window for 0 RESET 1 BREAKPOINT 2 Timer Overflow 3 A/D Complete 4 HSI Data Available 5 High Speed Output 6 HSI.O 7 Software Timers 8 Serial Port 9 EXTINT 10 Trap (if not used for breakpoint) 11 Unimplemented Op-code 12 TI 13 RI 14 4th entry in HSI FIFO 15 Timer2 Capture 16 Timer2 Overflow 17 EXTINT1 18 HSI FIFO Full 19 NMI Other processor state values will be shown numerically. Note that not all of these interrupts exist on all members of the processor family. The TRAP op-code (hex 0F7) is used as a breakpoint instruction. The monitor is less than 1200 bytes in length, including I/O initialization. The monitor uses 256 bytes or less of RAM, but requires no on-chip RAM other than scratch registers, the original contents of which are saved while in the monitor. The monitor has been assembled with the PseudoSam ASM96 assembler. Other assemblers may be used if the appropriate changes are made to pseudo-ops and source file formatting. Thanks to Gene Pfister for the use of his 80196 target board, and for pointing out a number of errors in the original version of the 80196 monitor. 14.10. Texas Instruments TMS370 The TMS370 contains either 128 or 256 bytes of directly addressable Register File. Of these, the NoICE register window displays A, B, PC, SP, ST (status), and PG if paged memory is used. Other locations in the Register File may be displayed in the register or data window using the WATCH command. Except for RESET, and one TRAP instruction used for breakpoint, the standard monitor routes interrupts through a region of RAM which duplicates the layout of memory at address 7Fxxh. This region is initialized with vectors to default handlers which enter the monitor and report a processor state which names the interrupt. If user code changes the contents of this region, interrupts may be passed to user-specified routines without entering the monitor. Unique processor states are reported in the register window for 0 RESET 1 BREAKPOINT 2 Poweron Reset 3 OSC Fail Reset 4 Watchdog Reset 5 Trap 15 6 Trap 14 7 Trap 13 8 Trap 12 9 Trap 11 10 Trap 10 11 Trap 9 12 Trap 8 13 Trap 7 14 Trap 6 15 Trap 5 16 Trap 4 17 Trap 3 18 Trap 2 19 Trap 1 20 Trap 0 21 Reserved 1 22 Reserved 2 23 Reserved 3 24 Reserved 4 25 Reserved 5 26 Reserved 6 27 ADC 28 Timer 2 29 Serial Tx 30 Serial Rx 31 Timer 1 32 SPI 33 Int 3 34 Int 2 35 Int 1 36 PACT SCI Tx 37 PACT SCI Rx 38 PACT Cmd/Def0 39 PACT Cmd/Def1 40 PACT Cmd/Def2 41 PACT Cmd/Def3 42 PACT Cmd/Def4 43 PACT Cmd/Def5 44 PACT Cmd/Def6 45 PACT Cmd/Def7 46 PACT Buffer 47 PACT CP6 48 PACT CP5 49 PACT CP4 50 PACT CP3 51 PACT CP2 52 PACT CP1 53 PACT Timer Overflow Other processor state values will be shown numerically. Note that not all of these interrupts exist on all members of the processor family. In particular, the PACT is not present in most family members, and support for it can be omitted from the monitor. One TRAP op-code (initially TRAP15, or hex 0E0) is used as a breakpoint instruction. This may be replaced by any other TRAP instuction, or by the CALL instruction by appropriate changes to the monitor. The monitor is less than 1300 bytes in length, including I/O initialization. The monitor uses 256 bytes or less of RAM, but requires no on-chip RAM other than scratch registers, the original contents of which are saved off-chip while in the monitor. The monitor has been assembled with the SA370 assembler. Other assemblers may be used if the appropriate changes are made to pseudo-ops and source file formatting. A compromise was made regarding the relative jump and call instructions. In SA370, the instruction JMPL 123 will add 123 to the program counter following the jump instruction, while the instruction JMPL LABEL will perform a relative jump to LABEL. That is, in the former case, the value of the expression becomes the offset portion of the instruction, while in the latter case the offset is computed by subtracting the location of the following instruction from the destination address. This presents a difficulty to a disassembler, as there is no way to determine the format of the original source code. Since the format with LABEL is much more common than the format with a constant (at least I hope it is!) NoICE370 will show the absolute destination address when disassembling JUMPL and CALLR instructions. Thanks to Brian Mohlman for providing databooks, an assembler, and for building and lending a TMS370 target board. 14.11. Other Processors Additional processors may be supported in the future, as time and interest allow. Some likely candidates are listed below. If you are interested in one of these, or wish to suggest another target, please contact the author at the address listed in the final section of this document. The Hitachi H8 family looks straightforward, but I don't have a cross assembler or any target hardware on which to check out a monitor. The Microchip PIC would be fun, but the architecture of the PIC pretty much precludes the use of a monitor-based debugger: there is no version of the chip with external code memory, most members of the family have only a two level stack, and there is no way to push or pull data from the stack except for call and return. 15. HOW IT WORKS NoICE relies on a target monitor which implements a small set of commands; and a PC-resident host program which does most of the work. Commands are provided to read target configuration, to read and write blocks of memory, to read and write processor registers, to input from and output to I/O ports, to set and clear breakpoints, and to execute. Everything else is done by the PC. The commands are identical in format for all target processors. Only the format of the register block is unique to the specific target processor. 15.1. Breakpoints, Execution, and Single-Step One of the unique features of NoICE is that it is able to implement single-step operation without the use of special hardware. This is accomplished by the insertion of breakpoint instructions at the location(s) to be executed after the instruction to be stepped. For most instructions, the next instruction to be executed is the next one in sequential memory. Since the disassembler knows how long each instruction is, the address of the next sequential instruction may be obtained simply by calling the disassembler's instruction processing function for the instruction to be stepped. A breakpoint is inserted at the next sequential address, and the target told to execute until the breakpoint is hit, at which time the breakpoint is removed. Certain instructions, such as branches, jumps, subroutine calls, and returns may cause the flow of execution to be changed. Code is added to the instruction processing functions of such instructions to derive the alternate execution address. In the case of subroutine returns and computed jumps, this may necessitate reading target registers or memory. Breakpoints are inserted at both the alternate execution address and the next sequential address, and the target told to execute until a breakpoint is hit, at which time both breakpoints are removed. We had originally planned to determine the single next instruction address, but this caused several difficulties: the first is the larger number of instruction processing functions which would need to be written, to account for different conditional branches and the like. A more serious problem exists for targets such as the 8051 family which can branch based on the states of bits in I/O devices: For such instructions, there is no guarantee that the same value will be seen by the monitor reading ahead, and by the target at execution time. For these reasons, we insert two breakpoint instructions for all transfer of control instructions. 16. TARGET COMMUNICATIONS NoICE can use any of COM1, COM2, COM3, or COM4 serial ports at any baud rate from 300 to 57600. Non-standard baud rates (that is, rates which are not power of two multiples of 300) may be specified, as the baud rate divisor is calculated from the entered baud rate as 115200/baud. Any value of "baud" which results in an integer divisor may be used. Any PC asynchronous card using an 8250, 16450, or 16550 UART may be used. Most common will be RS-232, but RS-422 or RS-485 is also possible as long as the card looks to the processor like a standard COM card. NoICE turns RTS on before sending a message, and turns RTS off at all other times. This is intended to allow the use of half duplex communications devices, such as short-haul modems, or single wire-pair RS-485. PC-compatible RS-485 cards and RS-232 to RS-485 converters are available from Black Box, JDR, B and B, and various other vendors. RTS will remain off during target execution. As described in section 8.2, operator keyhits will be output to the UART by NoICE during target execution. However, since RTS will remain off, these characters will not be seen by the target if a half-duplex communications device or medium is being used. The message format is Byte 0 Function code, whose value must be greater than 80 hex or the target will ignore it. This aids in re-synchronization if target and host lose sync. Byte 1 Length of data to follow, 0 to 255. Some target implementations may restrict the length to a smaller value. All targets must allow a data length of at least 19. Byte 2 to n Data (if Byte 1 is non-zero). Interpretation of the data is determined by the function code in Byte 0. See below. Byte n+1 Two's complement of the eight bit sum of Bytes 0 through n, such that the sum of Bytes 0 through n+1 is zero for a correctly received message. Messages received with an incorrect checksum are ignored. The communications protocol is half duplex, with the PC acting as master. Messages receive an immediate reply, except for FN_RUN_TARGET, the reply to which will be generated if and when the target executes a breakpoint, an unhandled interrupt, or is reset. 16.1. FN_GET_STATUS (0FFH) get device info This function allows the host to identify the target's processor type, and to obtain other useful information about the target. The request contains no data bytes. The reply data is as follows: Byte 2 Processor type Byte 3 Size of target comm buffer (19 to 255) Byte 4 Options. Currently zero. Bytes 5,6 Low bound of target mapped memory (0 if not mapped). Least significant byte first. Bytes 7,8 High bound of target mapped memory (0 if not mapped) Least significant byte first. Byte 9 Length of target's breakpoint instruction. Bytes 10 to n Target's breakpoint instruction (number of bytes specified by the value of Byte 9) Bytes n+1 to m Zero-terminated ASCII string: target description 16.2. FN_READ_MEM (0FEH) read memory This function allows the host to read bytes from the target's memory. The request data is always 4 bytes long, and appears as follows: Byte 2 Memory page (or zero if paged memory is not supported) Bytes 3,4 Memory address, least significant byte first Byte 5 Number of bytes to return The reply data is as follows: Bytes 2 to n Requested data bytes 16.3. FN_WRITE_MEM (0FDH) write memory This function allows the host to write bytes to the target's memory. The request data is always at least 3 bytes long, and appears as follows: Byte 2 Memory page (or zero if paged memory is not supported) Bytes 3,4 Memory address, least significant byte first Bytes 5 to nn Data to write. The length of the data to write may be computed from the net data length in Byte 1 as write length = Byte 1 - 3 The reply data is as follows: Byte 2 Status value for write: 0=success, 1=failed verify after write 16.4. FN_READ_REGS (0FCH) read registers This function allows the host to read the target processor's registers. The request contains no data bytes. The reply data is as follows: Byte 2 to nn Register image. The byte order must match the target register definition in the host's target support module. Any multi-byte values must be provided least significant byte first. 16.5. FN_WRITE_REGS (0FBH) write registers This function allows the host to write the target processor's registers. The request data is as follows: Byte 2 to nn Register image. Two possible reply formats exist: Byte 2 Status value for write: 0=success, 1=failed write Byte 2 to nn Register image. The second format is used by processors such as the 8051 which have multiple register banks. Since the register bank specifier is considered to be one of the processor registers, this format allows the processor to return a new register set when the bank register is changed. 16.6. FN_RUN_TARGET (0FAH) run target This function tells the target to begin execution at the address specified in its local register structure. If the host wishes to specify an execution address, it must do so by writing to the target's registers before issuing the execute command. The request contains no data bytes. The reply data is as follows (returned when and if the target executes a breakpoint or is reset): Byte 2 to nn Register image. 16.7. FN_SET_BYTES (0F9H) breakpoint This function allows the host to write to target memory, and to obtain the contents before the write. It is used to insert and remove breakpoint instructions. The length of the request is four times the number of bytes to be set. Request data is as follows: Byte 2 Page for first byte (0 if paged memory not supported) Bytes 3,4 Address for first byte (least significant byte first) Byte 5 Data to store at first byte ... Byte 4n-2 Page for n'th byte (0 if paged memory not supported) Bytes 4n-1, 4n Address for n'th byte (least significant byte first) Byte 4n+1 Data to store at n'th byte The reply data is as follows: Byte 2 Data from first byte before store ... Byte n+2 Data from n'th byte before store If the target is unable to successfully write a byte (for example, if an attempt is made to write a breakpoint into ROM), no further insertions will made in response to the command, and the returned data will include only the number of bytes actually inserted. Thus, the return length may be used to verify complete insertion of all bytes, or to tell where a failure has occurred. 16.8. FN_IN (0F8H) input from port This function allows the host to read a target input port. If the target processor does not support separate memory and input/output spaces, then this command reads a byte from target memory. The request data is as follows: Bytes 2,3 Port address, least significant byte first The reply data is as follows: Byte 2 Data byte from port 16.9. FN_OUT (0F7H) output to port This function allows the host to write to a target output port. If the target processor does not support separate memory and input/output spaces, then this command writes a byte to target memory. Note that unlike FN_WRITE_MEM, no verification is done, since re-reading an I/O device may cause undesired operation. For this reason, this function is useful even for processors without separate input/output address spaces. The request data is as follows: Bytes 2,3 Port address, least significant byte first Byte 4 Data byte to write The reply data is as follows: Byte 2 Status value: 0 16.10. FN_ERROR (0F0H) error reply This function is never sent by the host to the target. It may be returned by the target in response to a message with a valid checksum, but whose function code is unknown to the target. The reply contains no data bytes. 17. CUSTOMIZING A TARGET MONITOR The task of supporting a new target hardware platform is relatively easy. The starting point is the existing basic target monitor for your processor. The target monitors are written such that hardware-dependent code is isolated to a few locations in the source file. The areas to be examined and changed as required are these: 1) Target monitor ROM location, ROM_START. This will depend on where the processor begins execution, on the memory technology being used, and possibly on requirements for other ROM-resident code. If a ROM/RAM/UART board is installed, the monitor will most likely reside in that ROM. 2) Target monitor RAM location, RAM_START. The monitors require approximately 100 bytes of RAM; less if the stack sizes can be reduced, or if a smaller communications buffer is acceptable. The communications buffer size, COMBUF_SIZE, must be at least 19 bytes, although download performance will be improved if a larger value is used (typically, 35 to 100 bytes). Monitor RAM should be located such that it does not inconvenience the project being developed. If a ROM/RAM/UART board is installed, it may be convenient to use the top or bottom of the RAM on that board. 3) Target hardware initialization. This is the most involved portion of porting the monitor. If the target processor is a single-chip micro with onboard peripherals, the prototype target monitor will probably contain most of the initialization code already. In any case, the initialization code developed here will likely be reused in the startup code for the final application. 4) Target UART. The UART to be used for target communications must be initialized, and the basic transmit and receive routines written. If a ROM/RAM/UART board is installed, that board's UART will most likely be used. Code for such a UART, as well as for any UART on the microprocessor chip itself, may exist in the prototype target monitor. 5) Breakpoint Instruction. If the target processor has a single- byte software interrupt instruction, it is convenient to use it as the breakpoint instruction, as a single byte breakpoint may be placed at any desired RAM location. However, if the target has no such instruction, or if the instruction is being used by the application code, or if the monitor does not have access to the interrupt vector for the instruction (as may occur during testing of the target monitor using another debug monitor), then a multi- byte breakpoint instruction may be used. Typically, the multi-byte breakpoint instruction will be a call to a monitor subroutine, which will push processor registers so as to simulate an interrupt. In most cases, the prototype target monitor will have appropriate code for the breakpoint instruction. 17.1. Testing a Customized Target Test the modified target monitor by connecting its serial port to that of a PC. Turn on the target, and then run NoICE. Use the SHOW=1 command line option of NoICE, or the SHOW 1 command, to display the hex values of communications to and from the target. When NoICE starts up, it first attempts to read the target version and status information (see FN_GET_STATUS in section 16). If this is successful, NoICE then attempts to read the target registers (see FN_READ_REGS in section 16). If this is successful, NoICE then attempts to read memory locations to refresh the source window (see FN_READ_MEM in section 16). Three tries are made for each function. If any function fails to respond after three attempts, the operator is informed. The hex values (if any) displayed by SHOW=1 can assist you in debugging your target monitor. The most common problems are bad cables and mismatched baud rates (unless, of course, you happen to make a programming error...). Most of the communications functions can be exercised individually via keyboard commands: VERSION will exercise FN_GET_STATUS, and display any results, including the target's identification string. REG followed by carriage return will exercise FN_READ_REGS. Any returned values will be displayed in the register window. A common error is to forget to return 16 bit registers least significant byte first. Check the displayed registers to see if this is the case. REG followed by a register name and a value will exercise FN_WRITE_REGS. In order to verify that the register was accepted by the target, follow this command by R to read back the registers from the target. EDIT followed by an address will exercise FN_READ_MEM to read one byte at the specified address. It is often useful to read the first byte of the target monitor, or some other location with known contents. DUMP or UNASM will use FN_READ_MEM to read multiple bytes. EDIT followed by an address and a value or values will exercise FN_WRITE_MEM to write the specified values to the specified address. Since FN_WRITE_MEM verifies the write, you should attempt to write both RAM and PROM in order to insure that the monitor verifies correctly. IN followed by an address will exercise FN_IN to input a byte from the specified address. This should be tested even if your target does not have specific I/O instructions. OUT followed by an address and a value will exercise FN_OUT to output a byte to the specified address. This should be tested even if your target does not have specific I/O instructions. BREAK followed by an address will exercise FN_SET_BYTE twice, to temporarily insert and remove a breakpoint. In order to test the ability to set multiple bytes with a single FN_SET_BYTE, you must set several breakpoints, and then issue a GO command to insert them all. GO will exercise FN_RUN_TARGET. If an address is specified, it will be sent to the target via FN_WRITE_REGS before FN_RUN_TARGET is issued. If breakpoints have been set, they will be sent to the target via FN_SET_BYTES before FN_RUN_TARGET is issued. A reply to FN_RUN_TARGET will only occur if the target returns to the monitor after beginning execution. This may be arranged either by inserting a breakpoint, or by assembling a breakpoint instruction (typically a software interrupt) into the code to be executed on the target. 18. TWO BIT MEMORY MANAGEMENT Eight bit processors can do a remarkable amount of work, but sometimes a 16 bit address space just isn't enough. We have had considerable success with a simple scheme which bank switches a portion of system ROM. RAM is generally not banked, although there is no reason why this technique would not work for RAM as well, or instead of, ROM. Consider a Z80 processor with 32K of RAM between 8000h and 0FFFFh (A15=1); and 32K of ROM address space from between 0000h and 7FFFh (A15=0). Let the 16K of ROM between 0000h and 3FFFh be always mapped. It contains the restart and interrupt vectors, the interrupt handlers, shared subroutines, and other "root" code. Let the 16K of ROM address space between 4000h and 7FFFh be mapped to one of eight pages, with the page number selected by a three bit latch somewhere in the processor's I/O space. Rules of use are the classic rules for overlays: The root can call subroutines in the root, or it can map to and call subroutines in the overlays. An overlay can call subroutines within itself, or in the root, but cannot call subroutines in other overlays. (If necessary, more complex software can be written to save overlay information on the stack and allow inter-overlay calls, but this is seldom necessary.) The hardware is pitifully simple: in addition to the 3 bit page latch, it requires 4 two input gates and a 128 Kbyte ROM. /RD ----------------------------- ROM /OE +--------+ A15 -------------| | | OR |------ ROM /CS /MREQ -----------| | +--------+ +--------+ A14 -------------| | | AND |------ ROM A16 latched PG2------| | +--------+ +--------+ A14 ----------| | | AND |------ ROM A15 latched PG1------| | +--------+ +--------+ A14 ----------| | | AND |------ ROM A14 latched PG0------| | +--------+ A13 ----------------------------- ROM A13 ... A0 ----------------------------- ROM A0 Figure 17-1 Two Bit MMU For the Z80 As shown in Figure 17-1, when processor A15=1 or /MREQ=1 (/MREQ is the Z80's low true memory request), the ROM is deselected. When A15=0 and /MREQ=0, the ROM is selected, and one of eight 16K pages is accessed, depending on the values on ROM A16, ROM A15, and ROM A14. When processor A14=0, the outputs of the AND gates will be zero regardless of the value in the page latch (PG2, PG1, PG0). Thus, the root page is selected. When processor A15=0, /MREQ=0, and A14=1, the contents of the page latch is applied to ROM A16, ROM A15, and ROM A14, selecting one of eight pages. As page 000 is the root, there are effectively seven useful overlay pages. +--------+ R/W -------------| | | NAND |------ ROM /OE E ---------------| | +--------+ +--------+ | | A15 -------------| INVERT |------ ROM /CS | | +--------+ +--------+ A14 -------------| | | OR |------ ROM A16 latched PG2------| | +--------+ +--------+ A14 ----------| | | OR |------ ROM A15 latched PG1------| | +--------+ +--------+ A14 ----------| | | OR |------ ROM A14 latched PG0------| | +--------+ A13 ----------------------------- ROM A13 ... A0 ----------------------------- ROM A0 Figure 17-2 Two Bit MMU For the 68HC11 Figure 17-2 shows the circuit for ROM-at-the-top processors such as the 68HC11. Obviously, more or fewer latched page bits may be used with either processor to select more or fewer pages. 19. CHANGE HISTORY The first public release of NoICE was version 1.5. This section describes new features and changes in various public releases since that time. Minor revision levels not listed here may have been issued to correct minor bugs. 19.1. Changes In Version 1.5.2 * Added the SHOW command * Fixed various bugs in the 68HC11 and 8051 monitors 19.2. Changes In Version 1.5.4 * Be sure breakpoint doesn't overlap instruction being stepped * Fix elapsed time overflow during RUN command * Add cursor control to symbol dump command 19.3. Changes In Version 1.6.2 * Add WATCH command, to display memory data in the register or data window * Add persistent breakpoint numbers to breakpoints, to simplify deleting breakpoints. * Numeric values may be entered in decimal by following the number with a period: "10." is ten. * "DEF -name" will delete symbol "name" * PLAY file.ext command is an alias for @files.ext 19.4. Changes In Version 2.0 * Change the file viewer to remain open while other commands are executed. This makes it easier to move around in the view file while stepping the target. New or revised commands to support this are VIEW, NOVIEW, HEX, ASCII, and FIND. This also affects the usage of the cursor keys at the command prompt. * Add source-level debug for assembly language programs using a number of popular assemblers. Commands are MODE, SOURCE, FILE and LINE. * Revise the symbol processing utilities to extract line number as well as symbol information from listing and map files. * Move the register window to the top two lines of the screen. This allows the disassembly/source window to use the full screen width, so that comments are visible. 19.5. Changes In Version 2.2 * Add mouse support and a menu system. This adds a menu bar at the top of the screen, plus various pull-down menus and dialog boxes. * Place "SHOW" data in a pop-up window. This prevents communications debug data from overwriting the normal screen display. * Replace the old DOS command with one which loads COMMAND.COM. This allows the user to issue multiple commands. * Deleted the DIR command, as the file dialog boxes provide more elegant directories for most purposes. * Added NOICE.CFG, a configuration file in which startup commands and parameters may be stored. * Added commands to change screen colors and number of lines, either from within NOICE.CFG or at the command prompt. 19.6. Changes In Version 2.3 * Add TRACE and VIEWTRACE commands * Add AUTOGENERATE command to automatically generate symbols during disassembly. * Add CAPTURE command to capture disassembly and target output to file. * Correct a bug involving use of the TAB key in dialog boxes containing list boxes. * Correct an error which caused the 68HC11 to always step into (rather than over) certain JSR and BSR instructions. * Standardize on the use of Control-Break (rather than ESC, F10, etc. in different places) to abort GO, PLAY, DUMP, LOAD, and other lengthy commands. 19.7. Changes In Version 2.4 * Correct error in 8051 version when stepping "over" CJNE instruction * Correct error in 68HC11 monitor: incorrect RAM interrupt vector usage (monitor version 1.3) * Allow use of Control-Break to abort extended disassemblies, and correct other Control-Break usage. * Add insertion and removal of breakpoints via mouse. * Add support for the 16550 UART (FIFOs) 19.8. Changes In Version 2.5 * Add support for the Texas Instruments TMS370 * Add scroll bars to file viewer * Add switches to RECORD command (and Record dialog box) to record Breakpoints, Watches, and Symbols 20. ORDERING INFORMATION If you find a bug, or would like to suggest an enhancement, please contact me at the address below, or via e-mail at 102203.1513@compuserve.com If you use NoICE, but have not yet registered this copy, please do so now. The distribution package includes * Registered version of NoICExxx PC-host program and on-line help * Printed User's Guide * Target assembly language source code for MONxxx target monitor * Executables and C source code for the symbol processing utilities described in section 13 above. If you use CompuServe, the easiest way to register NoICE is on-line. It is fast, and solves the currency problem for international customers. GO SWREG, and select "register shareware". Do a keyword search for "NoICE" to find the processor you want. Follow the ordering instructions. Otherwise, you may register by mail using the form below. The cost is $25 (US) for the first processor, and $5 (US) for each additional processor ordered at the same time. Please add $5 (US) for shipping outside of North America. Send your check or money order to: John Hartman 1030 14th Avenue Southeast Minneapolis, MN 55414 USA If you are ordering from outside the United States, you may find that Postal Money orders are the easiest way to send US dollars. Due to the limitations of CompuServe's on-line registration, I cannot offer the second-processor-for-five-bucks deal via CompuServe. However, if you order two processors via CompuServe, I will send you the entire set. Software will be shipped on a 720K 3.5 inch floppy unless your order specifies 1.2M 5.25 inch floppy. NOICE ORDER FORM Your name and address: __________________________________________________________________ __________________________________________________________________ __________________________________________________________________ __________________________________________________________________ If you have an e-mail address, and would like to be notified of bug fixes and new versions of NoICE, please list your e-mail address: __________________________________________________________________ Target processor(s) desired: ____ Z80/Z180 ____ Z8 ____ 68HC11 ____ 6809 ____ 8051 ____ 80(1)96 ____ 65(C)02 ____ M50740/M38000 ___ TMS370 In order to assist me in adding new features and symbol processors to NoICE, please list the assembler(s) and/or C compiler(s) which you intend to use: __________________________________________________________________ In order that I may most effectively distribute new versions of NoICE and other shareware products, please tell me where you got your demo copy of NoICE, and what version that copy was: __________________________________________________________________ __________________________________________________________________ If you heard about NoICE from a registered user, mention that user's name and current address, and I will send them a $5 rebate. Encourage your friends to register, and earn back your payment. __________________________________________________________________ If you have any other comments, please list them below.