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. ,