Chapter 7 The Debugger Introduction The MonAm Debugger Programming mistakes (known as bugs, after a spider that was found crawling around the core memory of one of the early computers) can range from the trivial, such as a missing linefeed in a printout, through the usual (an incorrect result) to the very serious where the computer crashes because you have used the wrong pointer or corrupted the system memory (like that spider). To help you find and correct all forms of bugs, HiSOFT BASIC includes a debugger, MonAm. MonAm is a powerful symbolic debugger and disassembler which lets you examine programs and memory, execute programs an instruction at a time and trap processor exceptions caused by programmer error. MonAm uses its own screen (in the Amiga¨ sense), so if you are debugging a program which uses windows, your program will not be sent re-draw messages or have its display destroyed when you single-step or breakpoint. This makes it particularly useful for graphical output programs such as applications running under Intuition. If you are already an expert from using MonAm supplied with Devpac Amiga version 3, please read the next few pages on the use of MonAm with HiSOFT BASIC. Devpac 2 users should note that many new features have been added to version 3 of the debugger. Debugging BASIC Programs Although MonAm is a low-level debugger, displaying such things as 680x0 instructions and registers, it can be used to good effect for debugging programs written with any compiler that generates machine-code output such as HiSOFT BASIC. You will see sub-program and function names within the code and you can view your original source and step through it by line etc. However, in order to make use of the debugger and to understand this section of the manual you should have at least a basic knowledge of assembly language. It is not intended for the beginner. In order to use the debugger fully with HiSOFT BASIC programs you must remember to enable both the Line Debug (either compressed or standard) and Debugging Symbols options. Note that this does not give you access to local variables. In general it is easier to debug programs that do not use the BASIC shared library since the debugger will then give the names of the runtime routines. One thing to consider before groping around inside your program with MonAm is that many bugs can be discovered much more easily by simply looking at the source code. Take some time to explore the problem and then carefully study the parts of the program likely to produce such results. Using this method of debugging you are much more likely to spot structural errors or find a better way of doing something rather than simply patching up the problem. Program initialisation Before your BASIC program starts executing, a number of initialisation procedures will be called. These include the startup code which handles CLI or Workbench startup with parameters, heap and run-time initialisation. Your program will start at label REF0001. You can use the Run Until command and simply enter #1 which will run until the first line of your program. Alternatively you may wish to run until a certain line number in your source file. Source files MonAm is able to understand line number debugging information so that it Ôknows' where in memory each program line starts and can automatically load your source code for you. Using these facilities, the debugger will Ôtrack' the source code correctly showing both the current instruction in a disassembly and the corresponding line of BASIC. By default, MonAm attempts to load the program source for you (although you may disable this via the Preferences command). For many programs, you need not worry about multiple source files but when working on a larger program which is divided into a number of source files you will want access to each one. You may load further source files from disk by selecting the appropriate window and using the Load ASCII command (Ctrl-A). If any line number debugging was generated for the file it will also be Ôlocked' to the program counter so that it is tracked automatically. When control switches between source files (calling a procedure in another unit, for example) it is up to you to flip between them using the . and , keys. When a source file is loaded, you may line numbers with all of the debugger commands through two special operators; # and ?. The first of these yields a program address, so placing a breakpoint at #10 puts a breakpoint at line 10. The expression #0 is taken to mean the first executable line of code. The second, less frequently used operator does the opposite, returning you the line number corresponding to a given program address. Variables Although there are no facilities for displaying a particular Pascal variable it is quite possible to examine or even change the values of program variable. All global variables are given a label name so that typing their name will return the address at which they are stored in memory, not their value. Setting a window start address to a variable name will allow you to view and edit that memory. Understanding the generated code The easiest way to find the machine code that corresponds to a line in your BASIC program and vice versa is with the debuggers # and ? operators. If you have used the Add Error Line Numbers (LINES) option you will see lines of code such as: move.l #$AAAABBBB,(A5) at the beginning of the code for each line. The hex number AAAA is the physical line number i.e. the line number displayed by the editor, while the hex number BBBB is the last actual line number given in the source. If you have Event checks switched on you will also see a line like this: jsr $14(A5) at the start of each line. This is the code that checks to see if an event has occurred. To find the value of a global variable find a line when its value is set. The code for this line will finish by storing its value via an offset from A5. For example, a%=42 might generate move.w #$2A,$E78(a5) Here $2A is 42 in hexadecimal. The variable a% will be stored at address a5+$E78. Setting a window start address to a variable name will allow you to view and edit that memory. When interpreting the data you are looking at you must bear in mind the format in which the variable is stored, whether it is a integer, or long integer or string for example. See Appendix G for further details. A quicker way to examine a numeric variable's value without upsetting your window display is to use the Other Bases command by simply pressing O. Something similar to the following line can then be entered: {a5+E78}.w This would display the word (omitting the extension shows a longword) stored in counter in both decimal and hex. Note that Mon also Ôunderstands' about the way that HiSOFT BASIC deals with in-line strings. These are really a subroutine call (to str_constant) followed by the length of the string and its actual data. Fortunately this is disassembled as: string "data" so that you may just skip over it using Ctrl-T. Also, note that you may see NOP instructions within the compiled code; don't be alarmed. These are produced by the code generator because on its first pass it leaves room for a JMP absolute instruction when program flow changes, but on pass 2 it notices that the destination is within range for a four byte BRA, so it has to add the NOP (it does not optimise to BRA.S as these take the same time to execute). As the NOPs never get executed there is no speed penalty, but there is a size increase. This is worthwhile; the result is that there are no size limits on compiled programs. Termination You will normally want to run the program until you detect certain conditions or an exception occurs. In many cases you can just return control to the program with Ctrl-R and allow it to terminate normally. However, sometimes this is not possible. If the program is about to do something wrong, such as pass the incorrect value or use an uninitialised pointer, you may be able to manually adjust the values so that it works correctly. If you want to abandon the program you can just quit MonAm which will leave the program in memory in a halted state. If you wish to exit more cleanly then you should resume execution from the label System which is effectively like executing a BASIC SYSTEM statement. This may leave some resources lying around but it will terminate the program, allowing you to continue with further compilations etc. Note however that if the A5 or A3 registers have been corrupted the system will almost certainly crash. Warning: be very wary of using the machine after a program has crashed. Any memory corruption can cause serious problems either immediately or much later on. If you think the machine may be in a compromised state it is always much safer to reboot before continuing. MonAm Concepts Here is a swift look at the concepts behind MonAm; it is a good idea to read this section before moving on to the next sections, even if you are an experienced programmer. Front Panel Display When MonAm is invoked it displays a Front Panel showing registers, memory, source code and instructions. The name Front Panel stems from the type of panels that were mounted on mainframe and mini computers to provide information on the state of the machine at a particular moment, usually through the use of flashing lights. These lights represent whether or not particular flip-flops (electronic switches) within the computer are open or closed; the flip-flops that are chosen to be shown on this panel are normally those that make up the internal registers and flags of the computer thus enabling programmers and engineers to observe what the computer is doing when running a program. These were hardware front panel displays; what MonAm provides you with is a software front panel - the code within MonAm works out the state of the computer and then displays this information on the screen. The MonAm display consists of a number of windows through which you can view the 680x0 registers, a disassembly of your program, your program's source code or a portion of memory - you choose what you want in each window (within certain limitations). The layout of MonAm's front panel is shown on the next page. MonAm's front panel MonAm's Windows As we have said, there are four different types of view through a window: * a register window in which you can see the various 680x0 data and address registers, the program counter (PC), the status register (SR) and the current instruction. The values of the data and address registers are shown in hexadecimal together with some information about the locations to which the registers point. * a disassembly window which shows a 680x0 disassembly of the memory that it is addressing, including any symbols that are found. * a memory window which displays the contents of memory locations in hexadecimal and ASCII. * a source code window. In this type of window you can view a text file which may be the source code of the program that you are debugging, assuming that this exists. You can display line numbers if you wish and, if the program that owns the source code has been compiled with line debugging enabled, you will be able to use this information to step through the program's source code and set breakpoints on source lines. Up to five windows can be shown simultaneously or, by changing the width and height of the windows you, can show just two. Each window is numbered from 1 to 5 and can display different types of information - window 1 can be of any type, register, memory, source code or disassembly; windows 2 and 4 can be memory, disassembly or source code windows whilst windows 3 and 5 are restricted to being memory windows. Stacking Windows Each window also has depth - you can stack views beneath a window so that you have almost limitless flexibility in what you choose to display. In addition you can split and widen most windows; split means to grow or to shrink the window vertically whilst widen means to do the same horizontally. These operations may hide other windows temporarily or they may uncover hidden windows. Locking Windows Each window may also be locked to an arbitrary expression. Thus, you can lock a memory window to a register so that it displays the contents of the memory addressed by that register. Or you might want to lock a disassembly window to the PC, which is the default condition for window 2 unless you have saved. Each view on the window stack can be locked to a different expression although it does not make sense to lock the register window. All the above window features will be discussed in more detail later. The Current Window MonAm uses the concept of a current window - this is denoted by displaying its title highlighted and is the window on which any operation will take place. The current window may be changed by pressing the Tab key to cycle between them, or by pressing the A key together with the window number, for example A2 selects window number 2, even if it is hidden currently. If your typing seems to be ignored in MonAm don't be alarmed; it means that another screen is active, such as that of your program. To correct this click on any part of the MonAm display. You can always tell when the MonAm display is active because the mouse pointer will be bug-shaped. MonAm and Multi-Tasking The Amiga¨ is a multi-tasking machine, and this imposes some restrictions on what MonAm can do. Having loaded a program (or task) into memory, that task is suspended. This means it is waiting, in this case for a MonAm command to let it continue. The other state the task can be in is executing - running at the same time as MonAm. Some commands require one or other of these states to operate - for example you can only single-step a task that is suspended. If the task is running you will get the error Task must be suspended! when you try to single-step it. MonAm can only debug one task at a time. Symbolic Debugging A major feature of MonAm is its ability to use symbols taken from the original program whilst debugging. MonAm uses standard AmigaDOS file HUNK_SYMBOL hunks as produced by most Amiga¨ programs that produce executable files, such as linkers, compilers and GenAm, the assembler supplied with Devpac Amiga. Naturally HiSOFT BASIC produces these. MonAm can also accept line number information from various different types of HUNK_DEBUG hunk, which enables the debugger to handle source code files that are connected with the program being debugged on a line basis. If the program to be debugged contains this line number information, you will be able to set breakpoints in its source code and even single-step it, source line by source line. Products that support this, currently, are: HighSpeed Pascal, Devpac Amiga 3, HiSOFT BASIC 2 and SAS/Lattice C. MonAm Requesters MonAm makes extensive use of requesters which are similar in concept to those in Intuition programs but have several differences. a MonAm requester A MonAm requester displays the prompt ESC to abort above the top left corner of the box together with a prompt, normally followed by a blank line or some text to edit, with a cursor. At any time a requester may be exited by pressing Esc, or data may be entered at the cursor by normal typing. Various keys may be used to edit the text: ¬, ® move the cursor left or right through the text Shift-¬, Shift-® move the cursor to the start of the line or to the end of the line Backspace delete the character behind the cursor Del delete the character under the cursor AX delete the entire line Esc abandon the requester commands available within MonAm requesters When you have finished entering a line, press the Return key; if the line contains errors the screen will flash and the Return key will be ignored allowing correction of the data before pressing Return again. Some MonAm requesters simply display a message together with the prompt Return; these are normally used to inform you of some form of error. The box will disappear on pressing the Return or Esc keys, whichever you find more convenient. Command Input MonAm is controlled by single-key commands which gives a fast user-interface, although this can take getting used to if you are familiar with a line-oriented command interface of another debugger. Users of our debuggers on other machines such as the Atari range will find many commands are identical. In general the A key is the window key - when used in conjunction with other keys it acts on the current window. The Ctrl key is usually used to invoke commands connected with execution of the program that is being debugged. Commands may be entered in either upper or lower case. Those commands whose effects are potentially disastrous require the Ctrl key to be pressed in addition to a command key. The keys used were chosen to be easy to remember, wherever possible. Commands take effect immediately - there is no need to press Return and invalid commands are simply ignored. The relevant sections of the front panel display are updated after each command so any effects can be seen immediately. MonAm is a powerful and sometimes complex program and we realise that it is unlikely that many users will use every single command. For this reason the remainder of the MonAm manual is divided into two sections - the former is an introduction to the basic commands of the program, while the latter is a full reference section. It is possible for new users and beginners to use the debugger effectively while having only read the Overview; but don't be intimidated by the Reference section. MonAm Overview Starting MonAm MonAm is invoked by typing the command monam [Return] or by calling it from the HiSOFT BASIC editor. If you start MonAm from a CLI you can include, optionally, a program name and a command line to be passed to the program. For example, monam c:mytest demos/finbonacci.s [Return] will cause MonAm to be invoked which will load a program called mytest and pass a filename to this program. When MonAm has loaded, the screen will look like this: The MonAm initial screen If you started MonAm without asking for a program to be loaded, the prompt Executable file to load will appear. This gives you another chance to load a program to debug; either type the filename of the program that you want to investigate and hit Return or press Return by itself (or Esc) to quit the requester. Should MonAm have been called from the HiSOFT BASIC editor, the program that you are developing will be loaded automatically or used from memory, if it was compiled there. Debugging a Program If you have asked MonAm to load a program to debug you may now be prompted for a command line, if you haven't already given one; enter the line you want or just press Return. MonAm will then try to load the program. If it fails, it will display AmigaDOS error xx You can use the Load Program command to try to load the program again. Assuming the filename is valid, MonAm will load the executable file and any symbols within the file. After the file and its symbols have been loaded successfully, the message Breakpoint will appear; this is because MonAm places a breakpoint at the first instruction of the program and then executes it. The most common command in MonAm is probably single-step, obtained by pressing Ctrl-Z (or Ctrl-Y if you find it more convenient, perhaps because you have a German keyboard). This will execute the instruction at the PC, shown in the Register window and, normally, also in the Disassembly window. After executing it the debugger re-displays the values of the windows, so you can watch the processor execute your program, step by step. Single-stepping is the best way of going through sections of code that are suspect and require deeper investigation, but it is also the slowest - you may only be interested in a section of code near the end of your program which could take a long tome to reach if you have to single-step all the way. There is, of course, an answer. Breakpoints A breakpoint is a special instruction placed into your program to stop it running and enter MonAm. There are many types of breakpoint but we will restrict ourselves to the simplest for now. A breakpoint may be set by pressing AB, then entering the address you wish to place the breakpoint. You can enter addresses in MonAm in hex (the default base), as a symbol, or as a complex expression. Examples of valid addresses are 1A2B0, prog_start, 10+mydata or #12 (this means line 12 hexadecimal). If you type in an invalid address the screen will flash and allow you to correct the expression. Having set a breakpoint you need some way of letting your program actually run, and Ctrl-R will do this. If will execute your program using the values of the registers displayed and starting from the PC. MonAm will be re-entered if a breakpoint has been hit, or if an exception occurs. MonAm uses its own screen which is independent of your program's screen. If you use the screen gadgets at the top right of the MonAm screen you will see your current program's display. This allows you to debug programs without disturbing their output. The MonAm screen will go to the back when you run a program from within the debugger and pop to the front when a breakpoint or other exception is reached. As usual, you can drag the MonAm screen from the top to reveal your program's screen. Windows MonAm uses its own windows too, and any window may be zoomed to the full screen size by pressing AZ. To return to the main display press AZ again, or the Esc key. The Esc key is also the best way of getting out of anything you may have invoked by accident. The Zoom command, like all A commands, works on the current window which you can change by pressing Tab. You can dump the current window to your printer by pressing AP. To change the address from which a window displays its data, press AA, then enter the new address. The locking of a window to an expression is detailed in the Reference section. Quitting MonAm To quit MonAm press Ctrl-C. This returns MonAm directly to the CLI. If the task you are debugging is still running or suspended when you try and quit, you will be warned. If MonAm terminates while the task under investigation is running, the machine will crash if any exception occurs subsequently. A safer way to exit is to use the Ctrl-Q command to stop the task first. If you used the Debug option from the editor then Ctrl-C will always terminate your program as well as MonAm. We hope this overview has given you a good idea of the most common features of MonAm to let you get on with the complex process of writing and debugging assembly language programs. When you feel more confident you should try and read the following Reference section, probably best taken, like all medicine, in small doses. MonAm Reference This is the reference section to MonAm; it is a complete description of the features and commands of this powerful debugger. Numeric Expressions There are many occasions within MonAm when you will want to enter a numeric expression; perhaps to lock a window to an expression, to assign a value to a register or to set the start address of a window. For these cases, MonAm has a full expression evaluator, based on that in GenAm, our assembler, including operator precedence. The main difference between it and a BASIC expression evaluator is that the default base for numbers is hexadecimal. The BASIC operators like and which have symbolic names are replaced by symbols. The precedence table for MonAm's operators is given below: Precedence of Operator Operator(s) 1 monadic minus (-) and plus (+), source operators (# and ?) 2 bitwise not (~) 3 shift left (<<) and shift right (>>) 4 bitwise And (&), Or (!) and Xor (^) 5 multiply (*) and divide (/) 6 addition (+) and subtraction (-) 7 equality (=), less than (<), greater than (>), inequality (<> and !=), less than or equals (<=), greater than or equals (>=) The comparison operators are signed and return 0 if false or -1 ($FFFFFFFF) if true. The shift operators take the left hand operand and shift it the number of bits specified in the right hand operand, vacated bits are filled with zeroes. This precedence can be overridden by the use of parentheses ( and ). With operators of equal precedence, expressions are evaluated from left-to-right. Spaces in expressions (other than those within quotes - ASCII constants) are not allowed. All expression evaluation is done using 32-bit signed-integer arithmetic, with no checking of overflow. Numbers Absolute numbers may be in various forms: decimal constants, e.g. \1029 hexadecimal constants, e.g. 12f or $12f octal constants, e.g. @730 binary constants, e.g. %1100010 character constants, e.g. ÔX' \ is used to denote decimal numbers, $ is used to denote hexadecimal numbers (the default), % for binary numbers, @ for octal numbers and single Ô or double " quotes for character constants. Character Constants Whichever quote is used to mark the start of a string must also be used to denote its end and quotes themselves may be used in strings delimited with the same quote character by having it occur twice. Character constants can be up to 4 characters in length and evaluate to right-justified longs with null-padding if required. For example, here are some character constants and their ASCII and hex values: Entered Value Hexadecimal "Q" Q $00000051 Ôhi' hi $00006869 "Test" test $54657374 "it's" it's $6974277C Ôit''s' it's $6974277C Symbols may be referred to and are normally case-insensitive and significant to 32 characters although this can be changed with the MonAm Preferences command. Registers may be referred to simply by name, such as A3 or d7 (case insensitive), but this causes a clash with certain hex numbers. To obtain such hex numbers precede them with either a leading zero or a $ sign. There are several reserved symbols which are case insensitive, namely CODE, SP, SR, and SSP. Both A7 and SP refer to either the user- or supervisor-stack, depending on the current value of the status register. CODE refers to the first hunk in the program. This is the same as HUNK1. The second hunk is HUNK2 and so on. Source Operators There are two operators which allow debugging at a source code level; these are the # and ? operators. To use these operators, you must have a source window open which is associated with the loaded executable program. In turn, this loaded program must have been produced by a package that includes line number information in the program's HUNK.DEBUG hunk, i.e. you have used one of the Line Debug options (LINEDEBUG and HCLNDEBUG). Otherwise the # and ? operators are invalid. The # operator takes a source line number as its argument and returns the associated memory address, within the loaded program. So, say you have the source of hello.bas loaded into window 2 and the executable of hello loaded as the current program then: m3=#20 will set the start address of window 3 to the address of line number 20 of the hello program (assuming that window 3 is not locked to another expression). If the line number is out of range of the source (e.g. if you ask for line number 100 when there are only 90 lines of source), the result will be the address of the first or last line of the source, accordingly. If you use the # operator when there is no line number information available, the result will be 0. The ? operator is the reverse of #; it returns the source line number, given a memory address. If the address is out of range of the code connected with the source window, ? returns a value of 0. If you have only one source file loaded, the use of these operators is unambiguous. However, if you have loaded two or more source files into MonAm's windows, # and ? may return unpredictable results; in this case it is best to use them when one source file is open in the current window - they will then relate to this file. These operators allow you to perform a variety of commands on a source level such as: Set Breakpoint, Run Until and Lock Window. This can make the process of debugging a complex program a far simpler and less tiresome task. Indirection The MonAm expression evaluator also supports indirection using the { and } symbols. Indirection may be performed on a byte, word or long basis, by following the } with a period then the required size, which defaults to long. If the pointer is invalid, either because the memory is unreadable or even (if word or longword indirection is used) then the expression will not be valid. For example, the expression {data_start+10}.w will return the word contents of location data_start+10, assuming data_start is even. Indirection may be nested as you would nest ordinary parentheses. Memory Registers In addition there are 10 memories numbered M0 through M9, which are treated in a similar way to registers and can be assigned to using the Register Set command. These are available for your own use although some have special functions as described below - you can view the memory registers by zooming the register window. The values of memories 1 through 5 inclusive are the current start address of the relevant window (including source code displays) and assigning to them will change the start address of the display within that window. Here's a full table of the memory registers: Memory Register Contents m0 the effective address referenced by the current instruction (destination where there are two) m1 the start address of window 1 m2 the start address of window 2 m3 the start address of window 3 m4 the start address of window 4 m5 the start address of window 5 m6 spare m7 spare m8 the start address of any binary file that has been loaded m9 the end address of any binary file that has been loaded m8 and m9 are useful if you have loaded a binary file and then want to save it out to disk again - you do not have to remember the start and end addresses of the file, just use m8 and m9 when saving. If window 1 has a register display in it, m1 will be meaningless but will retain any previous value. Window Types There are five possible windows within the MonAm display and the exact contents of these windows and how they are displayed is detailed below. The allowed types of each window are:. Window Allowed Type(s) 1 register, memory, disassembly, source 2 memory, disassembly, source 3 memory only 4 memory, disassembly, source 5 memory only A window can have a number of different views attached to it; you can think of the window as a stack, having depth. So, in window 2, you can view a disassembly of code, a section of memory and a portion of an ASCII file, although only one of these at a time is visible. To cycle through the different views use the Next/Previous View commands and to create or delete a display use the Open View and Close View commands. Most windows can also be split, either vertically or horizontally so that more, or less, can be displayed within the window - this action may hide or reveal other windows and it is best to experiment with the split commands (described below) to understand how they work. A window can be locked to an expression so that its start address is dependent on the value of that expression - see the Lock to Expression command below. You can also zoom a window; it will then occupy the whole of MonAm's screen. Each type of window will now be described. Register Window the register window The data registers are shown in hex, together with the ASCII display of their four bytes. The address registers are also shown in hex, together with a hex display of the memory that each register is addressing. This is word-aligned or byte-aligned as necessary, with non-readable memory displayed as **. To the right of this hex display is its ASCII interpretation. The status register is shown in hex and in flag form, additionally with U or S denoting user- or supervisor-modes. The PC value is shown together with a disassembly of the current instruction. Where this involves one or more effective addresses these are shown in hex, together with a suitably-sized display of the memory they point to. For example, the display TST.L $12A(A3) ;00001FAE 0F01 signifies that the value of $12A plus register A3 is $1FAE, and that the word memory pointed to by this is $0F01. A more complex example is the display MOVE.W $12A(A3),-(SP) ;00001FAE 0F01 > 0002AC08 FFFF The source addressing mode is as before but the destination address is $2AC08, presently containing $FFFF. Note that this display is always of a suitable size (MOVEM data being displayed as a quad-word) and when pre-decrement addressing is used this is included in the address calculations. Disassembly Window the disassembly window Disassembly displays show memory as disassembled instructions to the standard described below. On the left the hex address is shown, followed by any symbol, then the disassembly itself. The current value of the PC is denoted with a >, if it is visible. You can scroll through the disassembly window as described under Cursor Keys below. If the instruction has a breakpoint placed on it this is shown using square brackets ([ ]) afterwards, the contents of which depend on the type of breakpoint. For stop breakpoints this will be the number of times left for this instruction to execute, for conditional breakpoints it will be a ? followed by the beginning of the conditional expression, for count breakpoints it is an = sign followed by the current count and for permanent breakpoints a * is displayed. The exact format of the disassembled op-codes is to the Motorola standard. All output is upper-case (except lower-case labels) and all numeric output is in hexadecimal, except Trap numbers. Leading zeroes are suppressed and the $ hex delimiter is not shown on numbers less than 10. Where relevant numerics are shown signed. The only deviation from Motorola standard is the register lists shown in MOVEM instructions - in order to save display space the type of the second register in a range is abbreviated, for example MOVEM.L d0-d3/a0-a2,-(sp) will be disassembled as MOVEM.L d0-3/a0-2,-(sp) Certain library calls will be shown symbolically even if no symbol information was loaded with your program. The disassembler is intelligent and recognises a MOVE into register A6 followed by a JSR using A6 so that the call, if valid, will be displayed by name; for example move.l 4,A6 jsr _LVOOpenLibrary(A6) The disassembler does this for the exec, graphics, dos and intuition libraries, using the special file monam.libfile. If this file is not found in the current directory or the current libs: assignment during MonAm's initialisation then such disassembly will not occur. Memory Window the memory window Memory displays show memory in the form of a hex address, word-formatted hex display and ASCII. Unreadable memory locations are denoted by **. The number of bytes shown is calculated from the window width, up to a maximum of 16 bytes per line. You can scroll through the memory window as described under Cursor Keys below. Source Window the source window The source window shows ASCII files in a similar way to a screen editor with the name of the file displayed in the title bar. The default tab setting is 8 though this can be toggled to 4 with the Edit Window command. You can choose whether or not to display line numbers for the file and whether they are shown in decimal or hexadecimal. When line number information exists in the HUNK_DEBUG hunk of your program, you can use the medium level debugging features of MonAm to step through the source and set breakpoints within it, rather like you can with a source code debugger. You can scroll through the source window as described under Cursor Keys below. Cursor Keys The cursor keys can be used on the current window, the action of which depends on the display type. On a memory display all four cursor keys change the current address, by byte or line, while Shift ­ and Shift ¯ move a page in either direction. On a disassembly display ­ and ¯ change the start address on an instruction basis, ¬ and ® change the address on a word basis and Shift ­ and Shift ¯ on a page basis. On a source-code display ­ and ¯ change the display on a line basis, and Shift ­ and Shift ¯ on a page basis. Window Commands Commands that are reached through the use of the A (right Amiga) key are normally available at any time. Many of these commands are connected with and apply to the current window. The current window is denoted by having an inverse title and it can be changed by pressing Tab or A plus the window number. Most window commands work in any window, zoomed or not, though when it does not make sense to do something the command is ignored. The exceptions to the above are the Stack, Unstack and View Stack commands which, for ease of use, are not reached through the A key and do not work on a zoomed window. AA or M Set Address Allows you to set the starting address of a memory, disassembly or source window (the latter only if line number information exists in the HUNK_DEBUG hunk). You can use any valid expression to generate this start address e.g. _main $C227B8 StartProgram+8 PC AE Edit View On a memory window this lets you edit memory in hexadecimal or ASCII. Hex editing can be accomplished using keys 1-9, A-F, together with the cursor keys. Pressing Tab switches between hex & ASCII, ASCII editing takes each keypress and writes it to memory. The cursor keys can be used to move about memory. To leave edit mode press the Esc key. On a register display using this command is the same as using AR, Register Set, described shortly. Within a source window this command toggles the tab setting between 4 and 8. You cannot edit a disassembly window. AG Goto Source Line This command works on source windows and allows you to choose the line that will appear at the top of the window. If you select a line that is beyond the end of the file, the last line will be shown at the top of the window. AL Lock to Expression This allows source (with line number information), disassembly and memory windows to be locked to a particular expression. After any exception the start address of the display is re-calculated, depending on the locked expression. Each stacked view within a window can have its own lock. MonAm will ignore you if you try to lock a source window that refers to a program that does not have line number information attached to it. If you try to lock a source window to an expression that lies outside the address range of the source file you will be ignored. This, in fact, is very useful; it means that if you have a stack of source windows (see below for details of stacking windows) which make up the executable that you are debugging and you lock each display to the PC, you will be able to trace the path of the program through each source file. If an instruction in the top view calls a subroutine in the stack, the top view will not change but, if you then view the relevant stacked view, it will change to show you the called subroutine. To unlock, simply enter a blank string. You can lock one window to another window by using the memory registers such as M2. You can even lock a window to the indirection of its own memory register (e.g. {m2}) which might be useful to step through a linked list (in conjunction with the Esc key to update the window each time). AP Print Window Dumps the current window contents onto the printer or to a file. This command can be aborted by pressing Esc. You can choose the printer device and the filename using the Preferences command. AS Split Window Splits a window vertically i.e. makes it taller or shorter depending on its current state; this may hide or uncover another window. You would normally use this to set up the display as you like it and then save the set-up with the Save Preferences command. It can be useful at any time, though, if you would like to see more information in a window or you need another window. This command has no effect on window 1. AT Type This command works on windows 1, 2 and 4; it changes the type of the display between register (for window 1), disassembly, memory and source (if a source file has been loaded into the window). AW Widen Window Splits a window horizontally i.e. makes it wider or narrower depending on its current state; this may hide or uncover another window. You would normally use this to set up the display as you like it and then save the set-up with the Save Preferences command. It can be useful at any time, though, if you would like to see more information in a window or you need another window. This command has no effect on window 1. AZ Zoom Window This zooms the current window to be full size. Other A commands are still available and normal size can be achieved by pressing Esc or AZ again. Zooming a register window shows some extra information (which depends on the processor type) and the memory registers (m0 - m9): the zoomed register display (on a 68020 machine) A zoomed window behaves differently from a normal window in that, as you scroll through it, it does not update the associated memory register (m1 to m5). Also, if you change the value of the memory register while in a zoomed window , the start address of the display will not change. Think of a zoomed window as only temporary. Shift-. Open View Creates a new view on the current window and numbers it accordingly. The type of the new view will be the same as the previous one if this is possible. The display will be numbered xa, xb, xc, xd etc. where x is the number of the window e.g. if you stack a new display on window 2, it will be numbered 2b with the original display being numbered 2a. Remember, though, that there is only one memory register per window, but you can lock each display to a different expression. This gives a tremendous amount of flexibility. This command does not work on a zoomed window. The associated memory register is bound to the top view only, although all locks on all views are re-calculated where necessary. Shift-, Close View Removes the visible display from the current window's display list, unless there is only one display attached to this window, in which case the command does nothing. If you close a view on a source window, the source file will be un-loaded from memory and a disassembly window will replace the closed source view. All other displays attached to this window will be re-numbered if necessary i.e. if you remove display 2c from (2a, 2b, 2c, 2d), 2d will be re-numbered to be 2c. This command does not work on a zoomed window. . and , Next/Previous View These two commands allow you to cycle through views that have been stacked onto a window. Pressing . (full stop or period) cycles forward through the available displays whilst , (comma) cycles backwards. Both will roll round in a loop. For example, say you have 3 displays stacked on window 4 (4a Source, 4b Memory and 4c Disassembly) and you are currently displaying 4b Memory. Press . and 4c Disassembly will appear, press . again and you will see 4a Source. These commands do not work on a zoomed window. Esc Pressing Esc will update all the window displays, if necessary and re-calculate the addresses to which any windows and views are locked. This can be very useful in many cases; for example say you have window 3 locked to {m5} (the address pointed to by window 5) and you then scroll through window 5. Normally this will not update window 3. However, all you have to do is to press Esc when you want to update window 3 (and all the other windows). You can press the Esc key while your program is running to see how the machine state is changing (assuming that the MonAm screen is at the front). Other A Commands All A (right Amiga) commands (like the window commands described above) are available for use at any time whilst you are using MonAm. There are a few other such commands that are not related to the current window: AB Set Breakpoint Allows the setting of any type of breakpoint, described later under Breakpoints. AO or O Show Other Bases This prompts for an expression and displays its value in hexadecimal, decimal and as a symbol if relevant. example of Show Other AR Register Set Allows any register to be set to a value, by specifying the register, an equals sign and its new value. It can also be used to set the value of the memory registers. For example the line a3=a2+4 sets register A3 to be A2 plus 4 whereas: m3=m2 will set the value of the window 3 register to be the same as the window 2 register. All windows will then be re-drawn, which may cause a display that you did not expect if, say, the display in window 3 is locked to an expression. You can also use this to set the start address of a window when in zoom mode so that, on exit from zoom mode, the relevant window starts at the required address. Screen Switching MonAm uses its own Screen display and will always make itself the front and active window whenever an exception (including breakpoints) occurs. V View other Screen This will put the MonAm screen to the back, normally showing your program's screen. Pressing any key will return the MonAm screen (so long as you have not activated any other window). Breakpoints Breakpoints allow you to stop the execution of your program at specified points within it. MonAm allows up to eight simultaneous breakpoints, each of which may be one of five types. When a breakpoint is hit MonAm is entered and it then decides whether to halt execution of your program (when it will enter the front panel display) or continue; this decision is based on the type of the breakpoint and the state of your program's variables. Simple Breakpoint [1] These are one-off breakpoints which, when executed, are cleared and cause MonAm to be entered. Stop Breakpoint [n] These are breakpoints that cause program execution to stop after the break-pointed instruction has been executed a specified number of times. In fact a simple breakpoint is really a stop breakpoint with a count of one. Count Breakpoint [=] Merely counters; each time such a breakpoint is reached a counter associated with it is incremented, and the program will resume. These breakpoints are more like monitors - they never cause a program to stop and are useful for profiling. Permanent Breakpoint [*] These are similar to simple breakpoints except that they are never cleared - every time execution reaches a permanent breakpoint MonAm will be entered. Conditional Breakpoint [?] The most powerful type of breakpoint; these allow program execution to stop at a particular address only if an arbitrarily complex set of conditions apply. Each conditional breakpoint has associated with it an expression (conforming to the rules already described). Every time the breakpoint is reached this expression is evaluated, and if it is non-zero (i.e. true) then the program will be stopped, otherwise the program will continue. AB Set Breakpoint This is a window command allowing the setting or clearing of breakpoints at any time. The line entered should be one of the following forms, depending on the type of breakpoint required:
will set a simple breakpoint.
, will set a stop breakpoint at the given address, which will execute times. The expression is evaluated before the program is executed.
,= will set a count breakpoint. The initial value of the count will be zero.
,* will set a permanent breakpoint.
,? will set a conditional breakpoint, using the given expression.
,- will clear any breakpoint at the given address. Breakpoints cannot be set on addresses which are odd, unreadable, or within ROM. Every time a breakpoint is reached, regardless of whether the program is interrupted or resumed, the program state is remembered in the History buffer, described below Help Show Help and Breakpoints This displays the current breakpoints, task status, its segment list (showing where your program is), free memory and the system memory list. UK A500 1.2 users (who cannot use the Help key) can also obtain this command by pressing AH. Ctrl-B Simple Breakpoint Included mainly for compatibility with MonAm 1, this sets a simple breakpoint at the start address of the current window, so long as it contains a disassembly display. If a breakpoint is already there then it will be cleared. U Run Until This prompts for an address and a breakpoint specifier (1, n, =, *, or ?). The chosen type of breakpoint is then placed at the given address and program execution resumed. Ctrl-K Kill Breakpoints Clears all set breakpoints. This is also done automatically when you quit MonAm with a task still running. Ctrl-A Breakpoint After A command that places a simple breakpoint at the instruction after the instruction at the PC and resumes execution from the PC. This is particularly useful for DBF-type loops if you don't want to go through the loop, but just want to see the result after the loop is finished. Ctrl-X Stop executing This is a command to stop your task while it is executing. It does this by forcing the Trace bit to be set, so you will get a Trace exception. While this does work on some systems, be very careful if you stop a task in the middle of some AmigaDOS ROM routines, particularly signal handling and message passing. The above command accesses memory fields that are not guaranteed to remain the same for different versions of the Amiga¨ operating system. This command was Ctrl-S in MonAm version 1. History MonAm has a history buffer in which the machine status is remembered for later investigation. The most common way of entering data into the history buffer is when you single-step, but in addition every breakpoint reached and every exception caused enters the machine state into the buffer. The various forms of the Run command also cause entries to be made into this buffer. The history buffer has room for five entries - when it fills the oldest entry is removed to make room for the newest entry. H Show History Buffer This opens a large window displaying the contents of the history buffer. All register values are shown including the PC as well as a disassembly of the next instruction to be executed. If a disassembly in the History display includes an instruction which has a breakpoint placed on it, the [ ]s will show the current values for that breakpoint, not the values at the time of the entry into the history buffer. Quitting MonAm Ctrl-C or AQ Exit MonAm This exits MonAm, returning control to whatever task invoked MonAm. All breakpoints are killed although, if the task you are debugging is still running or suspended when you try and quit, you will be warned. If MonAm terminates while the task under investigation is running, the machine will crash should any exception occurs subsequently. Generally the best way to terminate a program is to set its PC to the label System and continue from there, first. If the Debug option has been used from the HiSOFT BASIC editor then MonAm will terminate automatically when the program it is debugging has terminated. Ctrl-Q Quit a program This is a way of forcing the task being debugged to quit. This can be hazardous to use, and should only be done as a last resort. If your program is terminated in this way it will not clean up, and thus not de-allocate any memory it was using or close windows etc. The above command accesses memory fields that are not guaranteed to remain the same for different versions of the Amiga¨ operating system. Loading & Saving Ctrl-L Load Program This will prompt for a filename and a command line and will attempt to load the file ready for execution. If MonAm has already loaded a program it is not possible to load another until the former has terminated. The file to be loaded must be an executable file. Use the Load Binary File command if you wish to edit other file types. This command is not available if MonAm has been invoked using Debug from the editor. B Load Binary File This will prompt for a filename and an optional load address (separated by a comma) and will then load the file where specified. If no load address is given then memory will be allocated from the system. M8 will be set to the start address of the loaded file and M9 to the end address. This is a change from version 2 of MonAm, where M0 and M1 were set to the start and end addresses of the loaded file. S Save Binary File This will prompt for a filename, a start address and an (inclusive) end address. To re-save a file recently loaded with the Load Binary File command ,M8,M9 may be specified, assuming of course that M0 and M1 have not been re-assigned. A or AQ Load ASCII File This powerful command allows an ASCII file, normally of source code, to be loaded and viewed within MonAm. This can be loaded into window 2 or window 4. If the loaded program has line number information relevant to this source file, you will be able to use line number operators on this display to step through the source code, set breakpoints within it etc. A new view on this window will be opened if the window already contains an ASCII file, otherwise the text will replace the current window. You can unload a source window using the Close View command. The source window will be locked automatically to the PC. Memory for source code displays is taken from the system so sufficient free memory must be available. Executing Programs Ctrl-R Return to program / Run This runs the current program with the given register values at full speed and is the normal way to resume execution after entry via a breakpoint or an exception. Ctrl-Z Single-Step Single-steps the instruction at the PC with the current register values. Single-stepping a Trap, Line-A or Line-F opcode will, by default, be treated as a single instruction. Ctrl-Y Single-Step Identical to Ctrl-Z above but included for the convenience of users of German keyboards. Ctrl-T Trace Instruction This interprets the instruction at the PC using the displayed register values. It is similar to Ctrl-Z but obeys BSRs, JSRs, Traps, Line-A and Line-F calls as if one instruction, re-entering the debugger on return from them to save stepping all the way through the routine or trap. It works on instructions in ROM or RAM. Ctrl-S Skip Instruction Ctrl-S increments the PC register by the size of the current instruction thus causing it to be skipped. Use this instead of Ctrl-Z when you know that this instruction is going to do something it shouldn't. R Run (various) This is a general Run command and prompts for the type of execution, selected by pressing a key. Run G Go This is identical to Ctrl-R and resumes the program at full speed. Run I Instruction This executes the entered number of instructions remembering information in the History buffer and then returning to MonAm. Traps are treated as single-instructions. Searching Memory G search memory (Get a sequence) You will see the prompt Search for B/W/L/T/I?, standing for Bytes, Words, Longs, Text and Instructions. If you select B, W or L you will then be prompted to enter the sequence of numbers you wish to search for, each separated by commas. MonAm is not fussy about word-alignment when searching, so it can find longs on odd boundaries, for example. If you select T you may search for any given text string, for which you will be prompted. The search will be case-dependent or case-independent, as you have chosen. If you select I you can search for part or all of the mnemonic of an instruction, for example if you searched for $E78(A5) you would find an instruction like MOVE.L D7,$E78(A5). The case of the string you enter is un-important unless you have chosen it to be so, but you should bear in mind the format that the disassembler produces, e.g. always use hex numbers, refer to A7 rather than SP and so on. Having selected the search type and parameters, the search begins, control passing to the Next command, described below. Searching Source-Code Windows If the G command is used on a source-code window the T sub-command is automatically chosen and if the text is found the window will re-display the line containing it. N find Next N can be used after the G command to find subsequent occurrences of the search data. With the B, W, L and T options you will always find at least one occurrence, which will be in the buffer within MonAm that is used for storing the sequence. With the T option you may also find a copy in the system keyboard buffer. With these options, the Esc key is tested every 64k bytes and can be used to stop the search. With the I option, which is very much slower, the Esc key is tested every 2 bytes. The search will start just past the start address of the current window (except register windows) and if an occurrence is found re-display the window at the given address. The search area of memory goes from 0 to the end of chip memory, then $F80000 to $FFFFFF (the ROM) then any additional RAM. Miscellaneous Ctrl-P Preferences This permits control over various options within MonAm. The first three require Y/N answers, pressing Esc aborts or Return leaves them alone. the Preferences display Auto-load source file When switched to Yes, upon loading a program, MonAm will attempt to load the first source file associated with the program. This will only occur if the executable file contains line number debugging information and the source file can be found in the current directory. The new source file window will then be locked to the Program Counter in order to track program flow. This is of most use when debugging a program generated from a single source file. Source window line numbers Affects whether line numbers are shown for all debugger source windows. You may select No line numbers, Decimal numbers or Hex numbers. Hexadecimal is often the preferred setting because by default, MonAm treats all numbers as hex. Decimal line numbers, used with the # operator for example, require a prefix of backslash. Automatic Ô_' or Ô@' prefix This is provided mainly for the convenience of C compiler users. With it enabled, MonAm will automatically add a leading underscore or @ character to the appropriate symbols. However, symbols without the leading character will still take precedence. Case insensitive symbols MonAm version 3 defaults to using case insensitive symbols, i.e. upper and lower case characters are not distinguished between. Selecting No will mean that you must match the case of each symbol character exactly as with previous versions of MonAm. Symbol significance This prompts for the significant length of symbols, which is normally 32 but may be reduced to as low as 8 or increased if required. Although reducing this can save some typing, using too low a value can make some symbols impossible to select. Show relative offset symbols This option defaults to Yes and affects the disassembly of address register indirect with offset addressing modes, i.e. xxx(An). With the option on, the current value of the given address register is added to the offset then searched for in the symbol table. If found it is disassembled as symbol(An). This option is very useful for certain styles of assembly language programming as well as high level languages which use a base register as a major offset, such as SAS/C which uses A4 as a pointer to the merged data section. Show ZAn in disassembly Is normally switched off but advanced programmers may wish to enable the display of the normally hidden Z registers used by some 680x0 instructions. Interlace Allows you to choose between a double height interlaced NTSC/PAL screen for MonAm(Y), a non-interlaced NTSC/PAL screen (N) or the default screen mode set by the Workbench Screen Mode preferences(D). This option will take effect after preferences have been saved and MonAm restarted. MonAm will normally replicate the Workbench screen's format. Printer device name This lets you set the device that MonAm uses for its printer commands. The default is PRT:, the system printer device configured through Preferences. You may specify an AmigaDOS filename in order to re-direct printing to disk. Save preferences Reply Y to this command to save your current preferences to the file MonAm.prefs in the current directory. When MonAm loads it will read your preferences from this file. MonAm.prefs is firstly searched for in the current directory, then in the ENV:Devpac directory, in a similar way to the editor preferences file. Note that the ENV:Devpac directory is used rather than ENV:HBasic. This is for the benefit of users of our Devpac assembly language development system; there is only one debugger preferences file and the debugger from either package may be used interchangeably. Note however that versions 3.04 and below of MonAm did not Ôunderstand' about BASIC string constants. I Intelligent Copy This copies a block of memory to another area. The addresses should be entered in the form ,, The copy is intelligent in that the block of memory may be copied to a location which overlaps its previous location. No checks at all are made on the validity of the move; copying to non-existent areas of memory is likely to crash MonAm and corrupting system areas may well crash the machine. L List Labels This opens up a large window and displays all loaded symbols. Any key displays the next page, pressing Esc aborts. The symbols will be displayed in the order they were found on the disk (or in memory if using the Debug option from the editor). Ctrl-U name Unload symbols This command can only be used if you are debugging a task which had a symbol table loaded with it. What it does is de-allocate the memory used for storing the symbols, freeing it for the system to use. This can be very useful if memory is tight while debugging a larger program, as you can load it, together with symbols, set a breakpoint at a symbolic address, then lose the labels before letting it run. Of course once you hit your breakpoint you won't have any symbols. W Fill Memory With This fills a section of memory with a particular byte. The range should be entered in the form ,, The warning described previously about no checks applies equally to this command. P Disassemble to Printer/Disk This command allows the disassembly of an area of memory to printer or disk, complete with original labels and, optionally, an automatic list of labels created by MonAm, based on cross-references. The first line should be entered as , The next line prompts for the area of memory used to build the cross-reference list, which should be left blank if no automatic labels are required else should be of the form , Next is the prompt for data areas which will be disassembled as DC instructions, of the form ,[,] The optional size field should be B, W or L, defaulting to L, determining the size of the data. When all data areas have been defined, a blank line should be entered. Finally a filename prompt will appear; if this is blank all output will be to the printer, else it will be assumed to be a disk file. If automatic labels were specified there may be a delay at this point while the table is generated. Automatic labels are of the form Lxxxxx where xxxxx is the actual hex address. Printer Output This is of the form of an 8 digit hex number, then up to 10 words of hex data, 12 characters of any symbol, then the disassembly itself. Printer output may be aborted by pressing Esc. Disk Output This is in a form directly loadable by GenAm, the assembler supplied with Devpac, consisting of any symbol, a tab, then the disassembly itself, with a tab separating any operand from the op-code. If you are disassembling an area of memory without loaded symbols then the XREF option should be used else no symbols will appear at all in the output file. Pressing Esc or a disk error will abort the disassembly. M Modify Address Included for compatibility with MonAm 1, equivalent to AA. O Show Other Bases Included for compatibility with MonAm 1, equivalent to AO. D Change Drive & Directory This allows the current drive and sub-directory to be changed. Command Summary Window Commands AA Set Address AB Set Breakpoint AE Edit View AG Goto Source Line AL Lock to Expression AP Print Window AR Register Set AS Split Window AT Change Type AW Widen Window AZ Zoom Window Shift-. Open View Shift-, Close View . and , Next/Previous View Esc Update all Windows Breakpoints Ctrl-A Breakpoint After Ctrl-B Simple Breakpoint Ctrl-K Kill Breakpoints Ctrl-X Stop Executing AB Set Breakpoint U Run Until Help Show Help and Breakpoints Loading and Saving Ctrl-L Load Program A Load ASCII File B Load Binary File S Save Binary File Executing Programs Ctrl-R Return to program / Run Ctrl-S Skip Instruction Ctrl-T Trace Instruction Ctrl-Y Single-Step Ctrl-Z Single-Step R Run (various) Searching Memory G Search Memory (Get a sequence) N Find Next Miscellaneous Ctrl-C or AQ Exit MonAm Ctrl-Q Quit a program Ctrl-P Preferences Ctrl-U Unload symbols AO or O Show Other Bases D Change Drive & Directory H Show History Buffer I Intelligent Copy L List Labels M Modify Address P Disassemble to Printer/Disk V View other Screen W Fill Memory With Bug Hunting There are probably as many strategies for finding bugs as there are programmers; there is really no substitute for learning the hard way, by experience. However, here are some hints which we have learnt, the hard way! Firstly, a very good way of finding bugs is to look at the source code and think. The disadvantage of reaching first for the debugger, then second for the source code, is that it gets you into bad habits. You may switch to a machine or programming environment that does not offer low-level debugging, or at least not one as powerful you are used to. If a program fails in a very detectable way, such as causing an exception, debugging is normally easier than if, say, a program sometimes doesn't quite work exactly as it should. Many bugs are caused by a particular memory location being stepped on. Where the offending memory location is detectable, by producing a bus error, for example, a conditional breakpoint placed at one or more main subroutines can help greatly. For example, suppose the global variable at address $123456 is somehow becoming odd during execution, the conditional expression could be set up as {$123456}&1 Count breakpoints are a good way of tracking down bugs before they occur. For example, suppose a particular subroutine is known to eventually fail but you cannot see why, then you should set a count breakpoint on it, then let the program run. At the point where the program stops, because of an exception say, look at the value of the count breakpoint (using Help). Terminate the program, re-load it, then set a stop breakpoint on the subroutine for that particular value or one before it. Let it run, then you can follow through the sub-routine on the very call that is fails on, to try and work out why. Good luck! Exceptions MonAm employs the 680x0 processor exceptions to stop runaway programs and to single-step, so at this point it would be useful to explain them and detail what normally happens when they occur on an Amiga. While using the 680x0 processors, there are various types of exception that can occur, some deliberately, others accidentally. An exception is a special condition that takes priority over normal processing - it might be an interrupt from an external device, an illegal instruction, an address error, a co-processor violation or a number of other pre-defined events. When an exception occurs the processor's context is saved on the supervisor stack and execution is then transferred to any one of 256 different addresses, held in the exception table (on the 68010 upwards, the address of the start of this table is held in the vector base register, or VBR). This table is set up by the Amiga's operating system so that an exception effectively transfers control to Exec, which is part of the Amiga's operating system. The operating system then looks to see if the task that was running when the exception occurred has installed an exception handler i.e. the task wants to handle exceptions itself. If it has, control is passed to that exception handler; this is how MonAm traps exceptions because MonAm has attached such an exception table to the task that it has executed. Unfortunately, there a few exceptions that MonAm cannot trap because Exec does not pass them on - in these cases the operating system does what it normally does in the absence of an exception handler, it produces a Software Error alert (the dreaded Guru). MonAm actually uses two of the exception vectors itself, one to set breakpoints in programs and the other to allow single-stepping. The various forms of exceptions, their usual results, and what happens when they occur with MonAm active is shown in the following table, which is a summary of the exception table. Note that the first 64 vectors are defined by Motorola. Exception no. Exception MonAm active 0 reset initial interrupt stack pointer n.a. 1 reset initial program counter n.a. 2 bus error trapped 3 address error trapped 4 illegal instruction breakpoint 5 zero divide trapped 6 CHK instruction trapped 7 TRAPV instruction trapped 8 privilege violation trapped 9 trace single-step 10 line 1010 emulator trapped 11 line 1111 emulator trapped 12 reserved trapped 13 co-processor protocol violation trapped 14 format error guru 16-23 reserved trapped 24 spurious interrupt guru 25-31 level x interrupt autovector, where x=26-exception no. not trapped 32-47 trap #0 to #15 not trapped 48 FPCP branch or set on un-ordered condition trapped 49 FPCP inexact result trapped 50 FPCP divide by zero trapped 51 FPCP underflow trapped 52 FPCP operand error trapped 53 FPCP overflow trapped 54 FPCP signalling NAN trapped 55 reserved trapped 56 MMU configuration error guru 57 68851 illegal operation guru 58 68851 access level violation trapped 59-63 reserved trapped 64-255 user defined vectors unused Restrictions As it runs as a process MonAm relies on the exec, intuition and graphics libraries. If your program starts destroying memory to which it has no right it is possible for it to corrupt fatally something the system needs so that when MonAm is entered after an exception the machine will crash. Fortunately this type of error is rare, usually address errors occur before programs start destroying memory. Owing to a hardware feature, a word- or longword-access on odd memory locations 1 to 7 inclusive can cause a complete machine crash. There seems to be nothing we can do to prevent this. Environment When a program is invoked from MonAm it is set up to look as if it has been run from the CLI, not the Workbench. Don't try and run the standard system programs from within MonAm, such as dir. These programs rely on undocumented registers (particularly A5) and memory areas which MonAm cannot emulate. Single stepping MonAm cannot single-step or breakpoint any code when executing in Supervisor mode. This is because the exec exception handler checks for an exception in supervisor mode, and will put up a Guru alert if this is the case. If not it will enter MonAm and work normally. If your program creates another program or task you cannot use MonAm to breakpoint it or single-step. MonAm can only debug the program that was specified when it initially loaded. Taking over MonAm is an operating system debugger in that it relies upon the system for its display and input etc. If a program tries to shut down the system or take over resources (such as the screen display) for its own exclusive use, MonAm will no longer function correctly. An example of this is a games program which takes over the display. In some cases it is possible to work round this by using the correct operating system conventions for accessing shared resources (for testing only, if desired) such as opening an Intuition screen for the display.