ProLink (TM) Microsoft Compatible Linkage Editor Copyright (C) 1985 by NightOwl Software, Inc. ProLink software and User's Guide written by Ronald G. Fowler Prolink Table of Contents Copyright, trademarks, warranty, and license........ 2 1. Overview ........................................... 4 2. Getting started .................................... 5 2.1 Command Lines.................................... 5 2.2 Syntax Conventions .............................. 6 2.3 Expressions and Symbols.......................... 6 2.4 Filenames ....................................... 7 3. Basic linkage editing .............................. 8 3.1 The ORIGIN command .............................. 8 3.2 The LINK command ................................ 8 3.3 The SEARCH command .............................. 9 3.4 Automatic library search......................... 9 3.5 The LOAD command ................................ 10 3.6 Starting over: the RESET command ................ 10 3.7 Giving up entirely: the ABORT command ........... 10 3.8 Naming the output file: the OUTFIL command ...... 11 3.9 Closing the edit: EXIT and CLOSE commands ....... 11 4. Automating the process: the READ command ........... 13 4.1 Comments in READ files .......................... 13 5. ProLink query commands ............................. 15 5.1 The HELP command ................................ 15 5.2 The STAT command ................................ 15 5.3 The EVAL command ................................ 15 5.4 The DUMP command ................................ 15 6. Symbols and ProLink ................................ 17 6.1 The SYMFIL command .............................. 17 6.2 The SYMBOL command .............................. 17 6.3 Undefined symbols: the UNDEF command ............ 17 6.4 Multiply defined symbols: the MULDEF command .... 18 6.5 Unreferenced symbols: the UNREF command ......... 18 6.6 Sorting the symbols: the SORT command ........... 18 6.7 The DEFINE and REDEF commands ................... 18 6.8 The PURGE command ............................... 19 6.9 The WRSYM command ............................... 19 6.10 Special symbols ................................. 20 6.10.1 $MEMRY, ?MEMRY ............................. 20 6.10.2 ?BEG?, ?END? ............................... 20 6.11 Re-defineable symbols ........................... 21 7. Advanced applications .............................. 22 7.1 Modifying the image: the PATCH command .......... 22 7.2 Ignoring undefined externals: the $X option ..... 23 7.2.1 The SEED command ........................... 24 7.3 Modular add-ons: the RESOLVE command ............ 24 7.4 The SETLOC command .............................. 27 8. ProLink error messages ............................. 28 Appendices: A1. Appendix 1: the LINKMAP rel-file dump utility ...... 29 A2. Appendix 2: Format of ProLink object files ......... 30 Copyright Notice ---------------- ProLink software package and User's Guide are copyright (C) 1985 by NightOwl Software, Inc. All Rights reserved worldwide. No part of this publication or the ProLink software package may be reproduced, transcribed, transmitted, stored in any retrieval system, or translated into any language without the express written consent of NightOwl Software, Inc., Route 1 Box 7, Fort Atkinson, WI. Trademark Notice ---------------- "CP/M", "RMAC", "LINK-80" and "DDT" are trademarks of Digital Research, Pacific Grove, CA. "Macro-80" and "Microsoft" are trademarks of Microsoft Corporation. "Intel" is a trademark of Intel Corporation. "Zilog" and "Z80" are trademarks of Zilog, Inc. "ProLink" is a trademark of NightOwl Software, Inc. Warranty -------- NightOwl Software, Inc., makes no representations or warranties with respect to the contents of this User's Guide or the ProLink software package, and specifically disclaims any implied warran- ties of merchantability or fitness for a particular purpose. NightOwl Software, Inc. shall under no circumstances be liable for consequential damages or related expenses, even if it has been notified of the possibility of such damages. Some states do not allow the exclusion of implied warranties, so the above exclusion may not apply to you. This warranty gives you specific legal rights and you may also have other rights which vary from state to state. NightOwl software does warrant the diskette on which the software is furnished, to be free from defects in materials and workman- ship under normal use for a period of sixty (60) days from the date of delivery to you, as evidenced by a copy of your receipt. NightOwl Software's entire liability and your exclusive remedy shall be the replacement of any diskette(s) not meeting NightOwl Software's limited warranty. NightOwl Software reserves the right to revise this publication and the ProLink software from time to time without obligation to notify any person of such revisions. Single computer license ----------------------- The ProLink software package provided with this User's Guide is furnished under a license and may be used only in accordance with the license terms described below. Your use of the software or this User's Guide shall be deemed to constitute your acceptance of the terms of this license. 1) You may use ProLink only on a single computer or CPU. 2) You may copy ProLink only for backup or modification purposes in support of your use of ProLink on a single computer or CPU. 3) You may not remove any copyright, trademark or other notice or product identification from your ProLink diskette and you must reproduce and include any such notice or product identi- fication on any copy of ProLink. 1. Overview ProLink is a Microsoft-format linkage editor for computers employing the Z80 microprocessor and running CP/M and compatible operating systems. ProLink is a command-driven linker, and provides an interactive environment for the generation of object program modules. In addition to the basic link and library search commands, ProLink provides an array of commands for symbol file control, object module placement, "hot-patching" the object image, automatic operation from batch execution files, "add-on" modules, and more. ProLink is an in-memory single pass linkage editor, and is thus quite fast; it is intended strictly for assembly-language modules (rather than "high-level" compiler output, which is NOT supported by ProLink) and supports all Microsoft-format relocation bases. 2. Getting Started This section deals with the "basics" of operating ProLink: commands and command lines, syntax conventions employed in this User's Guide, expressions and symbols, and filenames. 2.1 Command lines ----------------------------------------------------------------- ProLink takes its input entirely from command lines; each command line represents a particular task (command) that you want ProLink to execute. For example, to link together the files BASE.REL and SUPPORT.REL, the line LINK BASE,SUPPORT might be used. The command ("LINK", always the first "word" of a command line) tells Prolink what you want done, and BASE and SUPPORT are arguments to the command. Arguments generally tell Prolink what files (or symbols, or numbers) that the command will work with, but occasionally they MODIFY what the command does, and hence might sometimes be called "optional arguments". Note that "arguments" and "optional arguments" can sometimes be mixed on a single command line. When ProLink is initially invoked (by typing PROLINK at the CP/M command prompt), you may optionally specify a command line to be executed when ProLink loads. For example, from CP/M command level, you might type PROLINK LINK FOO;EXIT Note that everything after "PROLINK" is an input command line to ProLink, and is executed just as if you had typed it at the ProLink command prompt. All ProLink commands are valid from the CP/M command line; when any such command line is completed (or if no command line is entered) you'll see the ProLink input prompt (the '*' character), which is ProLink's signal that it's ready to accept another line of input. (Note that an "EXIT" command in the input stream, as is given in the example above, will cause ProLink to write its output file and return immediately to CP/M, without prompting you for any additional input). As you can see from the example above, ProLink accepts multiple commands on a line. Simply separate them with a semicolon, and ProLink will execute them logically as if they had actually been typed in separately. Note that the maximum length of a ProLink command line is 128 characters, and this includes any multiple commands within a single physical line of input (note that a command line entered with ProLink from your operating system command level may have a smaller maximum -- for example, some versions of ZCPR allow only an 80 character input line. This does not change the maximum length that ProLink will accept at its command level, however). 2.2 Syntax Conventions ----------------------------------------------------------------- Throughout this User's Guide, we'll be using a common "shorthand" for describing each of ProLink's commands. These conventions are those commonly used in software documentation (in BASIC inter- preters, etc.). In general, argument types are enclosed in angle brackets; for example, a filename argument to the LINK command will be described as LINK . When using the command, don't type in the angle brackets; replace the text within the angle brackets with a real argument. Thus, an actual LINK command might be entered as LINK TESTPROG Similarly, square brackets will be used to denote optional items (again, don't type in the square brackets). To continue our LINK example, an optional second argument might be given in the syntax description as LINK [,] which means that an optional second filename is allowed, if prefixed by a comma. An elipsis ("...") indicates that any number of arguments are allowed (generally limited only by the maximum length of a com- mand line, which is 128 characters). Thus, the full syntax description for LINK is LINK [,] ... which indicates that more optional filenames may be entered. 2.3. Expressions and Symbols ----------------------------------------------------------------- Many ProLink commands take a numeric argument (i.e., an argument that evaluates as a number). Such an argument is called an expression, and is referred to as "" in syntax charts. ProLink expressions are integer numbers; the components (and the result of evaluation) are unsigned 16-bit integers. Valid op- erators are "+", "-", "*" and "/" (add, subtract, multiply, divide). Symbol names (from any linked modules already in mem- ory) may also be included. Thus, the following are legal ex- pressions: PATCH+3 NMEMPL/4 6*8+9 Note that the multiplication and division operators are evaluated first; hence, in the third example, the result is 57, not 102. The order of evaluation may be modified by placing parentheses' around the terms that are to be evaluated first. Thus, in the second example, we could have 6*(8+9) to get a result of 102. Parentheses may be nested to any reasonable level: ((NMEMPL+3)/(6+9)+1)/8 It is important to note that numeric constants are considered to be hexadecimal as a default. To avoid confusion with symbols, all constants beginning with letters 'A' to 'F' should be preceeded with a leading zero (thus, 0FFA1, not FFA1; the latter would be interpreted by ProLink as a symbol). You can specify a decimal number by preceeding the number with a pound sign ("#"); thus the constant 10 is 10 hex, or 16 decimal, while #10 is 10 decimal, or 0A hex. 2.4 Filenames ----------------------------------------------------------------- Generally, filenames used by ProLink are fully in accordance with the specifications for CP/M, with the following enhancement: Any file specification may be preceeded with a user number, as long as a colon separates the file name from the user spec- ification. This holds true whether or not a drive specification is also present (this is often called the "ZCPR style" naming convention). Thus the following are legal filenames: B3:OBJECT.REL C:MXO-SM13.HEX 3:SYSLIB.REL 3. Basic Linkage Editing This section deals with the minimal subset of ProLink commands needed to do simple program linking. This is the basic "core" of ProLink, and the commands detailed here are the ones you're most likely to use over and over. 3.1 The ORIGIN command ----------------------------------------------------------------- ORIGIN is used to set the beginning address of your output file. By setting an ORIGIN, you change the EXECUTION ADDRESS of the output code, but NOT its position in the output file (that is, the first byte of output still occupies the first position in the output file). If you don't specify an ORIGIN address, ProLink will default to 100H. You should be aware that ProLink's default origin will include a 3-byte jump field at 100H that is filled in with a jump to your program's entry point at linkage time. If you change the origin, ProLink will not generate this jump instruction, and the code segment (CSEG) of your first module must begin your program. Occasionally, you'll want to defeat this jump-field generation, even when loading programs at 100H (for example, Echelon's ZCPR3 utilities must start at exactly 100H, without the jump field). You can do this by explicitly setting the origin: ORIGIN 100 Note that the ORIGIN command cannot be used after any program loading has started (either with the LINK or LOAD commands). Once the load has started, the origin cannot be changed again until the currently-loaded file is either written out, or aborted (with the RESET command) 3.2 The LINK command ----------------------------------------------------------------- The most fundamental command of ProLink's set is the LINK command. Its syntax is: LINK [,] ... Thus, to link a single file (say, FOO.REL): LINK FOO (Note that the filetype, if not specified, defaults to REL). You can link several files with one LINK command: LINK FOO,MATHPAK,IOPACK,FORMAT Multiple link commands may be used instead, with the same result: LINK FOO LINK MATHPAK LINK IOPACK LINK FORMAT Note that all files entered as arguments to the LINK command are unconditionally linked into the object file, even if the subject files contain multiple modules. The LINK command will print the name of each module on the screen (in columnar format) as that module's linkage is completed, UNLESS you're linking from a READ file with the '$E' option active (see chapter 5 for more information on READ files). 3.3 The SEARCH command ----------------------------------------------------------------- The syntax for the SEARCH command is identical to that of the LINK command. The difference is that SEARCH treats the argument file(s) as libraries (i.e., collections of modules). Only those modules from the library files needed to satisfy unresolved references are actually linked into the file; the remainder are bypassed. Generally, you'll use the SEARCH command after one or more LINK commands, to "pull in" often-used routines from your library of code modules. For example, LINK DBSEARCH,FNPARS SEARCH SYSLIB In this example, DBSEARCH.REL and FNPARS.REL are unconditionally linked into the output file, and SYSLIB.REL is searched for needed subroutines to satisfy unresolved references from DBSEARCH and FNPARS. Although a detailed treatment of library files and their use is outside the scope of this discussion, it should be noted that library files can be constructed from the librarian supplied with your assembler (LIB-80 with Microsoft's MACRO-80 assembler, LIB with Digital Research's RMAC assembler). 3.4 Automatic library search ----------------------------------------------------------------- If your assembler supports a library-search pseudo-op (e.g., ".REQUEST" in Microsoft's MACRO-80 assembler), ProLink will automatically search all such requested libraries just prior to closing the output file (with the CLOSE or EXIT commands). To use this feature, the requested libraries must be available on the current drive, in the current user area. 3.5 The LOAD command ----------------------------------------------------------------- The LOAD command is used to load Intel "hex" format files, binary "image" files, or symbol files. Its syntax is as follows: LOAD [,] ... LOAD uses the filetype to distinguish "hex", binary, and symbol files. If you specify HEX as a filetype, LOAD will consider the file to be composed of Intel hex format records, and will load your file using the rules specified for that format. If you specify no filetype at all, LOAD will append "HEX" to the name as a filetype, and look for a hex file to load. If you specify "SYM" as a filetype, LOAD will load symbols into its internal symbol table. The file thus loaded must be in accordance with the MAC/SID symbol format, as generated by the MAC assembler (and many other commercial products). Note that symbol files written by ProLink are fully ompatible with this format; thus, SYM files written by ProLink may be safely reloaded in a later ProLink session, or used under Digital Research's SID or ZSID debuggers. Any filetype other than HEX or SYM (or blank) will be considered an "image" file. Typically these are COM files, but can also be overlay files, or even ASCII text files. Image files are loaded into memory starting at the current PC value (viewable with the STAT command, and changeable with the SETLOC command), and must fit in available memory Some LOAD examples: LOAD MEX112.COM,MXO-KP41 <-- Load MEX112.COM, overlay with KP41 hardware overlay LOAD MYPROG.SYM <-- Loads a symbol file LOAD DBSRCH <-- Loads DBSRCH.HEX 3.6 Starting over: the RESET command ----------------------------------------------------------------- During a linkage session, you might find that you want to start over for some reason. The RESET command will restore ProLink to its start-up state; any program currently being linked will be removed from memory, and ProLink's internal variables (including the default value of ORIGIN) will be reset. The RESET command takes no command line arguments. 3.7 Giving up entirely: the ABORT command ----------------------------------------------------------------- The ABORT command exits the current session, without writing a file or otherwise disturbing anything on the disk. The ABORT command takes no command line arguments. 3.8 Naming the output file: the OUTFIL command ----------------------------------------------------------------- The OUTFIL command is used to specify a name for your output file. Its syntax is as follows: OUTFIL The filename may contain a drive specification. If you omit the OUTFIL command, ProLink will build an output name using the name of your first input file: it will use the first eight characters of that name, stripping off the filetype (gen- erally "REL") and forming a filetype of "COM". Thus, if your linkage looked like this: LINK FILE1,FILE2 SEARCH SYSLIB ProLink would link FILE1.REL, FILE2.REL, search SYSLIB.REL, and write an output file named FILE1.COM. But if your program is actually a database searching utility, you might want to give it a more descriptive name: OUTFIL DBSEARCH or OUTFIL B:DBSEARCH 3.9 Closing the edit: EXIT and CLOSE commands ----------------------------------------------------------------- Up until this point, all of the commands we've looked at have to do with building the output file in memory. To actually write the output file, either the EXIT or CLOSE command is used. EXIT is the "normal" method of ending the linkage; it writes the output file, and exits to CP/M. CLOSE will write the output file in the same way, but, instead of exiting to CP/M, ProLink will do an automatic RESET command and return to command level. Thus, you're ready for another linkage session. The syntax is identical for CLOSE and EXIT, and is illustrated here for CLOSE: CLOSE [] The optional filename overrides any name that may have been specified with the OUTFIL command. Both EXIT and CLOSE will print a list of any unresolved symbols (if any remain unresolved), as well as a list of multiply-defined symbols (if multiply defined symbols exist). Following any such list, ProLink will print a one-line message containing the starting and ending addresses, followed by the size of the output file (in 256-byte pages). 4. Automating the process: the READ command Complex applications making full use of ProLink features will result in a lot of typing during the typical edit-assemble-link- debug cycle. In such circumstances, it is advisable to use an editor to make a file of ProLink commands, then use the READ command to execute these commands. The syntax of the READ command is as follows: READ [$E] ProLink will then take its input from the specified file. Note that, if no filetype is specified, ProLink will look for a file of type "LNK". Thus, you should create READ files with a "LNK" filetype. Normally, ProLink will not echo the command lines it is executing from a READ file. However, the "$E" option will override this, and each command will be displayed on your screen just prior to its execution (this is especially useful when "debugging" a READ file). A READ file may contain any valid ProLink command EXCEPT another READ command (i.e., READ files may not be nested). ProLink will abort a read-file in progress if an error is detected during the course of execution. 4.1 Comments in READ files ----------------------------------------------------------------- You can place a comment within a READ file (or at command level from the keyboard, for that matter) by placing a period (".") in the first character position of a line. Thus, the following lines are valid comments: . HARDB.LNK: generates Harris version of DB.COM . The following line should be omitted in final version The comment specifier may also be present as the first character of a multiple command line: LINK MAIN,SORT ;.include the SORT module SEARCH SYSLIB ;.look through SYSLIB for subroutines There are two special forms of comment lines that are interpreted by ProLink: .+ <-- turns command-echo on .- <-- turns command-echo off These command-line echo specifiers override any "$E" option given on the READ command line. 5. ProLink Query Commands ProLink provides a number of commands that may be used to query the system for various information. 5.1 The HELP command ----------------------------------------------------------------- HELP prints a list of available commands on the screen. Useful as a memory jogger, but it doesn't give any information about command syntax. You'll have to refer to the User's Guide for that. HELP does not take any command line arguments. 5.2 The STAT command ----------------------------------------------------------------- STAT may be used to display the status of the linkage at any particular time. STAT prints information such as output filename, symbol filename, state of the linkage, memory statistics, etc. STAT does not take any command line arguments. 5.3 The EVAL command ----------------------------------------------------------------- EVAL is a general-purpose expression evaluator. Its syntax is EVAL [,] ... EVAL is most useful for determining symbol values, but it can also come in handy for doing quick arithmetic calculations. EVAL prints its result both in hexadecimal and decimal (the decimal value is printed with a leading pound sign). 5.4 The DUMP command ----------------------------------------------------------------- DUMP displays memory from the image under construction, in the DDT-style combined hex and ASCII. The syntax for the DUMP command is DUMP [] [+][] If no start or end address is entered, DUMP will display from the previous ending DUMP address (or the program origin if no previous DUMP has been performed) for a length of 128 bytes. If a start-address is entered without an ending address, 128 bytes will be displayed. The ending address prefixed with the optional '+' specifier causes the end-address to be considered a count of bytes to display, rather than an actual ending address. Note that "D" is a shorthand synonym for "DUMP". 6. Symbols and ProLink Symbols are an integral part of the linkage process, and ProLink provides a number of commands for manipulating symbols and symbol files. 6.1 The SYMFIL command ----------------------------------------------------------------- SYMFIL is used to specify a symbol file name, to turn on the symbol file (ProLink, as a default, does not write a symbol file), and to control the "X" symbol option. Its syntax is SYMFIL [] [$ON] [$OFF] [$X] At least one of the four optional arguments must be present, and no more than one of the "$" options may be present in a single command line. The field is used to change the name of the symbol file written by ProLink; just specifying the name, however, does not cause ProLink to write a symbol file: the "$ON" option must be used for this. If no filespec is entered, ProLink will generate its own name, using the first eight characters of the output file name, with "SYM" appended as the filetype. The "$X" option toggles the x-symbol option on and off; for more information on the x-symbol option, see section 7.2. Some examples of the SYMFIL command are: SYMFIL DBSEARCH.SYM $ON <-- set name, enable symbol file SYMFIL $X <-- enable x-symbol option SYMFIL $ON <-- enable symfil, use default filename 6.2 The SYMBOL command ----------------------------------------------------------------- The SYMBOL command is used to display the current symbol table on the terminal. Note that "SYMBOLS" is a synonym for "SYMBOL", and that the command takes no command line arguments. 6.3 Undefined symbols: the UNDEF command ----------------------------------------------------------------- The UNDEF command may be used at any time to display all undefined symbols on the terminal. An automatic UNDEF is done when the output file is written, if any undefined symbols exist. UNDEF takes no command line arguments. 6.4 Multiply defined symbols: the MULDEF command ----------------------------------------------------------------- The MULDEF command is used to display any multiply-defined symbols on the terminal. An automatic MULDEF is done when the output file is written, if any multiply-defined symbols exist. MULDEF takes no command line arguments. 6.5 Unreferenced symbols: the UNREF command ----------------------------------------------------------------- The UNREF command displays on the terminal a list of symbols that are defined, but not referenced. This is useful for detecting blocks of code that are no longer referenced globally (if they are not referenced in the module in which they are defined, they may then be safely deleted). Such symbols, if referenced in their local modules, may have their global attribute removed. UNREF takes no command line arguments. 6.6 Sorting the symbols: the SORT command ----------------------------------------------------------------- As a default, ProLink does not sort its symbols, but writes them in the order in which they are encountered. Some symbolic debuggers require a sorted symbol table, and you can use the SORT command to accomplish this. SORT uses a simple bubble sort, and may take long periods of time with large symbol tables. You may safely stop the sort at any time with a control-C from the keyboard, without damage to the symbol table. SORT takes no command line options. The DEFINE and REDEF commands ----------------------------------------------------------------- Occasionally, you might find the need to add your own symbols, or redefine existing ones. The DEFINE and REDEF commands provide this capability. Both commands take the same command line syntax, which we'll specify only for DEFINE, as follows: DEFINE The DEFINE command requires that the symbol-name specified be either non-existant, or non-defined; the latter implies that the symbol can exist in the table by virtue of previous references by other modules, but that it must not yet be defined. If IS defined, the DEFINE command will draw an error message, and the symbol's value will not be changed. Note that if no references exist, DEFINE will create a new entry for the symbol, and then define it with a value specified by . The REDEF command requires that the argument symbol-name be an existing, defined symbol; if it is non-existant (or not defined), the REDEF command cause an error message, but no new symbol will be created. If is found, the old value will be lost, and the new value (specified by ) will be substituted in its place. 6.8 The PURGE command ----------------------------------------------------------------- The PURGE command is used to delete symbols from the symbol table. Its syntax is PURGE [,] ... PURGE will delete each of the symbols from the list, including any references to the symbol (i.e., if you PURGE a symbol, you remove not only its definition, but any references ProLink has formed for the symbol. So unless you load new modules with references to a purged symbol AFTER a purge, ProLink will not issue a "not-defined" diagnostic when the output file is written). PURGE will print a "not-found" message for any symbols in the list that it can't locate; this will not, however, stop the PURGE command: it will continue with any remaining symbols in the list. 6.9 The WRSYM command ----------------------------------------------------------------- The WRSYM command writes out the current symbol table to a disk file. It takes an optional filename argument: WRSYM [] Note that if a spec is present, this name overrides any filename specified by the SYMFIL command (which is used if is omitted). Also, a filename specified to WRSYM changes any SYMFIL-specified name; thus, the following sequence: SYMFIL FOO.SYM $ON WRSYM FUB.SYM CLOSE will never write FOO.SYM, but will instead write FUB.SYM from the WRSYM command, then delete and re-write FUB.SYM when the CLOSE command is issued. 6.10 Special symbols ----------------------------------------------------------------- ProLink supports several special symbols, that may be freely referenced in object modules. All four are for purposes of defining limits in the completed output file: the first pair are for L80 and LINK80 compatiblity, and the second pair are a more "kosher" way of referencing the output file boundaries. 6.10.1 $MEMRY and ?MEMRY ----------------------------------------------------------------- $MEMRY is a special variable name recognized by most Microsoft- compatible linkers, and must be a 2-byte storage area within any of the linked object modules. On encountering this symbol, ProLink will insert the first free memory address at this word location. Thus, a "main" module may include PUBLIC $MEMRY .... $MEMRY: DS 2 The base address of free memory is then available to all object modules by performing LHLD $MEMRY The same discussion relates to the symbol '?MEMRY'; this symbol is used by the Digital Research LINK-80 linker (and DR's PL/I language compilers) instead of $MEMRY. 6.10.2 ?BEG? and ?END? ----------------------------------------------------------------- While the above technique is useful for determining the location of free memory, we feel it is flawed in design, because it requires the linker to modify the binary image of the output file. We felt that a technique more consistant with the use of a linkage editor was required, so ProLink supports two special symbols that are defined by ProLink (and so should be used in your object modules only to determine memory limits). The symbol '?BEG?' contains the base address of the linked output image; '?END?' contains the ending address (which is actually the base of the "free" area). Thus, rather than loading a word value from memory to locate the base of the free area (as is done with $MEMRY and ?MEMRY), you simply reference ?END?. For example, EXTRN ?END?,?BEG? LXI H,?END? LXI D,?BEG? In this example, HL obtains the end of linked program, and DE the beginning. 6.11 Re-defineable symbols ----------------------------------------------------------------- ProLink supports a special kind of symbol, called a re-defineable symbol. Such a symbol may be defined more than once, and each succeeding definition definition will map to a unique symbol. Re-defineable symbols always end with the special character '@'; the first definition of such a symbol maps the '@' character to the character 'A', the second to 'B', and so on. This lets you have multiple (and likely, similar) modules, each with an identical entry name, say "TRMDR@" (one might be for an ADM3A, another for a Hazeltine 1500, etc). The first module encountered with such a name will be redefined by ProLink to have the name "TRMDRA", the second, "TRMDRB", etc. Each module might have an initialization entry point with a re-defineable symbol; thus "TINIT@" would be re-defined by ProLink as TINITA, TINITB, etc. In this example, you could add on as many terminal drivers as you like, simply by including them in your LINK command list. You can reference these symbols from within other modules simply by referencing them with their re-mapped name; this is especially useful when used with ProLink's RESOLVE command, which lets you reference symbols freely, without worrying about whether or not they actually exist. To continue our example, let's say that your mainline code module has a mass-initialization section, which is responsible for initializing every other module in the program; it contains a routine with a global name of UNDF, which simply returns (intended for use with the command "RESOLVE UNDF"). Your initialization section might look like this: EXTRN TINITA,TINITB,TINITC,TINITD ; CALL TINITA ;initialize all possible terminal dvrs CALL TINITB CALL TINITC CALL TINITD RET If your LINK command list then contains only two terminal driver modules (AND you've issued a "RESOLVE UNDF" command), the actual object code generated by ProLink would look like this: CALL TINITA CALL TINITA CALL UNDF CALL UNDF RET 7. Advanced Applications 7.1 Modifying the image: the PATCH command ----------------------------------------------------------------- Once your program is loaded, and resident in ProLink's memory, you can make changes to the generated image by using the PATCH command. The syntax of the PATCH command is as follows: PATCH []=[,] ... The specifies where to begin patching the image; usually, this expression will be given relative to a global symbol name (e.g., CMDTBL+3). is NOT optional on the first PATCH command of a session; after that, the PATCH command will remember where the last patch ended, and continue patching at the next successive location (unless a new address is specified by NOT omitting . Following the requisite "equals" sign is the list of patch values. A patch-value may be either a numeric expression or a string value. Numeric expressions are generally considered to be byte-values; thus, the following PATCH command will plug byte values into successive locations: PATCH SKWTBL=1,3,5,7,9,2,4,6,8,0A If the numeric expression resolves to a value greater than 255, however, PATCH will treat the value as a WORD value: PATCH DISTBL=DUMPCM,LISTCM,LISTCM+1 Generally, you can freely mix byte and word values, as long as there is no ambiguity in meaning: PATCH CMDTBL=8,BACKSP,9,TAB,13,CRLF,10,LF If you're patching word values, and the values are less than 256 (and thus, would otherwise by considered byte values by ProLink), you can enclose them in square brackets to force ProLink to treat them as words: PATCH DSPTBL=DUMPCM,[0],LISTCM,[5],LISTCM+1,[8] ASCII strings may be specified as patch-values, just by enclosing them in double-quotes: PATCH SOMESG="Copyright, 1985 by NightOwl Software, Inc." Again, byte expressions, word expressions, and strings may be freely intermixed: PATCH CMDTBL="DUMP",DUMPCM,"GOTO",GOTOCM,0 PATCH SOMESG="Version 1.0",0,NXTMSG When patching long strings, you can improve clarity in a READ file by taking advantage of the fact that the patch-address is optional after the first PATCH command. For example, PATCH SOMESG="ProLink Version 1.0",0D,0A PATCH ="Copyright (C) 1985 by NightOwl Software, Inc.",0 Generally, you should use the PATCH command only after all the object modules have been loaded, and all global symbols are fully resolved. The reason for this is that symbol references are maintained by ProLink througout its memory image of your program as linked lists. Prior to patching any values, PATCH insures that all of these references are resolved, and that all linked lists are reduced to their final values. In the case of undefined symbols, however, these lists cannot be reduced (since the symbols may be later resolved with another LINK or SEARCH command), and thus PATCH must leave these lists in memory. If you patch one of these references and then later issue a LINK or SEARCH command that resolves such a symbol reference, unexpected results may occur. 7.2 Ignoring undefined externals: the $X option ----------------------------------------------------------------- ProLink provides a feature that can be useful in disassembling REL modules. This feature can be invoked by specifying the "$X" option to the SYMFIL command (eg, SYMFIL $X or SYMFIL FOO.SYM $X) anytime during the linkage editing session. The "X" option status is displayed by the STAT command. Here's how it works: when your program is written to disk (with either the EXIT or the CLOSE command), and its symbol file is being generated, ProLink will force-define each undefined exter- nal reference, and give it a unique value known as the SEED value (see the SEED command for more information on the seed value). Each such forced definition will increment the seed value by one; thus all unresolved externals become resolved to unique values. When the symbol file is written to the disk, these force-resolved symbols are written with a pound-sign appended to the name. Now typically, the output and symbol files will be used as input to a disassembler (we highly recommend the public-domain DASM dis- assembler for this use); when your disassembler writes its source-code file, it's a simple matter to locate these special symbols with your text editor, remove the '#' character from the end of the name, and declare the symbol as external with an EXTRN statement. You should be aware that this technique breaks down when the module being disassembled contains an "external plus offset" type of reference. For example, EXTRN DECOUT ... CALL DECOUT+1 will generate such a reference. These references will not resolve uniquely with the $X option. You can, however, find such references with the LINKMAP utility (provided with ProLink), and make the fixes manually with a text editor. 7.2.1 The SEED command ----------------------------------------------------------------- Generally, the SEED value used with the 'X' option of the SYMFIL command (see description in the preceeding section) is set to the value of the symbol ?END? plus one. You can use the SEED com- mand, however, to provide your own starting SEED value. The syntax of the SEED command is as follows: SEED where is the initial value you want to use for seed. 7.3 Modular add-ons: the RESOLVE command ----------------------------------------------------------------- ProLink supports a modular programming contruct that, while it must be used with great care, encourages the use of "add-on" code blocks that may be added or removed at will, and thus produce custom or specialized versions of your programs, without the cumbersome and error-prone conditional assembly techniques that have traditionally been used for this purpose. This construct is embodied in the RESOLVE command. First, the syntax of the RESOLVE command: RESOLVE Basicly, the RESOLVE command specifies a symbol that is used to resolve ALL otherwise undefined globals, at the conclusion of the linkage editing session. Let's take a look at how this may be useful. Let's say you're developing a terminal program, that allows your keyboard and terminal to act as a terminal for another computer, through a serial port (and perhaps through a modem and phone line). The simplest (and hence least expensive) version of your program simply reads incoming characters from the serial line, and displays them on your screen, and reads your keyboard for characters and sends them out the modem. Now let's say that you want to develop separate but succeedingly more capable (and probably, more expensive) versions of your program, with the additional capabilities of logging the incoming data to a disk file and echoing these characters on the printer. Thus, there can be four versions of your program: Terminal program Terminal program with printer echo Terminal program with disk-file logging Terminal program with printer echo and disk-file logging Using traditional techniques, you'd likely generate a single source file, with conditional assembly to generate the necessary code. The mainline code might look something like this: TERMLOOP: CALL SERVICE$KEYBOARD ;read kbd, if char, send out CALL SERVICE$MODEM ;get char to A unless cy=clr JNC TERMLOOP ;jump if no char CALL CHROUT ;display character IF PRECHO ;maybe echo on printer CALL LISTOUT ;list output ENDIF IF DISKFILE ;mabe echo to disk file CALL DISKOUT ;disk output ENDIF JMP TERMLOOP To create any of the four versions requires that the source file be edited to set the proper equates, the re-assembled and relinked. With ProLink, however, only the linkage process must be repeated. Typically, you'd unconditionally call LISTOUT and DISKOUT (after declaring them as externals): EXTRN LISTOUT,DISKOUT ... CALL LISTOUT CALL DISKOUT JMP TERMLOOP You'd also provide a routine (in your mainline module, most likely) that simply returns: PUBLIC UNDF UNDF: RET Then, with the DISKOUT routine contained in a module named DISK.REL,and the LISTOUT routine contained in LISTOUT.REL, you can generate custom versions with just a few simple ProLink commands. For example, the full blown terminal program: RESOLVE UNDF ;.force-resolve undeclared externals LINK TERMINAL,DISK,LISTOUT ;.link the three modules (actually, the RESOLVE command is not actually needed in this first example, since all externals to TERMINAL.REL are present). To generate only the list-echo version: RESOLVE UNDF ;.force-resolve undeclared externals LINK TERMINAL,DISK ;.link only mainline and disk code Note that in the latter example, the call to LISTOUT (which is an undefined symbol, since the LIST.REL module, in which it is defined, is not included in the linkage list) resolves to a call to UNDF, which harmlessly returns. You can redesign the UNDF routine to pass back some information to the caller: UNDF: STC RET Thus, a call to an external that isn't defined might be considered to have failed if the caller gets a carry back: CALL LISTOUT JC NOLIST$PRESENT A better way to determine if an external routine is actually present might be LXI H,LISTOUT UNDTST: LXI D,UNDF MOV A,E SUB L MOV A,D SBB H STC RZ CMC RET Note the use of the entry point UNDTST ... it's an example of a routine that might be called (with an external in HL) to determine if an external routine is actually present. This example code would return carry=1 if the routine is absent. These have been rather simple examples of the kind of use that may be made of the RESOLVE command ... the possible applications are limited only by your imagination. We should note, however, before we close this discussion, that the RESOLVE command should only be used after your code design is complete; it's very easy to lose an external that MUST be present when this command is used. Further, you should avoid STORING into an external location, unless there is NO chance that the ex- ternal might be undefined (since the stored values would destroy your UNDF routine). 7.4 The SETLOC command ----------------------------------------------------------------- The SETLOC command is used to change the value of the location counter. The syntax of SETLOC is SETLOC Generally, the location counter should be considered the "next" load address; at start-up, its value is the same as ORIGIN (if you specified an origin; if not, the default origin is 100H, but the location counter is set to 103H, to leave room for the ProLink-generated jump to your program's entry point). After using one of the LINK, SEARCH or LOAD commands to load a module into memory, ProLink will move the location counter up to the first free memory cell AFTER the loaded module. The next LINK, SEARCH or LOAD command will then begin loading immediately after the first. Using the SETLOC command, however, you may freely change this "next-load" location. You might move it backward, to overload a new module in an area of an old. Or you can move it forward, creating a "hole" in the generated image. An example of how the former might be useful would be the following patch code, gen- erated totally by ProLink (most likely, as part of a READ file): LOAD MAINLINE,FPARSE ;.load our program modules DEFINE QQORIG ?END? ;.unlikely symbol name to hold end SETLOC ?END?+200 ;.move location counter up 200H SEARCH SYSLIB ;search our library for subrtns PATCH QQORIG=2A,MYSTAT ;install patch code PATCH =3E,01,C3,DISPAT PATCH RESET+2B=C3,QQORIG ;now place the patch inside prog From this example, you can see how we first loaded the program modules, then defined the free area as a special variable named "QQORIG". This saves the address of the "hole" (or patch area, in this application) into a specially defined variable. Then we used SETLOC to move the next load address up 200H bytes (to reserve plenty of room for patches), searched our library for needed subroutines, then installed the patch code in the "hole" we created and named QQORIG. Finally, we "spliced" a jump instruction to our patch area into the working code, 02BH bytes after the global named "RESET". You should be aware that this technique is not at all limited to things like code patches; in fact, one of the uses envisioned is dynamically built command-driven programs, using ProLink- created "command tables", and modularly constructed command handler modules. 8. ProLink Error Messages Most of the error messages generated by ProLink are quite self- explanatory (e.g., "disk full", "out of memory", etc.). However, a few are a bit cryptic in the interests of brevity, and will be described more fully in this section. "Format error in REL file" - the module you are linking doesn't appear to ProLink to be a Microsoft-compatible object module. Usually happens most often when your disk file has been trashed. "Second common larger" - ProLink is a one-pass linkage editor (as is Microsoft's L80); one of the consequences of the compact and "quick" single-pass linkage process is the fact that the first occurance of a COMMON area must be the largest, since ProLink allocates the space for a common area on its first occurance. If this rule isn't followed, and a second, larger definition of a named common area is encountered, ProLink will abort with this error message. "Unsupported relocation type in REL file" - this message will not usually occur unless you're loading an object module generated by certain compilers. As mentioned in the "overview" section, ProLink is an assembly-language-only tool, and leaves unsupported a small portion of the Microsoft relocatable format, normally used only by high-level language compilers. "Loading below program origin" - once an origin exists, no mod- ule should attempt to force code to load below that origin. Note that this can only be done in relocatable modules by code generated in the ASEG (absolute) location counter; HEX modules can draw this error, however, when they contain hex-load records that load below the established origin. "Internal Error" - you should NEVER see this one! If you do, and can duplicate the problem, please write down all pertinent details and forward them, with applicable code modules, to NightOwl Software, at the address listed in the opening pages of this User's Guide. Please call first to co-ordinate disk formats for any code modules you'll be supplying. Appendix 1: The LINKMAP rel-file dump utility LINKMAP is a simple utility to dump MicroSoft REL files to the console in a form similar to that of DUMP.COM, but with a DDT- like ASCII-display at the end of each line. In addition, LINKMAP displays the various other Microsoft REL data in a compact form. The syntax is simple: LINKMAP [] | | | | \ / Optional FILENAME should be a standard Microsoft-format REL file, and may be composed of multiple modules. If no filetype is specified, the type REL is assumed. If is entered, then LINKMAP will assume that the file is a library of modules, and will display only the specified module (someday, this syntax may be modified to allow a range of modules). LINKMAP buffers an entire module in memory before displaying it, so there is a noticeable delay when listing large modules. Notation: The following notational character set is used by LINKMAP to imply relocation base information: Blank ( ) : Absolute segment Single Quote (') : Code segment-relative Double Quote (") : Data segment-relative Excl. Mark (!) : Common-relative Appendix 2:Format of ProLink-compatible object files This section details the format of ProLink-compatible object files (commonly knows as the "Microsoft REL format"). This information will not be needed by most users, but is included here as a reference. For efficiency of storage, the Microsoft format consists of a bit stream; fields within the bit stream are not aligned on byte boundaries, except at the end of a module. There are two types of load fields: absolute and relocatable, indicated by the first bit of the field: if the first bit is 0, the succeeding eight bits are loaded as an absolute byte (at the "current" location counter - the current location counter is then incremented). If the first bit is 1, then the following two bits specify the TYPE of the relocatable field, as follows: 00 Special LINK field, described below 01 Code-relative: following 16 bits must load at the current location counter AFTER adding the base of the current code segment. 02 Data-relative: following 16 bits must load at the current location counter AFTER adding the base of the current data segment. 03 Common relative: following 16 bits load at the current location counter AFTER adding the base of the current common segment (as select by special rel field #1). The special fields (prefixed by the bit code 100) have: - a 4-bit control field (the "type" of the field) - An optional 'A' field (the "address" field) - An optional 'B' field (the "symbol" field) Thus, a SPECIAL link field might be represented as follows: 100 [] [] | | | | | | | | \ A field / \ B field / (4 bits) defines the type of the special field (defined below). is the 2-bit relocation base of the A-field value: 00 - The value is absolute (ASEG) 01 - The value is code-relative (CSEG) 02 - The value is data-relative (DSEG) 03 - The value is common-relative is the 16-bit value field, and must be biased by the relocation base in the field (0 if ASEG, code- base if CSEG, data-base if DSEG, current-common base if common-relative). is the 3-bit length of the symbol field; its value is the length of the succeeding symbol field is the symbol name, consisting of successive 8-bit values (characters) that comprise the symbol name. The length of is defined by . The field types are as follows: - items with a "B" field only: 0: Entry symbol: used for library search 1: Select common block: B field holds common name 2: Define module name: B field holds the name of the module 3: Library search B field has filename, linker appends REL 4: Extension link type not supported by ProLink - items with both an "A" and a "B" field: 5: Define common size 6: Chain external: "A" field is the head of a linked list, each node of which exists in the address field of an ex- ternal reference. "B" field is the name of the external symbol. 7: Define entry point: "A" field has address, "B" the name. - items with an "A" field only: 8: External minus offset: not supported by ProLink 9: External plus offset: the current location counter is an external reference that must be added to the "A" field. The name of the symbol referenced is contained in the "B" field. Since the reference is part of a linked list (of the chained external), the current location counter and the offset value (the "A" field) must be stored, and processing deferred, until all chains are filled in (at the conclu- sion of the linkage). 10: Define data segment size: size is the "A" field 11: Set location counter: to value of "A" field 12: Chain address: "A" field is the head of a linked list; all entries in the chain must be replaced with the current value of the location counter. 13: Define code segment size: size is the "A" field 14: End module (note this forces input to a byte boundary). - item with neither an "A" or "B" field: 15: End file The only known type of "extension" item (#4, above) is generally used only with the Microsoft COBOL compiler, and is thus not supported by ProLink. The "external minus offset" item, #8, is also used only by Microsoft language compilers; it, too is not supported by ProLink.