\INTRODUCTION The RAG Software GPL Disassembler is a software tool to aid in exploring and understanding the contents of your GROM/GRAM cartridges. It can also serve as an aid in learning to program in GPL by allowing you to look at existing GPL code. The GPL Disassembler reads from GROM/GRAM and produces GPL Source code. The disassembly process is directed via a "symbol" file that you create using a text editor. With a sufficiently detailed symbol file the disassembler can produce readable GPL source code with comments and labels you have chosen. Provided with the GPL Disassembler is a GROM/GRAM dump utility, and an installation program that allows you to tailor the programs to your configuration. The GPL Diassembler disk also contains helpful partial symbol files and complete symbol files for disassembly of two popular cartridges. Hardware Requirements: .sp;lm+8;in-3 1.^Memory Expansion 2.^Disk Drive 3.^Printer 4.^Some means of loading a standard E/A Option 5 Assembler Language program independent of the cartridge being disassembled. .lm-8;in+0;sp \GETTING^STARTED .SP2 The first thing you should do is make a working copy of the distribution disk. The disk is unprotected and can be copied with any disk or file copy program. The disk contains the following files. .sp;lm+5 DA/DMII^ - Symbol File for DM II, DA/EA^^^^- Symbol File for E/A, INSGDA^^ - The Installation Program, RAGGDA^^ - The Disassembler Segment 1, RAGGDB^^ - The Disassembler Segment 2, RAGGDU^^ - The GROM/GRAM dump Utility, S/RAMPAD - Partial Symbol File, S/GROM0^ - Partial Symbol File. .sp;lm-5 Using the working copy of the Disassembler disk you can now run the installation program, INSGDA, to modify the Disassembler and Dump programs to work with your configuration. .bp \INSTALLATION^PROGRAM The Disassembler and Dump utility are designed to work with various loaders and printers, and to produce compact listings to reduce print time and paper usage. In order to do this you must "install" the Disassembler and utility programs with options suitable to your environment. The INSGDA (E/A Option 5) program on the distribution disk will prompt you for the values for your environmemt and then modify the Disassembler and Dump Utilitiy on disk so that they will use your values. In order to produce a compact listing the printer should be set up to print in elite mode at 8 lines per inch. To accomplish this printing, the programs will send a "setup sequence" of control characters to the printer before printing the first line of the listing, and will send a "reset sequence" of control characters to the printer after printing the last line of the listing. The programs will count the number of lines per page. The number of lines per page must be coordinated with the way your printer is set up. The Disassembler and Dump utility as distributed is set up for a generic printer. During entry of your default values, press ENTER to proceed to the next prompt or press BACK (FCTN 8) to begin again at the beginning. Typing an asterisk (*) as the first character of the line indicates that the corresponding default value is not to be changed. A response of all blanks or of just pressing ENTER indicates that there is to be &no default value. Each of the prompts is described below. &Installation^Drive^Number Enter the number of the disk containing a working copy of the Disassembler and Dump utility programs. During installation the two programs RAGGDA and RAGGDU are loaded from this drive and then saved back to the drive. The default installation drive is 1 (i.e. DSK1). &Printer^Name Enter the device/filename for your printer. The distributed printer name is "PIO". This will be the default output file name for the disassembler and dump programs. &Printer^Setup^Sequence Enter the printer control codes required for making your printer print in the mode you want. For example: in elite mode at 8 lines/inch, or in compressed mode at 8 lines/inch. Enter the data in hexadecimal (2 digits per byte). You will have to refer to your printer manual to determine the proper codes for your printer. There is no setup sequence in the distributed programs. .CP3 &Printer^Reset^Sequence Enter the printer control codes required to make your printer revert to its normal printing mode. This sequence should contain a form feed to position the printer at the top of the page. Most printers have a single "reset" code. Enter the data in hexadecimal. You will have to refer to your printer manual to determine the proper codes for your printer. The distributed reset seguence is "0C", which is form feed. &Lines^Per^Page Enter, in decimal, the number of lines to print before a form feed is issued. The number of lines per page depends upon your paper size and the printer setup. For example, enter 80 for 11" paper at 8 lines/inch, or 60 for 11" paper at 6 lines/inch. The distributed value is 60 lines per page. &Left^Margin Enter, in decimal, the size of the left margin for the printer listings. The distributed value is a left margin of 4 characters. &Type^of^Return^(RT^or^BLWP) The programs can exit in two ways. First, they can return to the loader (or cartridge) that loaded them. This is what is done if "RT" is specified. This is the normal return for the Editor/Assembler Cartridge Option 5 and the TI Writer Cartridge Option 3. Second, they can execute a "BLWP @0" which causes the 4A to reset. This is done if "BLWP" is specified. Some loaders are not prepared for programs to return (i.e. a popular RAM DISK LOADER), the BLWP return will suit these loaders. The distributed value is RT. \RUNNING^THE^GPL^DISASSEMBLER The RAG SOFTWARE GPL Disassembler is a standard E/A Option 5 assembler language program that is independent from any cartridge. It can be loaded and executed by any E/A Option 5 loader. You must have some means of loading the disassembler while the cartridge you wish to disassemble is inserted (i.e. a RAMDISK loader, a GRAM device loader). Once loaded, the Disassembler can process a batch of disassemblies. &Disassembler^Prompts The GPL Disassembler will prompt you for the symbol file name and the output file name. When a disassembley is completed, the Disassembler will ask if you want to disassemble another program. Note that all device/file names are specified in the usual form. If during prompting you wish to restart from the beginning, simply press BACK. If no output file name is given, the default output file specified during installation will be used. If the output file name is either "PIO..." or "RS232..." then the printer setup sequence, the printer reset sequence, the left margin and the number of lines per page will be used. If the output file is not one of these then after 500 lines are written to the output file it will be closed and the disassembler will prompt for another output file name. This limit of 500 lines per file allows the output to be easily editted. Note that the disassembler does not handle the error caused when a disk fills up. You must insure there is sufficient space on the output disks. A 500 line file uses 45 to 48 sectors so that a single sided disk can hold 7 full output files. Disassembly is a three step process. During the first step the symbol file is read and any errors in the disassembly statements are diagnosed. If errors are found you are given a chance to terminate disassembly before steps 2 and 3 are done. During step two the disassembly is done with no output in order to define any required GROM/GRAM addresses. Step three is disassembly with output. The current GROM/GRAM addresss is displayed in the upper left corner of the screen during steps 2 and 3. \THE^SYMBOL^FILE The symbol file contains statements which control the GPL Disassembler. All statements may be entered in either upper, lower or mixed case. There are three classes of statements each of which is described below. The symbol file is created with any text editor. The statements are coded with the keyword identifying the statement beginning in column one and followed by at least one blank. The operand field is terminated by the end of the statement or by a blank. The "symbols" you define are specified as 1 to 6 characters the first of which must be a letter (to be acceptable to the GPL assembler). The addresses you specify are given in hexadecimal notation and may be specified with or without the ">" usually used to indicate hexadecimal notation. &Definition^of^Symbols These statements allow you to specify symbolic names to be used in the disassembled code to replace hexadecimal addresses. There are three kinds of symbols each defined by its own statement. .sp;in+5 GROM^^address,symbol .sp;in+0 defines a "symbol" to be used for a GROM/GRAM "address". .sp;in+5 CPU^^^address,symbol .sp;in+0 defines a "symbol" to be used for a CPU RAM/ROM "address". .sp;in+5 VDP^^^address,symbol .sp;in+0 defines a "symbol" to be used for a VPD RAM "address". During disassembly, if no symbol has been specified then hexadecimal addresses are used for CPU and VDP addresses, and symbols of the form "Gxxxx" are defined for GROM/GRAM addresses where "xxxx" is the hexadecimal address. &Disassembly^Specification The disassembly specification statements tell the disassembler what and how to disassemble the GPL program. Disassembly begins with the lowest address specified and continues sequentially to the end. Note that the parameters following a COINC instruction are handled properly by the disassembler. .sp;in+5 ADDR^^address[,symbol] .sp;in+0 specifies that a data area that contains 2 byte GROM/GRAM addresses begins at "address", and optionally specifies a "symbol" for that GROM/GRAM address. .sp;in+5 CALL^^address,fetch-count .sp;in+0 specifies that GPL CALL statements to "address" are followed by "fetch-count" bytes of inline parameters. .sp;in+5 CODE^^address[,symbol] .sp;in+0 specifies that GPL code begins at "address", and optionally specifies a "symbol" for that GROM/GRAM address. .sp;in+5 DATA^^address[,symbol] .sp;in+0 specifies that a data area begins at "address", and optionally specifies a "symbol" for that GROM/GRAM address. .sp;in+5 END^^^address .sp;in+0 specifies that disassembly is to end at "address". .sp;in+5 SKIP^^address[,symbol] .sp;in+0 specifies an area at "address" that is not to be decoded, and optionally specifies a "symbol" for that GROM/GRAM address. This area will be output as a BSS assembler directive. .sp;in+5 STRI^^address[,symbol] .sp;in+0 specifies that a data area containing strings begins at "address", and optionally specifies a "symbol" for that GROM/GRAM address. Strings are defined as a length byte followed by text. If the text contains one or more non-printable characters then the string will be output in hexadecimal. .sp;in+5 TEXT^^address[,symbol] .sp;in+0 specifies that a data area that contains text begins at "address", and optionally specifies a "symbol" for that GROM/GRAM address. If the text contains one or more non-printable characters then the text will be output in hexadecimal. &Disassembly^Notes These statements allow you to annotate the disassembly output. .sp;in+5 NOTE^^address,'any text' .sp;in+0 specifies that a comment statement containing the comment "any text" is to be inserted into the disassembly output at the GROM/GRAM "address". .sp;in+5 TITL^^address,'any text' .sp;in+0 specifies that a TITL statement containing the operand "any text" is to be inserted into the disassembly output at the GROM/GRAM "address". &Statement^Placement The statements in the symbol file can be in any order. They are sorted into address order by the disassembler. The disassembly area begins at the lowest address specified on a CODE, DATA, STRI, TEXT or ADDR statement and continues sequentally up to the highest address or to that specified on the END statement. If the address specified on a TITL or NOTE statement is not within the disassembled area the statements are ignored. Symbols specified on GROM statements that are within the disassembly area are output as labels on GPL statements whether the symbol is referenced or not. Symbols that are not within the disassembly area are output at the end as EQU statments only if they are referenced by some disassembled GPL statement. Symbols specified on CPU and VDP statements are output at the end as EQU statements only if they are used as an operand of some disassembled GPL statement. .sp2 \DISASSEMBLING^A^GPL^PROGRAM Disassembling a GPL program is an inexact process because it is impossible for the disassembler to distinguish data from instructions. You must provide the intelligence that the disassembler lacks. You do this via the "symbol" file that tells the disassembler how and what to disassemble. The disassembly process is an iterative process. You begin with a hex dump of the GROM/GRAM that contains the GPL program. From your knowledge of the general structure of GROMs and the information in the dump you identify the first instructions to disassemble and possibly some data areas. Then you begin building the symbol file to direct the disassembler. Usually, the first few disassemblies are output to the printer. After inspecting the printer output, and understanding more of the function of the GPL program, you modify and/or add to the symbol file so that on the next iteration a "better" disassembly is generated. \EXTENDING^A^DISASSEMBLY Three major features of many GPL programs can be used to "extend" the disassembly of them. A disassembly can be extended by disassembling more of the program or by adding more "meaningful" names to data or code areas. The first major feature that can be used is that many programs (or sections of programs) consist of a section of "mainline" code which CALLs subroutines. Quite a few of these subroutines will be short and easily understood. When you do identify the function of a subroutine you can assign it a meaningful name for the next disassembly iteration. Often when meaningful names are assigned to the smaller subroutines then the function of larger routines that call them then become apparent, and these larger routines can in turn be assigned meaningful names. The second feature that can aid in understanding a program is that many of them present selection menus. In the code you generally see a SCAN of the keyboard followed by range checking and then a CASE statement to do the selection. The addresses in the branches following the CASE can then be assigned meaningful names by knowing what the selection menu says. The third useful feature is that most programs issue prompting, information or diagnostic messages. The messages can usually be spotted in a GRAM dump (although sometimes the text has the "BASIC bias" of >60 already added to it). You can trace back from the message to the code that displays it and assign meaningful names both to the messages and the code. The disassembler output is also structured to aid in further iterations. At the end of the disassembly output a series of EQU statements is generated for all GRAM address used but not defined within the disassembled area. This list can be used to identify areas of GRAM that need to be disassembled. As a further aid, the two files, "RAMPAD" and "GROM0" on the disassembler distribution disk can be included as part of your symbol file. "RAMPAD" assigns names to parts of the RAMPAD at address >8300. These areas are used for the same purpose by most GPL programs and are mostly areas that have special meaning in the GROM operating system. "GROM0" assigns names to the defined GPL subroutines in GROM 0. \PITFALLS^IN^DISASSEMBLING There are several things that can throw you and the disassembler off the track. Some of these are identified below. The main problem is that almost every bit pattern is a valid GPL operation code so that the disassembler cannot distinguish between instructions and data. To compound this problem, many subroutines have parameter lists that follow the CALL statement that invokes them. These parameters are obtained by the FETCH statement. Unless the disassembler CALL, DATA, TEXT or ADDR statements are used to identify the parameters the disassembler will interpret the parameters as instructions and generate meaningless sequences of instructions. All data is valid for FMT suboperands so that if the disassembler accidentally gets into a FMT operation it is unlikely to get back out of it. The disassembler will sometimes terminate a FMT with a comment saying that it encountered a disassembler CODE statement while doing the FMT suboperands. It is a good policy to use the disassembler CODE statement to assign labels to instructions that are being disassembled rather than the GROM statement for this reason. You can cause the disassembler to incorrectly disassemble a GPL program by specifying a CODE statement with an address that overlaps a previously disassembled instruction or string area. For example, suppose a GRAM contains the following data: .sp;in+10 >6000^^06 86 50 .sp;in+0 and that the symbol file contains: .sp;in+10 CODE^^^>6000,GOOD CODE^^^>6001,BAD .sp;in+0 Then the disassembler would generate: .SP;IN+10 GOOD^^^CALL^^G8650 BAD^^^^CLR^^^@>8350 .SP;IN+0 which if assembled would produce the code: .sp;in+10 >6000^^06 86 50 >6003^^86 50 .IN+0;sp2;CP5 \RUNNING^THE^GROM^DUMP^UTILITY The GROM Dump Utility, RAGGDU, gives you a hexadecimal listing of sections of GROM/GRAM memory. Dumping the contents of one or more GROMs containing a GPL program is usually the first step in disassembling the program. The GROM Dump Utility is a standard E/A Option 5 assembler language program that can be loaded and run using any E/A Option 5 loader. The program is independent from the means of loading it. The dump utility will prompt you for the output file name, a page heading for the output file, and the starting and ending GROM addresses of the area you want dumped. The Dump Utility will continue prompting for starting and ending addresses until BACK (FCTN 9) is pressed in response to the "starting address" prompt, then the program will close the output file and give you the option of restarting from the beginning. The GROM addresses are entered as 1 to 4 hexadecimal digits. Note that the beginning address is truncated to a multiple of 16 and that all output lines are complete lines even though ending address would cause a short line. \DIAGNOSING^DISASSEMBLER^FAILURES Every attempt has been made to insure that the Disassembler has no bugs, however, in every complex program the possibility of bugs always exists. There are two possible type of failures. .SP;LM +5;IN -3 1.^The Disassembler completes normally, but some instruction or data was disassembled incorrectly. 2.^The Disassembler did not complete and/or the system required rebooting. .LM-5;IN+0;SP In both cases, the first thing to do is to correct all errors that were found by the Disassembler. In the first case above, you should be sure that you understand what should be disassembled. In all cases any bugs discovered as well as any usability problems should be reported to: .SP;IN+15 RAG SOFTWARE R.^A.^Green 1032 Chantenay Dr. Gloucester, Ont. CANADA^^^^K1C 2K9 .IN+0;SP If possible, a disk with the symbol file and a copy of the GRAM that can not be disassembled should be sent. This will make finding the bug easier. If a disk is sent, the material on the disk will &only be used for finding the bug and will be returned with a corrected version of the disassembler.