From 8b494f241f2abfc0f869ab42c1601ea5027d3477 Mon Sep 17 00:00:00 2001 From: Robert de Bath Date: Sun, 24 May 1998 18:43:39 +0200 Subject: Import dis88-pcix --- MANIFEST | 12 + Makefile | 45 ++ README | 91 ++++ dis.h | 203 +++++++ dis88.1 | 147 +++++ disfp.c | 157 ++++++ dishand.c | 1049 +++++++++++++++++++++++++++++++++++ dismain.c | 624 +++++++++++++++++++++ disrel.c | 28 + distabs.c | 708 ++++++++++++++++++++++++ part01 | 1448 ++++++++++++++++++++++++++++++++++++++++++++++++ part02 | 1812 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 12 files changed, 6324 insertions(+) create mode 100644 MANIFEST create mode 100644 Makefile create mode 100644 README create mode 100644 dis.h create mode 100644 dis88.1 create mode 100644 disfp.c create mode 100644 dishand.c create mode 100644 dismain.c create mode 100644 disrel.c create mode 100644 distabs.c create mode 100644 part01 create mode 100644 part02 diff --git a/MANIFEST b/MANIFEST new file mode 100644 index 0000000..f6b6e33 --- /dev/null +++ b/MANIFEST @@ -0,0 +1,12 @@ + File Name Archive # Description +----------------------------------------------------------- + MANIFEST 1 + Makefile 1 + README 1 + dis.h 1 + dis88.1 1 + disfp.c 1 + dishand.c 2 + dismain.c 1 + disrel.c 1 + distabs.c 2 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..c1352f0 --- /dev/null +++ b/Makefile @@ -0,0 +1,45 @@ +# @(#) Makefile, Ver. 2.1 created 00:00:00 87/09/01 +# Makefile for 8088 symbolic disassembler + +# Copyright (C) 1987 G. M. Harding, all rights reserved. +# Permission to copy and redistribute is hereby granted, +# provided full source code, with all copyright notices, +# accompanies any redistribution. + +# This Makefile automates the process of compiling and linking +# a symbolic object-file disassembler program for the Intel +# 8088 CPU. Relatively machine-independent code is contained in +# the file dismain.c; lookup tables and handler routines, which +# are by their nature machine-specific, are contained in two +# files named distabs.c and dishand.c, respectively. (A third +# machine-specific file, disfp.c, contains handler routines for +# floating-point coprocessor opcodes.) A header file, dis.h, +# attempts to mediate between the machine-specific and machine- +# independent portions of the code. An attempt has been made to +# isolate machine dependencies and to deal with them in fairly +# straightforward ways. Thus, it should be possible to target a +# different CPU by rewriting the handler routines and changing +# the initialization data in the lookup tables. It should not +# be necessary to alter the formats of the tables. + +OBJ = disrel.o dismain.o distabs.o dishand.o disfp.o + +dis88 : $(OBJ) + ld -i -s -o dis88 /lib/crt0.o $(OBJ) -lc + size dis88 + @echo "\07Build of 'dis88' complete." > /dev/tty + +.c.o : + cc -O -c $< + chmod 600 $*.o + +disrel.o : disrel.c + +dismain.o : dismain.c dis.h + +distabs.o : distabs.c dis.h + +dishand.o : dishand.c dis.h + +disfp.o : disfp.c dis.h + diff --git a/README b/README new file mode 100644 index 0000000..d0c80dc --- /dev/null +++ b/README @@ -0,0 +1,91 @@ + dis88 + Beta Release + 87/09/01 + --- + G. M. HARDING + POB 4142 + Santa Clara CA 95054-0142 + + + "Dis88" is a symbolic disassembler for the Intel 8088 CPU, + designed to run under the PC/IX operating system on an IBM XT + or fully-compatible clone. Its output is in the format of, and + is completely compatible with, the PC/IX assembler, "as". The + program is copyrighted by its author, but may be copied and re- + distributed freely provided that complete source code, with all + copyright notices, accompanies any distribution. This provision + also applies to any modifications you may make. You are urged + to comment such changes, giving, as a miminum, your name and + complete address. + + This release of the program is a beta release, which means + that it has been extensively, but not exhaustively, tested. + User comments, recommendations, and bug fixes are welcome. The + principal features of the current release are: + + (a) The ability to disassemble any file in PC/IX object + format, making full use of symbol and relocation information if + it is present, regardless of whether the file is executable or + linkable, and regardless of whether it has continuous or split + I/D space; + + (b) Automatic generation of synthetic labels when no sym- + bol table is available; and + + (c) Optional output of address and object-code informa- + tion as assembler comment text. + + Limitations of the current release are: + + (a) Numeric co-processor (i.e., 8087) mnemonics are not + supported. Instructions for the co-processor are disassembled + as CPU escape sequences, or as interrupts, depending on how + they were assembled in the first place. This limitation will be + addressed in a future release. + + (b) Symbolic references within the object file's data + segment are not supported. Thus, for example, if a data segment + location is initialized to point to a text segment address, no + reference to a text segment symbol will be detected. This limi- + tation is likely to remain in future releases, because object + code does not, in most cases, contain sufficient information to + allow meaningful interpretation of pure data. (Note, however, + that symbolic references to the data segment from within the + text segment are always supported.) + + As a final caveat, be aware that the PC/IX assembler does + not recognize the "esc" mnemonic, even though it refers to a + completely valid CPU operation which is documented in all the + Intel literature. Thus, the corresponding opcodes (0xd8 through + 0xdf) are disassembled as .byte directives. For reference, how- + ever, the syntactically-correct "esc" instruction is output as + a comment. + + To build the disassembler program, transfer all the source + files, together with the Makefile, to a suitable (preferably + empty) PC/IX directory. Then, simply type "make". + + To use dis88, place it in a directory which appears in + your $PATH list. It may then be invoked by name from whatever + directory you happen to be in. As a minimum, the program must + be invoked with one command-line argument: the name of the ob- + ject file to be disassembled. (Dis88 will complain if the file + specified is not an object file.) Optionally, you may specify + an output file; stdout is the default. One command-line switch + is available: "-o", which makes the program display addresses + and object code along with its mnemonic disassembly. + + The "-o" option is useful primarily for verifying the cor- + rectness of the program's output. In particular, it may be used + to check the accuracy of local relative jump opcodes. These + jumps often target local labels, which are lost at assembly + time; thus, the disassembly may contain cryptic instructions + like "jnz .+39". As a user convenience, all relative jump and + call opcodes are output with a comment which identifies the + physical target address. + + By convention, the release level of the program as a whole + is the SID of the file disrel.c, and this SID string appears in + each disassembly. Release 2.1 of the program is the first beta + release to be distributed on Usenet. + diff --git a/dis.h b/dis.h new file mode 100644 index 0000000..9f93b38 --- /dev/null +++ b/dis.h @@ -0,0 +1,203 @@ + /* + ** @(#) dis.h, Ver. 2.1 created 00:00:00 87/09/01 + */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 1987 G. M. Harding, all rights reserved * + * * + * Permission to copy and redistribute is hereby granted, * + * provided full source code, with all copyright notices, * + * accompanies any redistribution. * + * * + * This file contains declarations and definitions used by * + * the 8088 disassembler program. The program was designed * + * for execution on a machine of its own type (i.e., it is * + * not designed as a cross-disassembler); consequently, A * + * SIXTEEN-BIT INTEGER SIZE HAS BEEN ASSUMED. This assump- * + * tion is not particularly important, however, except in * + * the machine-specific portions of the code (i.e., the * + * handler routines and the optab[] array). It should be * + * possible to override this assumption, for execution on * + * 32-bit machines, by use of a pre-processor directive * + * (see below); however, this has not been tested. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include /* System standard I/O definitions */ +#include /* System file-control definitions */ +#include /* Object file format definitions */ + +#if i8086 || i8088 /* For CPU's with 16-bit integers */ +#undef int +#else /* Defaults (for 32-bit CPU types) */ +#define int short +#endif + +#define MAXSYM 1500 /* Maximum entries in symbol table */ + +extern struct nlist /* Array to hold the symbol table */ + symtab[MAXSYM]; + +extern struct reloc /* Array to hold relocation table */ + relo[MAXSYM]; + +extern int symptr; /* Index into the symtab[] array */ + +extern int relptr; /* Index into the relo[] array */ + +struct opcode /* Format for opcode data records */ + { + char *text; /* Pointer to mnemonic text */ + void (*func)(); /* Pointer to handler routine */ + unsigned min; /* Minimum # of object bytes */ + unsigned max; /* Maximum # of object bytes */ + }; + +extern struct opcode /* Array to hold the opcode table */ + optab[256]; + + /* + +--------------------------------------------- + | The following functions are the specialized + | handlers for each opcode group. They are, of + | course, highly MACHINE-SPECIFIC. Each entry + | in the opcode[] array contains a pointer to + | one of these handlers. The handlers in the + | first group are in dishand.c; those in the + | second group are in disfp.c. + +--------------------------------------------- + */ + +extern void dfhand(), /* Default handler routine */ + sbhand(), /* Single-byte handler */ + aohand(), /* Arithmetic-op handler */ + sjhand(), /* Short-jump handler */ + imhand(), /* Immediate-operand handler */ + mvhand(), /* Simple move handler */ + mshand(), /* Segreg-move handler */ + pohand(), /* Pop memory/reg handler */ + cihand(), /* Intersegment call handler */ + mihand(), /* Immediate-move handler */ + mqhand(), /* Quick-move handler */ + tqhand(), /* Quick-test handler */ + rehand(), /* Return handler */ + mmhand(), /* Move-to-memory handler */ + srhand(), /* Shift and rotate handler */ + aahand(), /* ASCII-adjust handler */ + iohand(), /* Immediate port I/O handler */ + ljhand(), /* Long-jump handler */ + mahand(), /* Misc. arithmetic handler */ + mjhand(); /* Miscellaneous jump handler */ + +extern void eshand(), /* Bus-escape opcode handler */ + fphand(), /* Floating-point handler */ + inhand(); /* Interrupt-opcode handler */ + +extern char *REGS[]; /* Table of register names */ + +extern char *REGS0[]; /* Mode 0 register name table */ + +extern char *REGS1[]; /* Mode 1 register name table */ + +#define AL REGS[0] /* CPU register manifests */ +#define CL REGS[1] +#define DL REGS[2] +#define BL REGS[3] +#define AH REGS[4] +#define CH REGS[5] +#define DH REGS[6] +#define BH REGS[7] +#define AX REGS[8] +#define CX REGS[9] +#define DX REGS[10] +#define BX REGS[11] +#define SP REGS[12] +#define BP REGS[13] +#define SI REGS[14] +#define DI REGS[15] +#define ES REGS[16] +#define CS REGS[17] +#define SS REGS[18] +#define DS REGS[19] +#define BX_SI REGS0[0] +#define BX_DI REGS0[1] +#define BP_SI REGS0[2] +#define BP_DI REGS0[3] + +extern int symrank[6][6]; /* Symbol type/rank matrix */ + +extern unsigned long PC; /* Current program counter */ + +extern int segflg; /* Flag: segment override in effect */ + +extern int objflg; /* Flag: output object as a comment */ + +#define OBJMAX 8 /* Size of the object code buffer */ + +extern unsigned char /* Internal buffer for object code */ + objbuf[OBJMAX]; + +extern void objini(), /* Object-buffer init routine */ + objout(); /* Object-code output routine */ + +extern int objptr; /* Index into the objbuf[] array */ + +extern void badseq(); /* Bad-code-sequence function */ + +extern char *getnam(); /* Symbol-name string function */ + +extern char *lookup(); /* Symbol-table lookup function */ + +extern int lookext(); /* Extern-definition lookup routine */ + +extern char *mtrans(); /* Interpreter for the mode byte */ + +extern void mtrunc(); /* Mode string truncator function */ + +extern char ADD[], /* Opcode family mnemonic strings */ + OR[], + ADC[], + SBB[], + AND[], + SUB[], + XOR[], + CMP[], + NOT[], + NEG[], + MUL[], + DIV[], + MOV[], + ESC[], + TEST[], + AMBIG[]; + +extern char *OPFAM[]; /* Indexed mnemonic family table */ + +extern struct exec HDR; /* Holds the object file's header */ + +#define LOOK_ABS 0 /* Arguments to lookup() function */ +#define LOOK_REL 1 +#define LOOK_LNG 2 + +#define TR_STD 0 /* Arguments to mtrans() function */ +#define TR_SEG 8 + + /* Macro for byte input primitive */ +#define FETCH(p) \ + ++PC; p = getchar() & 0xff; objbuf[objptr++] = p + +extern int close(); /* System file-close primitive */ +extern int fprintf(); /* Library file-output function */ +extern long lseek(); /* System file-position primitive */ +extern int open(); /* System file-open primitive */ +extern int printf(); /* Library output-format function */ +extern int read(); /* System file-read primitive */ +extern int sprintf(); /* Library string-output function */ +extern char *strcat(); /* Library string-join function */ +extern char *strcpy(); /* Library string-copy function */ +extern int strlen(); /* Library string-length function */ + + /* * * * * * * * * * * END OF dis.h * * * * * * * * * * */ + + diff --git a/dis88.1 b/dis88.1 new file mode 100644 index 0000000..c991ad7 --- /dev/null +++ b/dis88.1 @@ -0,0 +1,147 @@ +.TH dis88 1 LOCAL +.SH "NAME" +dis88 \- 8088 symbolic disassembler +.SH "SYNOPSIS" +\fBdis88\fP [ -o ] ifile [ ofile ] +.SH "DESCRIPTION" +Dis88 reads ifile, which must be in PC/IX a.out format. +It interprets the binary opcodes and data locations, and +writes corresponding assembler source code to stdout, or +to ofile if specified. The program's output is in the +format of, and fully compatible with, the PC/IX assembler, +as(1). If a symbol table is present in ifile, labels and +references will be symbolic in the output. If the input +file lacks a symbol table, the fact will be noted, and the +disassembly will proceed, with the disassembler generating +synthetic labels as needed. If the input file has split +I/D space, or if it is executable, the disassembler will +make all necessary adjustments in address-reference calculations. +.PP +If the "-o" option appears, object code will be included +in comments during disassembly of the text segment. This +feature is used primarily for debugging the disassembler +itself, but may provide information of passing interest +to users. +.PP +The program always outputs the current machine address +before disassembling an opcode. If a symbol table is +present, this address is output as an assembler comment; +otherwise, it is incorporated into the synthetic label +which is generated internally. Since relative jumps, +especially short ones, may target unlabelled locations, +the program always outputs the physical target address +as a comment, to assist the user in following the code. +.PP +The text segment of an object file is always padded to +an even machine address. In addition, if the file has +split I/D space, the text segment will be padded to a +paragraph boundary (i.e., an address divisible by 16). +As a result of this padding, the disassembler may produce +a few spurious, but harmless, instructions at the +end of the text segment. +.PP +Disassembly of the data segment is a difficult matter. +The information to which initialized data refers cannot +be inferred from context, except in the special case +of an external data or address reference, which will be +reflected in the relocation table. Internal data and +address references will already be resolved in the object file, +and cannot be recreated. Therefore, the data +segment is disassembled as a byte stream, with long +stretches of null data represented by an appropriate +".zerow" pseudo-op. This limitation notwithstanding, +labels (as opposed to symbolic references) are always +output at appropriate points within the data segment. +.PP +If disassembly of the data segment is difficult, disassembly of the +bss segment is quite easy, because uninitialized data is all +zero by definition. No data +is output in the bss segment, but symbolic labels are +output as appropriate. +.PP +For each opcode which takes an operand, a particular +symbol type (text, data, or bss) is appropriate. This +tidy correspondence is complicated somewhat, however, +by the existence of assembler symbolic constants and +segment override opcodes. Therefore, the disassembler's +symbol lookup routine attempts to apply a certain amount +of intelligence when it is asked to find a symbol. If +it cannot match on a symbol of the preferred type, it +may return a symbol of some other type, depending on +preassigned (and somewhat arbitrary) rankings within +each type. Finally, if all else fails, it returns a +string containing the address sought as a hex constant; +this behavior allows calling routines to use the output +of the lookup function regardless of the success of its +search. +.PP +It is worth noting, at this point, that the symbol lookup +routine operates linearly, and has not been optimized in +any way. Execution time is thus likely to increase +geometrically with input file size. The disassembler is +internally limited to 1500 symbol table entries and 1500 +relocation table entries; while these limits are generous +(/unix, itself, has fewer than 800 symbols), they are not +guaranteed to be adequate in all cases. If the symbol +table or the relocation table overflows, the disassembly +aborts. +.PP +Finally, users should be aware of a bug in the assembler, +which causes it not to parse the "esc" mnemonic, even +though "esc" is a completely legitimate opcode which is +documented in all the Intel literature. To accommodate +this deficiency, the disassembler translates opcodes of +the "esc" family to .byte directives, but notes the +correct mnemonic in a comment for reference. +.PP +In all cases, it should be possible to submit the output +of the disassembler program to the assembler, and assemble +it without error. In most cases, the resulting object +code will be identical to the original; in any event, it +will be functionally equivalent. +.SH "SEE ALSO" +adb(1), as(1), cc(1), ld(1). +.br +"Assembler Reference Manual" in the PC/IX Programmer's +Guide. +.SH "DIAGNOSTICS" +"can't access input file" if the input file cannot be +found, opened, or read. +.sp +"can't open output file" if the output file cannot be +created. +.sp +"warning: host/cpu clash" if the program is run on a +machine with a different CPU. +.sp +"input file not in object format" if the magic number +does not correspond to that of a PC/IX object file. +.sp +"not an 8086/8088 object file" if the CPU ID of the +file header is incorrect. +.sp +"reloc table overflow" if there are more than 1500 +entries in the relocation table. +.sp +"symbol table overflow" if there are more than 1500 +entries in the symbol table. +.sp +"lseek error" if the input file is corrupted (should +never happen). +.sp +"warning: no symbols" if the symbol table is missing. +.sp +"can't reopen input file" if the input file is removed +or altered during program execution (should never happen). +.SH "BUGS" +Numeric co-processor (i.e., 8087) mnemonics are not currently supported. +Instructions for the co-processor are +disassembled as CPU escape sequences, or as interrupts, +depending on how they were assembled in the first place. +.sp +Despite the program's best efforts, a symbol retrieved +from the symbol table may sometimes be different from +the symbol used in the original assembly. +.sp +The disassembler's internal tables are of fixed size, +and the program aborts if they overflow. diff --git a/disfp.c b/disfp.c new file mode 100644 index 0000000..c6dc0da --- /dev/null +++ b/disfp.c @@ -0,0 +1,157 @@ +static char *sccsid = + "@(#) disfp.c, Ver. 2.1 created 00:00:00 87/09/01"; + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 1987 G. M. Harding, all rights reserved * + * * + * Permission to copy and redistribute is hereby granted, * + * provided full source code, with all copyright notices, * + * accompanies any redistribution. * + * * + * This file contains handler routines for the numeric op- * + * codes of the 8087 co-processor, as well as a few other * + * opcodes which are related to 8087 emulation. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "dis.h" /* Disassembler declarations */ + +#define FPINT0 0xd8 /* Floating-point interrupts */ +#define FPINT1 0xd9 +#define FPINT2 0xda +#define FPINT3 0xdb +#define FPINT4 0xdc +#define FPINT5 0xdd +#define FPINT6 0xde +#define FPINT7 0xdf + + /* Test for floating opcodes */ +#define ISFLOP(x) \ + (((x) >= FPINT0) && ((x) <= FPINT7)) + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the handler for the escape family of opcodes. * + * These opcodes place the contents of a specified memory * + * location on the system bus, for access by a peripheral * + * or by a co-processor such as the 8087. (The 8087 NDP is * + * accessed only via bus escapes.) Due to a bug in the * + * PC/IX assembler, the "esc" mnemonic is not recognized; * + * consequently, escape opcodes are disassembled as .byte * + * directives, with the appropriate mnemonic and operand * + * included as a comment. FOR NOW, those escape sequences * + * corresponding to 8087 opcodes are treated as simple * + * escapes. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +eshand(j) + + register int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF eshand() * * * * * * * * * */ + + register char *a; + register int k; + + objini(j); + + FETCH(k); + + a = mtrans((j & 0xfd),(k & 0xc7),TR_STD); + + mtrunc(a); + + printf("\t.byte\t0x%02.2x\t\t| esc\t%s\n",j,a); + + for (k = 1; k < objptr; ++k) + printf("\t.byte\t0x%02.2x\n",objbuf[k]); + +}/* * * * * * * * * * * END OF eshand() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the handler routine for floating-point opcodes. * + * Since PC/IX must accommodate systems with and without * + * 8087 co-processors, it allows floating-point operations * + * to be initiated in either of two ways: by a software * + * interrput whose type is in the range 0xd8 through 0xdf, * + * or by a CPU escape sequence, which is invoked by an op- * + * code in the same range. In either case, the subsequent * + * byte determines the actual numeric operation to be per- * + * formed. However, depending on the method of access, * + * either one or two code bytes will precede that byte, * + * and the fphand() routine has no way of knowing whether * + * it was invoked by interrupt or by an escape sequence. * + * Therefore, unlike all of the other handler routines ex- * + * cept dfhand(), fphand() does not initialize the object * + * buffer, leaving that chore to the caller. * + * * + * FOR NOW, fphand() does not disassemble floating-point * + * opcodes to floating mnemonics, but simply outputs the * + * object code as .byte directives. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +fphand(j) + + register int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF fphand() * * * * * * * * * */ + + register int k; + + segflg = 0; + + FETCH(k); + + printf("\t.byte\t0x%02.2x\t\t| 8087 code sequence\n", + objbuf[0]); + + for (k = 1; k < objptr; ++k) + printf("\t.byte\t0x%02.2x\n",objbuf[k]); + +/* objout(); FOR NOW */ + +}/* * * * * * * * * * * END OF fphand() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the handler for variable software interrupt * + * opcodes. It is included in this file because PC/IX im- * + * plements its software floating-point emulation by means * + * of interrupts. Any interrupt in the range 0xd8 through * + * 0xdf is an NDP-emulation interrupt, and is specially * + * handled by the assembler. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +inhand(j) + + register int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF inhand() * * * * * * * * * */ + + register int k; + + objini(j); + + FETCH(k); + + if (ISFLOP(k)) + { + fphand(k); + return; + } + + printf("%s\t%d\n",optab[j].text,k); + + objout(); + +}/* * * * * * * * * * * END OF inhand() * * * * * * * * * * */ + + diff --git a/dishand.c b/dishand.c new file mode 100644 index 0000000..56c6321 --- /dev/null +++ b/dishand.c @@ -0,0 +1,1049 @@ +static char *sccsid = + "@(#) dishand.c, Ver. 2.1 created 00:00:00 87/09/01"; + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 1987 G. M. Harding, all rights reserved * + * * + * Permission to copy and redistribute is hereby granted, * + * provided full source code, with all copyright notices, * + * accompanies any redistribution. * + * * + * This file contains the source code for most of the spe- * + * cialized handler routines of the disassembler program. * + * (The file disfp.c contains handler routines specific to * + * the 8087 numeric co-processor.) Each handler routine * + * interprets the opcode byte (and subsequent data bytes, * + * if any) of a particular family of opcodes, and is re- * + * sponsible for generating appropriate output. All of the * + * code in this file is highly MACHINE-SPECIFIC, and would * + * have to be rewritten for a different CPU. The handler * + * routines are accessed only via pointers in the optab[] * + * array, however, so machine dependencies are confined to * + * this file, its sister file "disfp.c", and the data file * + * "distabs.c". * + * * + * All of the code in this file is based on the assumption * + * of sixteen-bit integers. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "dis.h" /* Disassembler declarations */ + +int segflg; /* Segment-override flag */ + +unsigned char objbuf[OBJMAX]; /* Buffer for object code */ + +int objptr; /* Index into objbuf[] */ + +unsigned long PC; /* Current program counter */ + + /* * * * * * MISCELLANEOUS SUPPORTING ROUTINES * * * * * */ + + +void +objini(j) /* Object code init routine */ + + register int j; + +{ + if ((segflg == 1) || (segflg == 2)) + segflg *= 3; + else + segflg = 0; + objptr = 0; + objbuf[objptr++] = (unsigned char)(j); +} + + +void +objout() /* Object-code output routine */ + +{ + register int k; + + if ( ! objflg ) + return; + else + { + printf("\t|"); + if (symptr >= 0) + printf(" %05.5lx:",(PC + 1L - (long)(objptr))); + for (k = 0; k < objptr; ++k) + printf(" %02.2x",objbuf[k]); + putchar('\n'); + } +} + + +void +badseq(j,k) /* Invalid-sequence routine */ + + register int j, k; + +{ + printf("\t.byte\t0x%02.2x\t\t| invalid code sequence\n",j); + printf("\t.byte\t0x%02.2x\n",k); +} + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This routine is the first of several opcode-specific * + * handlers, each of which is dedicated to a particular * + * opcode family. A pointer to a handler routine is con- * + * tained in the second field of each optab[] entry. The * + * dfhand() routine is the default handler, invoked when * + * no other handler is appropriate (generally, when an in- * + * valid opcode is encountered). * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +dfhand(j) + + register int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF dfhand() * * * * * * * * * */ + + segflg = 0; + + printf("\t.byte\t0x%02.2x",j); + + if (optab[j].min || optab[j].max) + putchar('\n'); + else + printf("\t\t| unimplemented opcode\n"); + +}/* * * * * * * * * * * END OF dfhand() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the single-byte handler, invoked whenever a * + * one-byte opcode is encountered. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +sbhand(j) + + register int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF sbhand() * * * * * * * * * */ + + objini(j); + + if (j == 0x2e) /* seg cs */ + segflg = 1; + + if ((j == 0x26) /* seg es */ + || (j == 0x36) /* seg ss */ + || (j == 0x3e)) /* seg ds */ + segflg = 2; + + printf("%s\n",optab[j].text); + + objout(); + +}/* * * * * * * * * * * END OF sbhand() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the handler for most of the processor's regular * + * arithmetic operations. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +aohand(j) + + register int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF aohand() * * * * * * * * * */ + + register int k; + int m, n; + char b[64]; + + objini(j); + + switch (j & 7) + { + case 0 : + case 1 : + case 2 : + case 3 : + printf("%s\t",optab[j].text); + FETCH(k); + printf("%s\n",mtrans(j,k,TR_STD)); + break; + case 4 : + FETCH(k); + printf("%s\tal,*0x%02.2x\n",optab[j].text,k); + break; + case 5 : + FETCH(m); + FETCH(n); + k = (n << 8) | m; + if (lookext((long)(k),(PC - 1),b)) + printf("%s\tax,#%s\n",optab[j].text,b); + else + printf("%s\tax,#0x%04.4x\n",optab[j].text,k); + break; + default : + dfhand(j); + break; + } + + objout(); + +}/* * * * * * * * * * * END OF aohand() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the handler for opcodes which perform short * + * (eight-bit) relative jumps. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +sjhand(j) + + register int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF sjhand() * * * * * * * * * */ + + register int k; + int m; + + objini(j); + + FETCH(m); + + if (m & 0x80) + k = 0xff00; + else + k = 0; + + k |= m; + + printf("%s\t%s\t\t| loc %05.5lx\n",optab[j].text, + lookup((PC + k + 1L),N_TEXT,LOOK_REL,-1L), + (PC + k + 1L)); + + objout(); + +}/* * * * * * * * * * * END OF sjhand() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the handler for a loosely-knit family of op- * + * codes which perform arithmetic and logical operations, * + * and which take immediate data. The routine's logic is * + * rather complex, so, in an effort to avoid additional * + * complexity, the search for external references in the * + * relocation table has been dispensed with. Eager hackers * + * can try their hand at coding such a search. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +imhand(j) + + register int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF imhand() * * * * * * * * * */ + + unsigned long pc; + register int k; + int offset, oflag, immed, iflag, mod, opi, w, rm; + int m, n; + static char a[100], b[30]; + + objini(j); + + FETCH(k); + + pc = PC + 1; + + offset = 0; + mod = (k & 0xc0) >> 6; + opi = (k & 0x38) >> 3; + w = j & 1; + rm = k & 7; + + if ((j & 2) + && ((opi == 1) + || (opi == 4) + || (opi == 6))) + { + badseq(j,k); + return; + } + + strcpy(a,OPFAM[opi]); + + if ( ! w ) + strcat(a,"b"); + + if ((oflag = mod) > 2) + oflag = 0; + + if ((mod == 0) && (rm == 6)) + { + FETCH(m); + FETCH(n); + offset = (n << 8) | m; + } + else if (oflag) + if (oflag == 2) + { + FETCH(m); + FETCH(n); + offset = (n << 8) | m; + } + else + { + FETCH(m); + if (m & 0x80) + n = 0xff00; + else + n = 0; + offset = n | m; + } + + switch (j & 3) + { + case 0 : + case 2 : + FETCH(immed); + iflag = 0; + break; + case 1 : + FETCH(m); + FETCH(n); + immed = (n << 8) | m; + iflag = 1; + break; + case 3 : + FETCH(immed); + if (immed & 0x80) + immed &= 0xff00; + iflag = 0; + break; + } + + strcat(a,"\t"); + + switch (mod) + { + case 0 : + if (rm == 6) + strcat(a, + lookup((long)(offset),N_DATA,LOOK_ABS,pc)); + else + { + sprintf(b,"(%s)",REGS0[rm]); + strcat(a,b); + } + break; + case 1 : + case 2 : + if (mod == 1) + strcat(a,"*"); + else + strcat(a,"#"); + sprintf(b,"%d(",offset); + strcat(a,b); + strcat(a,REGS1[rm]); + strcat(a,")"); + break; + case 3 : + strcat(a,REGS[(w << 3) | rm]); + break; + } + + strcat(a,","); + if (iflag) + strcat(a,"#"); + else + strcat(a,"*"); + sprintf(b,"%d",immed); + strcat(a,b); + + printf("%s\n",a); + + objout(); + +}/* * * * * * * * * * * END OF imhand() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the handler for various "mov"-type opcodes * + * which use the mod, reg, and r/m fields of the second * + * code byte in a standard, straightforward way. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +mvhand(j) + + int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF mvhand() * * * * * * * * * */ + + register int k, m = j; + + objini(j); + + FETCH(k); + + if ((m == 0x84) || (m == 0x85) /* Kind of kludgey */ + || (m == 0xc4) || (m == 0xc5) + || (m == 0x8d)) + if (m & 0x40) + m |= 0x03; + else + m |= 0x02; + + printf("%s\t%s\n",optab[j].text,mtrans(m,k,TR_STD)); + + objout(); + +}/* * * * * * * * * * * END OF mvhand() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the handler for segment-register "mov" opcodes. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +mshand(j) + + register int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF mshand() * * * * * * * * * */ + + register int k; + + objini(j); + + FETCH(k); + + if (k & 0x20) + { + badseq(j,k); + return; + } + + printf("%s\t%s\n",optab[j].text,mtrans(j,k,TR_SEG)); + + objout(); + +}/* * * * * * * * * * * END OF mshand() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the handler for pops, other than single-byte * + * pops. (The 8088 allows popping into any register, or * + * directly into memory, accessed either immediately or * + * through a register and an index.) * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +pohand(j) + + register int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF pohand() * * * * * * * * * */ + + char *a; + register int k; + + objini(j); + + FETCH(k); + + if (k & 0x38) + { + badseq(j,k); + return; + } + + printf("%s\t",optab[j].text); + + a = mtrans((j & 0xfd),k,TR_STD); + + mtrunc(a); + + printf("%s\n",a); + + objout(); + +}/* * * * * * * * * * * END OF pohand() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the handler routine for intersegment calls and * + * jumps. Its output is never symbolic, because the host * + * linker does not allow symbolic intersegment address * + * references except by means of symbolic constants, and * + * any such constants in the symbol table, even if they * + * are of the appropriate value, may be misleading. In * + * compiled code, intersegment references should not be * + * encountered, and even in assembled code, they should * + * occur infrequently. If and when they do occur, however, * + * they will be disassembled in absolute form. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +cihand(j) + + int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF cihand() * * * * * * * * * */ + + register int m, n; + + objini(j); + + printf("%s\t",optab[j].text); + + FETCH(m); + FETCH(n); + + printf("#0x%04.4x,",((n << 8) | m)); + + FETCH(m); + FETCH(n); + + printf("#0x%04.4x\n",((n << 8) | m)); + + objout(); + +}/* * * * * * * * * * * END OF cihand() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the handler for "mov" opcodes with immediate * + * data. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +mihand(j) + + register int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF mihand() * * * * * * * * * */ + + register int k; + int m, n; + char b[64]; + + objini(j); + + printf("%s",optab[j].text); + + if (j & 8) + { + FETCH(m); + FETCH(n); + k = ((n << 8) | m); + if (lookext((long)(k),(PC - 1),b)) + printf("#%s\n",b); + else + printf("#%d\n",k); + } + else + { + FETCH(m); + printf("*%d\n",m); + } + + objout(); + +}/* * * * * * * * * * * END OF mihand() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the handler for a family of quick-move opcodes. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +mqhand(j) + + int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF mqhand() * * * * * * * * * */ + + unsigned long pc; + register int m, n; + + objini(j); + + pc = PC + 1; + + FETCH(m); + FETCH(n); + + m = (n << 8) | m; + + printf("%s\t",optab[j].text); + + if (j & 2) + printf("%s,%s\n", + lookup((long)(m),N_DATA,LOOK_ABS,pc), + REGS[(j & 1) << 3]); + else + printf("%s,%s\n", + REGS[(j & 1) << 3], + lookup((long)(m),N_DATA,LOOK_ABS,pc)); + + objout(); + +}/* * * * * * * * * * * END OF mqhand() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the handler for a family of quick-test opcodes. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +tqhand(j) + + int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF tqhand() * * * * * * * * * */ + + register int m, n; + int k; + char b[64]; + + objini(j); + + printf("%s\t%s,",optab[j].text,REGS[(j & 1) << 3]); + + FETCH(m); + + if (j & 1) + { + FETCH(n); + k = ((n << 8) | m); + if (lookext((long)(k),(PC - 1),b)) + printf("#%s\n",b); + else + printf("#%d\n",k); + } + else + { + if (m & 80) + m |= 0xff00; + printf("*%d\n",m); + } + + objout(); + +}/* * * * * * * * * * * END OF tqhand() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the handler for multiple-byte "return" opcodes. * + * The 8088 allows returns to take an optional 16-bit ar- * + * gument, which reflects the amount to be added to SP * + * after the pop of the return address. The idea is to * + * facilitate the use of local parameters on the stack. * + * After some rumination, it was decided to disassemble * + * any such arguments as absolute quantities, rather than * + * rummaging through the symbol table for possible corre- * + * sponding constants. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +rehand(j) + + int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF rehand() * * * * * * * * * */ + + register int m, n; + + objini(j); + + FETCH(m); + FETCH(n); + + m = (n << 8) | m; + + printf("%s\t#0x%04.4x\n",optab[j].text,m); + + objout(); + +}/* * * * * * * * * * * END OF rehand() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the handler for "mov" opcodes involving memory * + * and immediate data. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +mmhand(j) + + register int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF mmhand() * * * * * * * * * */ + + char *a; + register int k; + char b[64]; + + objini(j); + + FETCH(k); + + if (k & 0x38) + { + badseq(j,k); + return; + } + + printf("%s",optab[j].text); + + if ( ! (j & 1) ) + putchar('b'); + + a = mtrans((j & 0xfd),(k & 0xc7),TR_STD); + + mtrunc(a); + + printf("\t%s,",a); + + if (j & 1) + { + FETCH(j); + FETCH(k); + k = (k << 8) | j; + if (lookext((long)(k),(PC - 1),b)) + printf("#%s\n",b); + else + printf("#%d\n",k); + } + else + { + FETCH(k); + printf("*%d\n",k); + } + + objout(); + +}/* * * * * * * * * * * END OF mmhand() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the handler for the 8088 family of shift and * + * rotate instructions. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +srhand(j) + + register int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF srhand() * * * * * * * * * */ + + char *a; + register int k; + + objini(j); + + FETCH(k); + + if ((k & 0x38) == 0x30) + { + badseq(j,k); + return; + } + + printf("%s",OPFAM[((k & 0x38) >> 3) + 16]); + + if ( ! (j & 1) ) + putchar('b'); + + a = mtrans((j & 0xfd),(k & 0xc7),TR_STD); + + mtrunc(a); + + printf("\t%s",a); + + if (j & 2) + printf(",cl\n"); + else + printf(",*1\n"); + + objout(); + +}/* * * * * * * * * * * END OF srhand() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the handler for the ASCII-adjust opcodes. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +aahand(j) + + register int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF aahand() * * * * * * * * * */ + + register int k; + + objini(j); + + FETCH(k); + + if (k != 0x0a) + { + badseq(j,k); + return; + } + + printf("%s\n",optab[j].text); + + objout(); + +}/* * * * * * * * * * * END OF aahand() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the handler for port I/O opcodes which specify * + * the port address as an immediate operand. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +iohand(j) + + register int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF iohand() * * * * * * * * * */ + + register int k; + + objini(j); + + FETCH(k); + + printf("%s\t0x%02.2x\n",optab[j].text,k); + + objout(); + +}/* * * * * * * * * * * END OF iohand() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the handler for opcodes which perform long * + * (sixteen-bit) relative jumps and calls. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +ljhand(j) + + register int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF ljhand() * * * * * * * * * */ + + register int k; + int m, n; + + objini(j); + + FETCH(m); + FETCH(n); + + k = (n << 8) | m; + + printf("%s\t%s\t\t| loc %05.5lx\n",optab[j].text, + lookup((PC + k + 1L),N_TEXT,LOOK_LNG,(PC - 1L)), + (PC + k + 1L)); + + objout(); + +}/* * * * * * * * * * * END OF ljhand() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the handler for a pair of oddball opcodes (0xf6 * + * and 0xf7) which perform miscellaneous arithmetic opera- * + * tions not dealt with elsewhere. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +mahand(j) + + register int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF mahand() * * * * * * * * * */ + + char *a; + register int k; + char b[64]; + + objini(j); + + FETCH(k); + + a = mtrans((j & 0xfd),(k & 0xc7),TR_STD); + + mtrunc(a); + + switch (((k = objbuf[1]) & 0x38) >> 3) + { + case 0 : + printf("\ttest"); + break; + case 1 : + badseq(j,k); + return; + case 2 : + printf("\tnot"); + break; + case 3 : + printf("\tneg"); + break; + case 4 : + printf("\tmul"); + break; + case 5 : + printf("\timul"); + break; + case 6 : + printf("\tdiv"); + break; + case 7 : + printf("\tidiv"); + break; + } + + if ( ! (j & 1) ) + putchar('b'); + + printf("\t%s",a); + + if (k & 0x38) + putchar('\n'); + else + if (j & 1) + { + FETCH(j); + FETCH(k); + k = (k << 8) | j; + if (lookext((long)(k),(PC - 1),b)) + printf(",#%s\n",b); + else + printf(",#%d\n",k); + } + else + { + FETCH(k); + printf(",*%d\n",k); + } + + objout(); + +}/* * * * * * * * * * * END OF mahand() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the handler for miscellaneous jump, call, push, * + * and increment/decrement opcodes (0xfe and 0xff) which * + * are not dealt with elsewhere. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +mjhand(j) + + register int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF mjhand() * * * * * * * * * */ + + char *a; + register int k; + + objini(j); + + FETCH(k); + + a = mtrans((j & 0xfd),(k & 0xc7),TR_STD); + + mtrunc(a); + + switch (((k = objbuf[1]) & 0x38) >> 3) + { + case 0 : + printf("\tinc"); + if ( ! (j & 1) ) + putchar('b'); + putchar('\t'); + break; + case 1 : + printf("\tdec"); + if ( ! (j & 1) ) + putchar('b'); + putchar('\t'); + break; + case 2 : + if (j & 1) + printf("\tcall\t@"); + else + goto BAD; + break; + case 3 : + if (j & 1) + printf("\tcalli\t@"); + else + goto BAD; + break; + case 4 : + if (j & 1) + printf("\tjmp\t@"); + else + goto BAD; + break; + case 5 : + if (j & 1) + printf("\tjmpi\t@"); + else + goto BAD; + break; + case 6 : + if (j & 1) + printf("\tpush\t"); + else + goto BAD; + break; + case 7 : + BAD : + badseq(j,k); + return; + } + + printf("%s\n",a); + + objout(); + +}/* * * * * * * * * * * END OF mjhand() * * * * * * * * * * */ + + diff --git a/dismain.c b/dismain.c new file mode 100644 index 0000000..b511785 --- /dev/null +++ b/dismain.c @@ -0,0 +1,624 @@ +static char *sccsid = + "@(#) dismain.c, Ver. 2.1 created 00:00:00 87/09/01"; + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 1987 G. M. Harding, all rights reserved * + * * + * Permission to copy and redistribute is hereby granted, * + * provided full source code, with all copyright notices, * + * accompanies any redistribution. * + * * + * This file contains the source code for the machine- * + * independent portions of a disassembler program to run * + * in a Unix (System III) environment. It expects, as its * + * input, a file in standard a.out format, optionally con- * + * taining symbol table information. If a symbol table is * + * present, it will be used in the disassembly; otherwise, * + * all address references will be literal (absolute). * + * * + * The disassembler program was originally written for an * + * Intel 8088 CPU. However, all details of the actual CPU * + * architecture are hidden in three machine-specific files * + * named distabs.c, dishand.c, and disfp.c (the latter * + * file is specific to the 8087 numeric co-processor). The * + * code in this file is generic, and should require mini- * + * mal revision if a different CPU is to be targeted. If a * + * different version of Unix is to be targeted, changes to * + * this file may be necessary, and if a completely differ- * + * ent OS is to be targeted, all bets are off. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "dis.h" /* Disassembler declarations */ + +extern char *release; /* Contains release string */ + +static char *IFILE = NULL; /* Points to input file name */ + +static char *OFILE = NULL; /* Points to output file name */ + +static char *PRG; /* Name of invoking program */ + +static unsigned long zcount; /* Consecutive "0" byte count */ + +int objflg = 0; /* Flag: output object bytes */ + +#if unix && i8086 && ibmpc /* Set the CPU identifier */ +static int cpuid = 1; +#else +static int cpuid = 0; +#endif + + /* * * * * * * MISCELLANEOUS UTILITY FUNCTIONS * * * * * * */ + +static void +usage(s) + register char *s; +{ + fprintf(stderr,"\07usage: %s [-o] ifile [ofile]\n",s); + exit(-1); +} + +static void +fatal(s,t) + register char *s, *t; +{ + fprintf(stderr,"\07%s: %s\n",s,t); + exit(-1); +} + +static void +zdump(beg) + unsigned long beg; +{ + beg = PC - beg; + if (beg > 1L) + printf("\t.zerow\t%ld\n",(beg >> 1)); + if (beg & 1L) + printf("\t.byte\t0\n"); +} + +static char * +invoker(s) + register char *s; +{ + extern int strlen(); + register int k; + + k = strlen(s); + + while (k--) + if (s[k] == '/') + { + s += k; + ++s; + break; + } + + return (s); +} + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This rather tricky routine supports the disdata() func- * + * tion. Its job is to output the code for a sequence of * + * data bytes whenever the object buffer is full, or when * + * a symbolic label is to be output. However, it must also * + * keep track of consecutive zero words so that lengthy * + * stretches of null data can be compressed by the use of * + * an appropriate assembler pseudo-op. It does this by * + * setting and testing a file-wide flag which counts suc- * + * cessive full buffers of null data. The function returns * + * a logical TRUE value if it outputs anything, logical * + * FALSE otherwise. (This enables disdata() to determine * + * whether to output a new synthetic label when there is * + * no symbol table.) * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +static int +objdump(c) + + register char *c; + +{/* * * * * * * * * * START OF objdump() * * * * * * * * * */ + + register int k; + int retval = 0; + + if (objptr == OBJMAX) + { + for (k = 0; k < OBJMAX; ++k) + if (objbuf[k]) + break; + if (k == OBJMAX) + { + zcount += k; + objptr = 0; + if (c == NULL) + return (retval); + } + } + + if (zcount) + { + printf("\t.zerow\t%ld\n",(zcount >> 1)); + ++retval; + zcount = 0L; + } + + if (objptr) + { + printf("\t.byte\t"); + ++retval; + } + else + return (retval); + + for (k = 0; k < objptr; ++k) + { + printf("0x%02.2x",objbuf[k]); + if (k < (objptr - 1)) + putchar(','); + else + putchar('\n'); + } + + objptr = 0; + + return (retval); + +}/* * * * * * * * * * END OF objdump() * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This routine, called at the beginning of the input * + * cycle for each object byte, and before any interpreta- * + * tion is attempted, searches the symbol table for any * + * symbolic name with a value corresponding to the cur- * + * rent PC and a type corresponding to the segment type * + * (i.e., text, data, or bss) specified by the function's * + * argument. If any such name is found, a pointer to it is * + * returned; otherwise, a NULL pointer is returned. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +static char * +getlab(type) + + register int type; + +{/* * * * * * * * * * START OF getlab() * * * * * * * * * */ + + register int k; + static char b[32], c[10]; + + if (symptr < 0) + if ((type == N_TEXT) + || ((type == N_DATA) && ( ! objptr ) && ( ! zcount ))) + { + if (type == N_TEXT) + sprintf(b,"T%05.5lx:",PC); + else + sprintf(b,"D%05.5lx:",PC); + return (b); + } + else + return (NULL); + + for (k = 0; k <= symptr; ++k) + if ((symtab[k].n_value == PC) + && ((symtab[k].n_sclass & N_SECT) == type)) + { + sprintf(b,"%s:\n",getnam(k)); + if (objflg && (type != N_TEXT)) + sprintf(c,"| %05.5lx\n",PC); + strcat(b,c); + return (b); + } + + return (NULL); + +}/* * * * * * * * * * * END OF getlab() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This routine performs a preliminary scan of the symbol * + * table, before disassembly begins, and outputs declara- * + * tions of globals and constants. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +static void +prolog() + +{/* * * * * * * * * * START OF prolog() * * * * * * * * * */ + + register int j, flag; + + if (symptr < 0) + return; + + for (j = flag = 0; j <= symptr; ++j) + if ((symtab[j].n_sclass & N_CLASS) == C_EXT) + if (((symtab[j].n_sclass & N_SECT) > N_UNDF) + && ((symtab[j].n_sclass & N_SECT) < N_COMM)) + { + char *c = getnam(j); + printf("\t.globl\t%s",c); + if (++flag == 1) + { + putchar('\t'); + if (strlen(c) < 8) + putchar('\t'); + printf("| Internal global\n"); + } + else + putchar('\n'); + } + else + if (symtab[j].n_value) + { + char *c = getnam(j); + printf("\t.comm\t%s,0x%08.8lx",c, + symtab[j].n_value); + if (++flag == 1) + printf("\t| Internal global\n"); + else + putchar('\n'); + } + + if (flag) + putchar('\n'); + + for (j = flag = 0; j <= relptr; ++j) + if (relo[j].r_symndx < S_BSS) + { + char *c = getnam(relo[j].r_symndx); + ++flag; + printf("\t.globl\t%s",c); + putchar('\t'); + if (strlen(c) < 8) + putchar('\t'); + printf("| Undef: %05.5lx\n",relo[j].r_vaddr); + } + + if (flag) + putchar('\n'); + + for (j = flag = 0; j <= symptr; ++j) + if ((symtab[j].n_sclass & N_SECT) == N_ABS) + { + char *c = getnam(j); + printf("%s=0x%08.8lx",c,symtab[j].n_value); + if (++flag == 1) + { + printf("\t\t"); + if (strlen(c) < 5) + putchar('\t'); + printf("| Literal\n"); + } + else + putchar('\n'); + } + + if (flag) + putchar('\n'); + +}/* * * * * * * * * * * END OF prolog() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This function is responsible for disassembly of the * + * object file's text segment. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +static void +distext() + +{/* * * * * * * * * * START OF distext() * * * * * * * * * */ + + char *c; + register int j; + register void (*f)(); + + for (j = 0; j < (int)(HDR.a_hdrlen); ++j) + getchar(); + + printf("| %s, %s\n\n",PRG,release); + + printf("| @("); + + printf("#)\tDisassembly of %s",IFILE); + + if (symptr < 0) + printf(" (no symbols)\n\n"); + else + printf("\n\n"); + + if (HDR.a_flags & A_EXEC) + printf("| File is executable\n\n"); + + if (HDR.a_flags & A_SEP) + { + printf("| File has split I/D space, and may have\n"); + printf("| extraneous instructions in text segment\n\n"); + } + + prolog(); + + printf("\t.text\t\t\t| loc = %05.5lx, size = %05.5lx\n\n", + PC,HDR.a_text); + + segflg = 0; + + for (PC = 0L; PC < HDR.a_text; ++PC) + { + j = getchar() & 0xff; + if ((j == 0) && ((PC + 1L) == HDR.a_text)) + { + ++PC; + break; + } + if ((c = getlab(N_TEXT)) != NULL) + printf("%s",c); + f = optab[j].func; + (*f)(j); + } + +}/* * * * * * * * * * END OF distext() * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This function handles the object file's data segment. * + * There is no good way to disassemble a data segment, be- * + * cause it is impossible to tell, from the object code * + * alone, what each data byte refers to. If it refers to * + * an external symbol, the reference can be resolved from * + * the relocation table, if there is one. However, if it * + * refers to a static symbol, it cannot be distinguished * + * from numeric, character, or other pointer data. In some * + * cases, one might make a semi-educated guess as to the * + * nature of the data, but such guesses are inherently * + * haphazard, and they are bound to be wrong a good por- * + * tion of the time. Consequently, the data segment is * + * disassembled as a byte stream, which will satisfy no * + * one but which, at least, will never mislead anyone. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +static void +disdata() + +{/* * * * * * * * * * START OF disdata() * * * * * * * * * */ + + register char *c; + register int j; + unsigned long end; + + putchar('\n'); + + if (HDR.a_flags & A_SEP) + { + PC = 0L; + end = HDR.a_data; + } + else + end = HDR.a_text + HDR.a_data; + + printf("\t.data\t\t\t| loc = %05.5lx, size = %05.5lx\n\n", + PC,HDR.a_data); + + segflg = 0; + + for (objptr = 0, zcount = 0L; PC < end; ++PC) + { + if ((c = getlab(N_DATA)) != NULL) + { + objdump(c); + printf("%s",c); + } + if (objptr >= OBJMAX) + if (objdump(NULL) && (symptr < 0)) + printf("D%05.5lx:",PC); + j = getchar() & 0xff; + objbuf[objptr++] = j; + } + + objdump(""); + +}/* * * * * * * * * * END OF disdata() * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This function handles the object file's bss segment. * + * Disassembly of the bss segment is easy, because every- * + * thing in it is zero by definition. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +static void +disbss() + +{/* * * * * * * * * * START OF disbss() * * * * * * * * * */ + + register int j; + register char *c; + unsigned long beg, end; + + putchar('\n'); + + if (HDR.a_flags & A_SEP) + end = HDR.a_data + HDR.a_bss; + else + end = HDR.a_text + HDR.a_data + HDR.a_bss; + + printf("\t.bss\t\t\t| loc = %05.5lx, size = %05.5lx\n\n", + PC,HDR.a_bss); + + segflg = 0; + + for (beg = PC; PC < end; ++PC) + if ((c = getlab(N_BSS)) != NULL) + { + if (PC > beg) + { + zdump(beg); + beg = PC; + } + printf("%s",c); + } + + if (PC > beg) + zdump(beg); + +}/* * * * * * * * * * * END OF disbss() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the program entry point. The command line is * + * searched for an input file name, which must be present. * + * An optional output file name is also permitted; if none * + * is found, standard output is the default. One command- * + * line option is available: "-o", which causes the pro- * + * gram to include object code in comments along with its * + * mnemonic output. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +main(argc,argv) + + int argc; /* Command-line args from OS */ + register char **argv; + +{/* * * * * * * * * * * START OF main() * * * * * * * * * * */ + + char a[1024]; + register int fd; + long taboff, tabnum; + long reloff, relnum; + + PRG = invoker(*argv); + + while (*++argv != NULL) /* Process command-line args */ + if (**argv == '-') + switch (*++*argv) + { + case 'o' : + if (*++*argv) + usage(PRG); + else + ++objflg; + break; + default : + usage(PRG); + } + else + if (IFILE == NULL) + IFILE = *argv; + else if (OFILE == NULL) + OFILE = *argv; + else + usage(PRG); + + if (IFILE == NULL) + usage(PRG); + else + if ((fd = open(IFILE,O_RDONLY)) < 0) + { + sprintf(a,"can't access input file %s",IFILE); + fatal(PRG,a); + } + + if (OFILE != NULL) + if (freopen(OFILE,"w",stdout) == NULL) + { + sprintf(a,"can't open output file %s",OFILE); + fatal(PRG,a); + } + + if ( ! cpuid ) + fprintf(stderr,"\07%s: warning: host/cpu clash\n",PRG); + + read(fd,&HDR,sizeof(struct exec)); + + if (BADMAG(HDR)) + { + sprintf(a,"input file %s not in object format",IFILE); + fatal(PRG,a); + } + + if (HDR.a_cpu != A_I8086) + { + sprintf(a,"%s is not an 8086/8088 object file",IFILE); + fatal(PRG,a); + } + + if (HDR.a_hdrlen <= A_MINHDR) + HDR.a_trsize = HDR.a_drsize = + HDR.a_tbase = HDR.a_dbase = + HDR.a_lnums = HDR.a_toffs = 0L; + + reloff = HDR.a_text /* Compute reloc data offset */ + + HDR.a_data + + (long)(HDR.a_hdrlen); + + relnum = + (HDR.a_trsize + HDR.a_drsize) / sizeof(struct reloc); + + taboff = reloff /* Compute name table offset */ + + HDR.a_trsize + + HDR.a_drsize; + + tabnum = HDR.a_syms / sizeof(struct nlist); + + if (relnum > MAXSYM) + fatal(PRG,"reloc table overflow"); + + if (tabnum > MAXSYM) + fatal(PRG,"symbol table overflow"); + + if (relnum) /* Get reloc data */ + if (lseek(fd,reloff,0) != reloff) + fatal(PRG,"lseek error"); + else + { + for (relptr = 0; relptr < relnum; ++relptr) + read(fd,&relo[relptr],sizeof(struct reloc)); + relptr--; + } + + if (tabnum) /* Read in symtab */ + if (lseek(fd,taboff,0) != taboff) + fatal(PRG,"lseek error"); + else + { + for (symptr = 0; symptr < tabnum; ++symptr) + read(fd,&symtab[symptr],sizeof(struct nlist)); + symptr--; + } + else + fprintf(stderr,"\07%s: warning: no symbols\n",PRG); + + close(fd); + + if (freopen(IFILE,"r",stdin) == NULL) + { + sprintf(a,"can't reopen input file %s",IFILE); + fatal(PRG,a); + } + + distext(); + + disdata(); + + disbss(); + + exit(0); + +}/* * * * * * * * * * * END OF main() * * * * * * * * * * */ + + diff --git a/disrel.c b/disrel.c new file mode 100644 index 0000000..1e28155 --- /dev/null +++ b/disrel.c @@ -0,0 +1,28 @@ +static char *copyright = + "@(#) Copyright (C) 1987 G. M. Harding, all rights reserved"; + +static char *sccsid = + "@(#) disrel.c, Ver. 2.1 created 00:00:00 87/09/01"; + +char *release = + "release 2.1 (PC/IX)"; + + /* + ** + ** This file documents the major revisions to the 8088 sym- + ** bolic disassembler. It also contains the release string + ** which is output at the head of each disassembly, and the + ** copyright string which must be incorporated in any code + ** distribution. + ** + ** Permission to copy and redistribute is hereby granted, + ** provided full source code, with all copyright notices, + ** accompanies any redistribution. + ** + ** REVISION HISTORY: + ** + ** SEP 87: + ** After internal shakeout, released on Usenet. + ** + */ + diff --git a/distabs.c b/distabs.c new file mode 100644 index 0000000..6390cec --- /dev/null +++ b/distabs.c @@ -0,0 +1,708 @@ +static char *sccsid = + "@(#) distabs.c, Ver. 2.1 created 00:00:00 87/09/01"; + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 1987 G. M. Harding, all rights reserved * + * * + * Permission to copy and redistribute is hereby granted, * + * provided full source code, with all copyright notices, * + * accompanies any redistribution. * + * * + * This file contains the lookup tables and other data * + * structures for the Intel 8088 symbolic disassembler. It * + * also contains a few global routines which facilitate * + * access to the tables, for use primarily by the handler * + * functions. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "dis.h" /* Disassembler declarations */ + +struct exec HDR; /* Used to hold header info */ + +struct nlist symtab[MAXSYM]; /* Array of symbol table info */ + +struct reloc relo[MAXSYM]; /* Array of relocation info */ + +int symptr = -1, /* Index into symtab[] */ + relptr = -1; /* Index into relo[] */ + +char *REGS[] = /* Table of register names */ + { + "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh", + "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", + "es", "cs", "ss", "ds" + }; + +char *REGS0[] = /* Mode 0 register name table */ + { + "bx_si", "bx_di", "bp_si", "bp_di", "si", "di", "", "bx" + }; + +char *REGS1[] = /* Mode 1 register name table */ + { + "bx_si", "bx_di", "bp_si", "bp_di", "si", "di", "bp", "bx" + }; + +int symrank[6][6] = /* Symbol type/rank matrix */ + { + /* UND ABS TXT DAT BSS COM */ + /* UND */ 5, 4, 1, 2, 3, 0, + /* ABS */ 1, 5, 4, 3, 2, 0, + /* TXT */ 4, 1, 5, 3, 2, 0, + /* DAT */ 3, 1, 2, 5, 4, 0, + /* BSS */ 3, 1, 2, 4, 5, 0, + /* COM */ 2, 0, 1, 3, 4, 5 + }; + + /* * * * * * * * * * * * OPCODE DATA * * * * * * * * * * * */ + +char ADD[] = "\tadd", /* Mnemonics by family */ + OR[] = "\tor", + ADC[] = "\tadc", + SBB[] = "\tsbb", + AND[] = "\tand", + SUB[] = "\tsub", + XOR[] = "\txor", + CMP[] = "\tcmp", + NOT[] = "\tnot", + NEG[] = "\tneg", + MUL[] = "\tmul", + DIV[] = "\tdiv", + MOV[] = "\tmov", + ESC[] = "\tesc", + TEST[] = "\ttest", + AMBIG[] = "", + ROL[] = "\trol", + ROR[] = "\tror", + RCL[] = "\trcl", + RCR[] = "\trcr", + SAL[] = "\tsal", + SHR[] = "\tshr", + SHL[] = "\tshl", + SAR[] = "\tsar"; + +char *OPFAM[] = /* Family lookup table */ + { + ADD, OR, ADC, SBB, AND, SUB, XOR, CMP, + NOT, NEG, MUL, DIV, MOV, ESC, TEST, AMBIG, + ROL, ROR, RCL, RCR, SAL, SHR, SHL, SAR + }; + +struct opcode optab[] = /* Table of opcode data */ + { + ADD, aohand, 2, 4, /* 0x00 */ + ADD, aohand, 2, 4, /* 0x01 */ + ADD, aohand, 2, 4, /* 0x02 */ + ADD, aohand, 2, 4, /* 0x03 */ + ADD, aohand, 2, 2, /* 0x04 */ + ADD, aohand, 3, 3, /* 0x05 */ + "\tpush\tes", sbhand, 1, 1, /* 0x06 */ + "\tpop\tes", sbhand, 1, 1, /* 0x07 */ + OR, aohand, 2, 4, /* 0x08 */ + OR, aohand, 2, 4, /* 0x09 */ + OR, aohand, 2, 4, /* 0x0a */ + OR, aohand, 2, 4, /* 0x0b */ + OR, aohand, 2, 2, /* 0x0c */ + OR, aohand, 3, 3, /* 0x0d */ + "\tpush\tcs", sbhand, 1, 1, /* 0x0e */ + NULL, dfhand, 0, 0, /* 0x0f */ + ADC, aohand, 2, 4, /* 0x10 */ + ADC, aohand, 2, 4, /* 0x11 */ + ADC, aohand, 2, 4, /* 0x12 */ + ADC, aohand, 2, 4, /* 0x13 */ + ADC, aohand, 2, 2, /* 0x14 */ + ADC, aohand, 3, 3, /* 0x15 */ + "\tpush\tss", sbhand, 1, 1, /* 0x16 */ + "\tpop\tss", sbhand, 1, 1, /* 0x17 */ + SBB, aohand, 2, 4, /* 0x18 */ + SBB, aohand, 2, 4, /* 0x19 */ + SBB, aohand, 2, 4, /* 0x1a */ + SBB, aohand, 2, 4, /* 0x1b */ + SBB, aohand, 2, 2, /* 0x1c */ + SBB, aohand, 3, 3, /* 0x1d */ + "\tpush\tds", sbhand, 1, 1, /* 0x1e */ + "\tpop\tds", sbhand, 1, 1, /* 0x1f */ + AND, aohand, 2, 4, /* 0x20 */ + AND, aohand, 2, 4, /* 0x21 */ + AND, aohand, 2, 4, /* 0x22 */ + AND, aohand, 2, 4, /* 0x23 */ + AND, aohand, 2, 2, /* 0x24 */ + AND, aohand, 3, 3, /* 0x25 */ + "\tseg\tes", sbhand, 1, 1, /* 0x26 */ + "\tdaa", sbhand, 1, 1, /* 0x27 */ + SUB, aohand, 2, 4, /* 0x28 */ + SUB, aohand, 2, 4, /* 0x29 */ + SUB, aohand, 2, 4, /* 0x2a */ + SUB, aohand, 2, 4, /* 0x2b */ + SUB, aohand, 2, 2, /* 0x2c */ + SUB, aohand, 3, 3, /* 0x2d */ + "\tseg\tcs", sbhand, 1, 1, /* 0x2e */ + "\tdas", sbhand, 1, 1, /* 0x2f */ + XOR, aohand, 2, 4, /* 0x30 */ + XOR, aohand, 2, 4, /* 0x31 */ + XOR, aohand, 2, 4, /* 0x32 */ + XOR, aohand, 2, 4, /* 0x33 */ + XOR, aohand, 2, 2, /* 0x34 */ + XOR, aohand, 3, 3, /* 0x35 */ + "\tseg\tss", sbhand, 1, 1, /* 0x36 */ + "\taaa", sbhand, 1, 1, /* 0x37 */ + CMP, aohand, 2, 4, /* 0x38 */ + CMP, aohand, 2, 4, /* 0x39 */ + CMP, aohand, 2, 4, /* 0x3a */ + CMP, aohand, 2, 4, /* 0x3b */ + CMP, aohand, 2, 2, /* 0x3c */ + CMP, aohand, 3, 3, /* 0x3d */ + "\tseg\tds", sbhand, 1, 1, /* 0x3e */ + "\taas", sbhand, 1, 1, /* 0x3f */ + "\tinc\tax", sbhand, 1, 1, /* 0x40 */ + "\tinc\tcx", sbhand, 1, 1, /* 0x41 */ + "\tinc\tdx", sbhand, 1, 1, /* 0x42 */ + "\tinc\tbx", sbhand, 1, 1, /* 0x43 */ + "\tinc\tsp", sbhand, 1, 1, /* 0x44 */ + "\tinc\tbp", sbhand, 1, 1, /* 0x45 */ + "\tinc\tsi", sbhand, 1, 1, /* 0x46 */ + "\tinc\tdi", sbhand, 1, 1, /* 0x47 */ + "\tdec\tax", sbhand, 1, 1, /* 0x48 */ + "\tdec\tcx", sbhand, 1, 1, /* 0x49 */ + "\tdec\tdx", sbhand, 1, 1, /* 0x4a */ + "\tdec\tbx", sbhand, 1, 1, /* 0x4b */ + "\tdec\tsp", sbhand, 1, 1, /* 0x4c */ + "\tdec\tbp", sbhand, 1, 1, /* 0x4d */ + "\tdec\tsi", sbhand, 1, 1, /* 0x4e */ + "\tdec\tdi", sbhand, 1, 1, /* 0x4f */ + "\tpush\tax", sbhand, 1, 1, /* 0x50 */ + "\tpush\tcx", sbhand, 1, 1, /* 0x51 */ + "\tpush\tdx", sbhand, 1, 1, /* 0x52 */ + "\tpush\tbx", sbhand, 1, 1, /* 0x53 */ + "\tpush\tsp", sbhand, 1, 1, /* 0x54 */ + "\tpush\tbp", sbhand, 1, 1, /* 0x55 */ + "\tpush\tsi", sbhand, 1, 1, /* 0x56 */ + "\tpush\tdi", sbhand, 1, 1, /* 0x57 */ + "\tpop\tax", sbhand, 1, 1, /* 0x58 */ + "\tpop\tcx", sbhand, 1, 1, /* 0x59 */ + "\tpop\tdx", sbhand, 1, 1, /* 0x5a */ + "\tpop\tbx", sbhand, 1, 1, /* 0x5b */ + "\tpop\tsp", sbhand, 1, 1, /* 0x5c */ + "\tpop\tbp", sbhand, 1, 1, /* 0x5d */ + "\tpop\tsi", sbhand, 1, 1, /* 0x5e */ + "\tpop\tdi", sbhand, 1, 1, /* 0x5f */ + NULL, dfhand, 0, 0, /* 0x60 */ + NULL, dfhand, 0, 0, /* 0x61 */ + NULL, dfhand, 0, 0, /* 0x62 */ + NULL, dfhand, 0, 0, /* 0x63 */ + NULL, dfhand, 0, 0, /* 0x64 */ + NULL, dfhand, 0, 0, /* 0x65 */ + NULL, dfhand, 0, 0, /* 0x66 */ + NULL, dfhand, 0, 0, /* 0x67 */ + NULL, dfhand, 0, 0, /* 0x68 */ + NULL, dfhand, 0, 0, /* 0x69 */ + NULL, dfhand, 0, 0, /* 0x6a */ + NULL, dfhand, 0, 0, /* 0x6b */ + NULL, dfhand, 0, 0, /* 0x6c */ + NULL, dfhand, 0, 0, /* 0x6d */ + NULL, dfhand, 0, 0, /* 0x6e */ + NULL, dfhand, 0, 0, /* 0x6f */ + "\tjo", sjhand, 2, 2, /* 0x70 */ + "\tjno", sjhand, 2, 2, /* 0x71 */ + "\tjc", sjhand, 2, 2, /* 0x72 */ + "\tjnc", sjhand, 2, 2, /* 0x73 */ + "\tjz", sjhand, 2, 2, /* 0x74 */ + "\tjnz", sjhand, 2, 2, /* 0x75 */ + "\tjna", sjhand, 2, 2, /* 0x76 */ + "\tja", sjhand, 2, 2, /* 0x77 */ + "\tjs", sjhand, 2, 2, /* 0x78 */ + "\tjns", sjhand, 2, 2, /* 0x79 */ + "\tjp", sjhand, 2, 2, /* 0x7a */ + "\tjnp", sjhand, 2, 2, /* 0x7b */ + "\tjl", sjhand, 2, 2, /* 0x7c */ + "\tjnl", sjhand, 2, 2, /* 0x7d */ + "\tjng", sjhand, 2, 2, /* 0x7e */ + "\tjg", sjhand, 2, 2, /* 0x7f */ + AMBIG, imhand, 3, 5, /* 0x80 */ + AMBIG, imhand, 4, 6, /* 0x81 */ + AMBIG, imhand, 3, 5, /* 0x82 */ + AMBIG, imhand, 3, 5, /* 0x83 */ + TEST, mvhand, 2, 4, /* 0x84 */ + TEST, mvhand, 2, 4, /* 0x85 */ + "\txchg", mvhand, 2, 4, /* 0x86 */ + "\txchg", mvhand, 2, 4, /* 0x87 */ + MOV, mvhand, 2, 4, /* 0x88 */ + MOV, mvhand, 2, 4, /* 0x89 */ + MOV, mvhand, 2, 4, /* 0x8a */ + MOV, mvhand, 2, 4, /* 0x8b */ + MOV, mshand, 2, 4, /* 0x8c */ + "\tlea", mvhand, 2, 4, /* 0x8d */ + MOV, mshand, 2, 4, /* 0x8e */ + "\tpop", pohand, 2, 4, /* 0x8f */ + "\tnop", sbhand, 1, 1, /* 0x90 */ + "\txchg\tax,cx", sbhand, 1, 1, /* 0x91 */ + "\txchg\tax,dx", sbhand, 1, 1, /* 0x92 */ + "\txchg\tax,bx", sbhand, 1, 1, /* 0x93 */ + "\txchg\tax,sp", sbhand, 1, 1, /* 0x94 */ + "\txchg\tax,bp", sbhand, 1, 1, /* 0x95 */ + "\txchg\tax,si", sbhand, 1, 1, /* 0x96 */ + "\txchg\tax,di", sbhand, 1, 1, /* 0x97 */ + "\tcbw", sbhand, 1, 1, /* 0x98 */ + "\tcwd", sbhand, 1, 1, /* 0x99 */ + "\tcalli", cihand, 5, 5, /* 0x9a */ + "\twait", sbhand, 1, 1, /* 0x9b */ + "\tpushf", sbhand, 1, 1, /* 0x9c */ + "\tpopf", sbhand, 1, 1, /* 0x9d */ + "\tsahf", sbhand, 1, 1, /* 0x9e */ + "\tlahf", sbhand, 1, 1, /* 0x9f */ + MOV, mqhand, 3, 3, /* 0xa0 */ + MOV, mqhand, 3, 3, /* 0xa1 */ + MOV, mqhand, 3, 3, /* 0xa2 */ + MOV, mqhand, 3, 3, /* 0xa3 */ + "\tmovb", sbhand, 1, 1, /* 0xa4 */ + "\tmovw", sbhand, 1, 1, /* 0xa5 */ + "\tcmpb", sbhand, 1, 1, /* 0xa6 */ + "\tcmpw", sbhand, 1, 1, /* 0xa7 */ + TEST, tqhand, 2, 2, /* 0xa8 */ + TEST, tqhand, 3, 3, /* 0xa9 */ + "\tstob", sbhand, 1, 1, /* 0xaa */ + "\tstow", sbhand, 1, 1, /* 0xab */ + "\tlodb", sbhand, 1, 1, /* 0xac */ + "\tlodw", sbhand, 1, 1, /* 0xad */ + "\tscab", sbhand, 1, 1, /* 0xae */ + "\tscaw", sbhand, 1, 1, /* 0xaf */ + "\tmov\tal,", mihand, 2, 2, /* 0xb0 */ + "\tmov\tcl,", mihand, 2, 2, /* 0xb1 */ + "\tmov\tdl,", mihand, 2, 2, /* 0xb2 */ + "\tmov\tbl,", mihand, 2, 2, /* 0xb3 */ + "\tmov\tah,", mihand, 2, 2, /* 0xb4 */ + "\tmov\tch,", mihand, 2, 2, /* 0xb5 */ + "\tmov\tdh,", mihand, 2, 2, /* 0xb6 */ + "\tmov\tbh,", mihand, 2, 2, /* 0xb7 */ + "\tmov\tax,", mihand, 3, 3, /* 0xb8 */ + "\tmov\tcx,", mihand, 3, 3, /* 0xb9 */ + "\tmov\tdx,", mihand, 3, 3, /* 0xba */ + "\tmov\tbx,", mihand, 3, 3, /* 0xbb */ + "\tmov\tsp,", mihand, 3, 3, /* 0xbc */ + "\tmov\tbp,", mihand, 3, 3, /* 0xbd */ + "\tmov\tsi,", mihand, 3, 3, /* 0xbe */ + "\tmov\tdi,", mihand, 3, 3, /* 0xbf */ + NULL, dfhand, 0, 0, /* 0xc0 */ + NULL, dfhand, 0, 0, /* 0xc1 */ + "\tret", rehand, 3, 3, /* 0xc2 */ + "\tret", sbhand, 1, 1, /* 0xc3 */ + "\tles", mvhand, 2, 4, /* 0xc4 */ + "\tlds", mvhand, 2, 4, /* 0xc5 */ + MOV, mmhand, 3, 5, /* 0xc6 */ + MOV, mmhand, 4, 6, /* 0xc7 */ + NULL, dfhand, 0, 0, /* 0xc8 */ + NULL, dfhand, 0, 0, /* 0xc9 */ + "\treti", rehand, 3, 3, /* 0xca */ + "\treti", sbhand, 1, 1, /* 0xcb */ + "\tint", sbhand, 1, 1, /* 0xcc */ + "\tint", inhand, 2, 2, /* 0xcd */ + "\tinto", sbhand, 1, 1, /* 0xce */ + "\tiret", sbhand, 1, 1, /* 0xcf */ + AMBIG, srhand, 2, 4, /* 0xd0 */ + AMBIG, srhand, 2, 4, /* 0xd1 */ + AMBIG, srhand, 2, 4, /* 0xd2 */ + AMBIG, srhand, 2, 4, /* 0xd3 */ + "\taam", aahand, 2, 2, /* 0xd4 */ + "\taad", aahand, 2, 2, /* 0xd5 */ + NULL, dfhand, 0, 0, /* 0xd6 */ + "\txlat", sbhand, 1, 1, /* 0xd7 */ + ESC, eshand, 2, 2, /* 0xd8 */ + ESC, eshand, 2, 2, /* 0xd9 */ + ESC, eshand, 2, 2, /* 0xda */ + ESC, eshand, 2, 2, /* 0xdb */ + ESC, eshand, 2, 2, /* 0xdc */ + ESC, eshand, 2, 2, /* 0xdd */ + ESC, eshand, 2, 2, /* 0xde */ + ESC, eshand, 2, 2, /* 0xdf */ + "\tloopne", sjhand, 2, 2, /* 0xe0 */ + "\tloope", sjhand, 2, 2, /* 0xe1 */ + "\tloop", sjhand, 2, 2, /* 0xe2 */ + "\tjcxz", sjhand, 2, 2, /* 0xe3 */ + "\tin", iohand, 2, 2, /* 0xe4 */ + "\tinw", iohand, 2, 2, /* 0xe5 */ + "\tout", iohand, 2, 2, /* 0xe6 */ + "\toutw", iohand, 2, 2, /* 0xe7 */ + "\tcall", ljhand, 3, 3, /* 0xe8 */ + "\tjmp", ljhand, 3, 3, /* 0xe9 */ + "\tjmpi", cihand, 5, 5, /* 0xea */ + "\tj", sjhand, 2, 2, /* 0xeb */ + "\tin", sbhand, 1, 1, /* 0xec */ + "\tinw", sbhand, 1, 1, /* 0xed */ + "\tout", sbhand, 1, 1, /* 0xee */ + "\toutw", sbhand, 1, 1, /* 0xef */ + "\tlock", sbhand, 1, 1, /* 0xf0 */ + NULL, dfhand, 0, 0, /* 0xf1 */ + "\trepnz", sbhand, 1, 1, /* 0xf2 */ + "\trepz", sbhand, 1, 1, /* 0xf3 */ + "\thlt", sbhand, 1, 1, /* 0xf4 */ + "\tcmc", sbhand, 1, 1, /* 0xf5 */ + AMBIG, mahand, 2, 5, /* 0xf6 */ + AMBIG, mahand, 2, 6, /* 0xf7 */ + "\tclc", sbhand, 1, 1, /* 0xf8 */ + "\tstc", sbhand, 1, 1, /* 0xf9 */ + "\tcli", sbhand, 1, 1, /* 0xfa */ + "\tsti", sbhand, 1, 1, /* 0xfb */ + "\tcld", sbhand, 1, 1, /* 0xfc */ + "\tstd", sbhand, 1, 1, /* 0xfd */ + AMBIG, mjhand, 2, 4, /* 0xfe */ + AMBIG, mjhand, 2, 4 /* 0xff */ + }; + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This simple routine returns the name field of a symbol * + * table entry as a printable string. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +char * +getnam(k) + + register int k; + +{/* * * * * * * * * * START OF getnam() * * * * * * * * * */ + + register int j; + static char a[9]; + + for (j = 0; j < 8; ++j) + if ( ! symtab[k].n_name[j] ) + break; + else + a[j] = symtab[k].n_name[j]; + + a[j] = '\0'; + + return (a); + +}/* * * * * * * * * * * END OF getnam() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This function is responsible for mucking through the * + * relocation table in search of externally referenced * + * symbols to be output as operands. It accepts two long * + * arguments: the code-segment location at which an extern * + * reference is expected, and the offset value which is * + * embedded in the object code and used at link time to * + * bias the external value. In the most typical case, the * + * function will be called by lookup(), which always makes * + * a check for external names before searching the symbol * + * table proper. However, it may also be called directly * + * by any function (such as the move-immediate handler) * + * which wants to make an independent check for externals. * + * The caller is expected to supply, as the third argument * + * to the function, a pointer to a character buffer large * + * enough to hold any possible output string. Lookext() * + * will fill this buffer and return a logical TRUE if it * + * finds an extern reference; otherwise, it will return a * + * logical FALSE, leaving the buffer undisturbed. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +int +lookext(off,loc,buf) + + long off, loc; + char *buf; + +{/* * * * * * * * * * START OF lookext() * * * * * * * * * */ + + register int k; + char c[16]; + + if ((loc != -1L) && (relptr >= 0)) + for (k = 0; k <= relptr; ++k) + if ((relo[k].r_vaddr == loc) + && (relo[k].r_symndx < S_BSS)) + { + strcpy(buf,getnam(relo[k].r_symndx)); + if (off) + { + if (off < 0) + sprintf(c,"%ld",off); + else + sprintf(c,"+%ld",off); + strcat(buf,c); + } + return (1); + } + + return (0); + +}/* * * * * * * * * * END OF lookext() * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This function finds an entry in the symbol table by * + * value. Its input is a (long) machine address, and its * + * output is a pointer to a string containing the corre- * + * sponding symbolic name. The function first searches the * + * relocation table for a possible external reference; if * + * none is found, a linear search of the symbol table is * + * undertaken. If no matching symbol has been found at the * + * end of these searches, the function returns a pointer * + * to a string containing the ASCII equivalent of the ad- * + * dress which was to be located, so that, regardless of * + * the success of the search, the function's return value * + * is suitable for use as a memory-reference operand. The * + * caller specifies the type of symbol to be found (text, * + * data, bss, undefined, absolute, or common) by means of * + * the function's second parameter. The third parameter * + * specifies the format to be used in the event of a nu- * + * meric output: zero for absolute format, one for short * + * relative format, two for long relative format. The * + * fourth parameter is the address which would appear in * + * the relocation table for the reference in question, or * + * -1 if the relocation table is not to be searched. The * + * function attempts to apply a certain amount of intelli- * + * gence in its selection of symbols, so it is possible * + * that, in the absence of a type match, a symbol of the * + * correct value but different type will be returned. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +char * +lookup(addr,type,kind,ext) + + long addr; /* Machine address to be located */ + + int type, /* Type of symbol to be matched */ + kind; /* Addressing output mode to use */ + + long ext; /* Value for extern ref, if any */ + +{/* * * * * * * * * * START OF lookup() * * * * * * * * * */ + + register int j, k; + static char b[64]; + + struct + { + int i; + int t; + } + best; + + if (lookext(addr,ext,b)) + return (b); + + if (segflg) + if (segflg & 1) + type = N_TEXT; + else + type = N_DATA; + + for (k = 0, best.i = -1; k <= symptr; ++k) + if (symtab[k].n_value == addr) + if ((j = symtab[k].n_sclass & N_SECT) == type) + { + best.t = j; + best.i = k; + break; + } + else if (segflg || (HDR.a_flags & A_SEP)) + continue; + else if (best.i < 0) + best.t = j, best.i = k; + else if (symrank[type][j] > symrank[type][best.t]) + best.t = j, best.i = k; + + if (best.i >= 0) + return (getnam(best.i)); + + if (kind == LOOK_ABS) + sprintf(b,"0x%05.5x",addr); + else + { + long x = addr - (PC - kind); + if (x < 0) + sprintf(b,".%ld",x); + else + sprintf(b,".+%ld",x); + } + + return (b); + +}/* * * * * * * * * * * END OF lookup() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This function translates an 8088 addressing mode byte * + * to an equivalent assembler string, returning a pointer * + * thereto. If necessary, it performs successive inputs * + * of bytes from the object file in order to obtain offset * + * data, adjusting PC accordingly. (The addressing mode * + * byte appears in several 8088 opcodes; it is used to * + * specify source and destination operand locations.) The * + * third argument to the function is zero if the standard * + * registers are to be used, or eight if the segment reg- * + * isters are to be used; these constants are defined sym- * + * bolically in dis.h. NOTE: The mtrans() function must * + * NEVER be called except immediately after fetching the * + * mode byte. If any additional object bytes are fetched * + * after the fetch of the mode byte, mtrans() will not * + * produce correct output! * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +char * +mtrans(c,m,type) + + register int c; /* Primary instruction byte */ + register int m; /* Addressing mode byte */ + + int type; /* Type code: standard or seg */ + +{/* * * * * * * * * * START OF mtrans() * * * * * * * * * */ + + unsigned long pc; + int offset, oflag, dir, w, mod, reg, rm; + static char a[100]; + static char b[30]; + + offset = 0; + dir = c & 2; + w = c & 1; + mod = (m & 0xc0) >> 6; + reg = (m & 0x38) >> 3; + rm = m & 7; + pc = PC + 1; + + if (type) + w = 1; + + if ((oflag = mod) > 2) + oflag = 0; + + if (oflag) + { + int j, k; + if (oflag == 2) + { + FETCH(j); + FETCH(k); + offset = (k << 8) | j; + } + else + { + FETCH(j); + if (j & 0x80) + k = 0xff00; + else + k = 0; + offset = k | j; + } + } + + if (dir) + { + strcpy(a,REGS[type + ((w << 3) | reg)]); + strcat(a,","); + switch (mod) + { + case 0 : + if (rm == 6) + { + int j, k; + FETCH(j); + FETCH(k); + offset = (k << 8) | j; + strcat(a, + lookup((long)(offset),N_DATA,LOOK_ABS,pc)); + } + else + { + sprintf(b,"(%s)",REGS0[rm]); + strcat(a,b); + } + break; + case 1 : + case 2 : + if (mod == 1) + strcat(a,"*"); + else + strcat(a,"#"); + sprintf(b,"%d(",offset); + strcat(a,b); + strcat(a,REGS1[rm]); + strcat(a,")"); + break; + case 3 : + strcat(a,REGS[(w << 3) | rm]); + break; + } + } + else + { + switch (mod) + { + case 0 : + if (rm == 6) + { + int j, k; + FETCH(j); + FETCH(k); + offset = (k << 8) | j; + strcpy(a, + lookup((long)(offset),N_DATA,LOOK_ABS,pc)); + } + else + { + sprintf(b,"(%s)",REGS0[rm]); + strcpy(a,b); + } + break; + case 1 : + case 2 : + if (mod == 1) + strcpy(a,"*"); + else + strcpy(a,"#"); + sprintf(b,"%d(",offset); + strcat(a,b); + strcat(a,REGS1[rm]); + strcat(a,")"); + break; + case 3 : + strcpy(a,REGS[(w << 3) | rm]); + break; + } + strcat(a,","); + strcat(a,REGS[type + ((w << 3) | reg)]); + } + + return (a); + +}/* * * * * * * * * * * END OF mtrans() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This simple routine truncates a string returned by the * + * mtrans() function, removing its source operand. This is * + * useful in handlers which ignore the "reg" field of the * + * mode byte. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +mtrunc(a) + + register char *a; /* Ptr. to string to truncate */ + +{/* * * * * * * * * * START OF mtrunc() * * * * * * * * * */ + + register int k; + + for (k = strlen(a) - 1; k >= 0; --k) + if (a[k] == ',') + { + a[k] = '\0'; + break; + } + +}/* * * * * * * * * * * END OF mtrunc() * * * * * * * * * * */ + + diff --git a/part01 b/part01 new file mode 100644 index 0000000..f78b652 --- /dev/null +++ b/part01 @@ -0,0 +1,1448 @@ +Subject: v15i006: Symbolic disassembler for PC/IX, Part01/02 +Newsgroups: comp.sources.unix +Sender: sources +Approved: rsalz@uunet.UU.NET + +Submitted-by: "G. M. Harding" +Posting-number: Volume 15, Issue 6 +Archive-name: dis88/part01 + +[ I packed up the archives and turned the formatted manpage + into an unformatted one. --r$ ] + + "Dis88" is a symbolic disassembler for the Intel 8088 CPU, + designed to run under the PC/IX operating system on an IBM XT + or fully-compatible clone. Its output is in the format of, and + is completely compatible with, the PC/IX assembler, "as". The + program is copyrighted by its author, but may be copied and re- + distributed freely provided that complete source code, with all + copyright notices, accompanies any distribution. This provision + also applies to any modifications you may make. You are urged + to comment such changes, giving, as a miminum, your name and + complete address. + + --- + G. M. HARDING + POB 4142 + Santa Clara CA 95054-0142 + +#! /bin/sh +# This is a shell archive. Remove anything before this line, then unpack +# it by saving it into a file and typing "sh file". To overwrite existing +# files, type "sh file -c". You can also feed this as standard input via +# unshar, or by typing "sh 'MANIFEST' <<'END_OF_FILE' +X File Name Archive # Description +X----------------------------------------------------------- +X MANIFEST 1 +X Makefile 1 +X README 1 +X dis.h 1 +X dis88.1 1 +X disfp.c 1 +X dishand.c 2 +X dismain.c 1 +X disrel.c 1 +X distabs.c 2 +END_OF_FILE +if test 406 -ne `wc -c <'MANIFEST'`; then + echo shar: \"'MANIFEST'\" unpacked with wrong size! +fi +# end of 'MANIFEST' +fi +if test -f 'Makefile' -a "${1}" != "-c" ; then + echo shar: Will not clobber existing file \"'Makefile'\" +else +echo shar: Extracting \"'Makefile'\" \(1593 characters\) +sed "s/^X//" >'Makefile' <<'END_OF_FILE' +X# @(#) Makefile, Ver. 2.1 created 00:00:00 87/09/01 +X# Makefile for 8088 symbolic disassembler +X +X# Copyright (C) 1987 G. M. Harding, all rights reserved. +X# Permission to copy and redistribute is hereby granted, +X# provided full source code, with all copyright notices, +X# accompanies any redistribution. +X +X# This Makefile automates the process of compiling and linking +X# a symbolic object-file disassembler program for the Intel +X# 8088 CPU. Relatively machine-independent code is contained in +X# the file dismain.c; lookup tables and handler routines, which +X# are by their nature machine-specific, are contained in two +X# files named distabs.c and dishand.c, respectively. (A third +X# machine-specific file, disfp.c, contains handler routines for +X# floating-point coprocessor opcodes.) A header file, dis.h, +X# attempts to mediate between the machine-specific and machine- +X# independent portions of the code. An attempt has been made to +X# isolate machine dependencies and to deal with them in fairly +X# straightforward ways. Thus, it should be possible to target a +X# different CPU by rewriting the handler routines and changing +X# the initialization data in the lookup tables. It should not +X# be necessary to alter the formats of the tables. +X +OBJ = disrel.o dismain.o distabs.o dishand.o disfp.o +X +dis88 : $(OBJ) +X ld -i -s -o dis88 /lib/crt0.o $(OBJ) -lc +X size dis88 +X @echo "\07Build of 'dis88' complete." > /dev/tty +X +X.c.o : +X cc -O -c $< +X chmod 600 $*.o +X +disrel.o : disrel.c +X +dismain.o : dismain.c dis.h +X +distabs.o : distabs.c dis.h +X +dishand.o : dishand.c dis.h +X +disfp.o : disfp.c dis.h +X +END_OF_FILE +if test 1593 -ne `wc -c <'Makefile'`; then + echo shar: \"'Makefile'\" unpacked with wrong size! +fi +# end of 'Makefile' +fi +if test -f 'README' -a "${1}" != "-c" ; then + echo shar: Will not clobber existing file \"'README'\" +else +echo shar: Extracting \"'README'\" \(4898 characters\) +sed "s/^X//" >'README' <<'END_OF_FILE' +X dis88 +X Beta Release +X 87/09/01 +X --- +X G. M. HARDING +X POB 4142 +X Santa Clara CA 95054-0142 +X +X +X "Dis88" is a symbolic disassembler for the Intel 8088 CPU, +X designed to run under the PC/IX operating system on an IBM XT +X or fully-compatible clone. Its output is in the format of, and +X is completely compatible with, the PC/IX assembler, "as". The +X program is copyrighted by its author, but may be copied and re- +X distributed freely provided that complete source code, with all +X copyright notices, accompanies any distribution. This provision +X also applies to any modifications you may make. You are urged +X to comment such changes, giving, as a miminum, your name and +X complete address. +X +X This release of the program is a beta release, which means +X that it has been extensively, but not exhaustively, tested. +X User comments, recommendations, and bug fixes are welcome. The +X principal features of the current release are: +X +X (a) The ability to disassemble any file in PC/IX object +X format, making full use of symbol and relocation information if +X it is present, regardless of whether the file is executable or +X linkable, and regardless of whether it has continuous or split +X I/D space; +X +X (b) Automatic generation of synthetic labels when no sym- +X bol table is available; and +X +X (c) Optional output of address and object-code informa- +X tion as assembler comment text. +X +X Limitations of the current release are: +X +X (a) Numeric co-processor (i.e., 8087) mnemonics are not +X supported. Instructions for the co-processor are disassembled +X as CPU escape sequences, or as interrupts, depending on how +X they were assembled in the first place. This limitation will be +X addressed in a future release. +X +X (b) Symbolic references within the object file's data +X segment are not supported. Thus, for example, if a data segment +X location is initialized to point to a text segment address, no +X reference to a text segment symbol will be detected. This limi- +X tation is likely to remain in future releases, because object +X code does not, in most cases, contain sufficient information to +X allow meaningful interpretation of pure data. (Note, however, +X that symbolic references to the data segment from within the +X text segment are always supported.) +X +X As a final caveat, be aware that the PC/IX assembler does +X not recognize the "esc" mnemonic, even though it refers to a +X completely valid CPU operation which is documented in all the +X Intel literature. Thus, the corresponding opcodes (0xd8 through +X 0xdf) are disassembled as .byte directives. For reference, how- +X ever, the syntactically-correct "esc" instruction is output as +X a comment. +X +X To build the disassembler program, transfer all the source +X files, together with the Makefile, to a suitable (preferably +X empty) PC/IX directory. Then, simply type "make". +X +X To use dis88, place it in a directory which appears in +X your $PATH list. It may then be invoked by name from whatever +X directory you happen to be in. As a minimum, the program must +X be invoked with one command-line argument: the name of the ob- +X ject file to be disassembled. (Dis88 will complain if the file +X specified is not an object file.) Optionally, you may specify +X an output file; stdout is the default. One command-line switch +X is available: "-o", which makes the program display addresses +X and object code along with its mnemonic disassembly. +X +X The "-o" option is useful primarily for verifying the cor- +X rectness of the program's output. In particular, it may be used +X to check the accuracy of local relative jump opcodes. These +X jumps often target local labels, which are lost at assembly +X time; thus, the disassembly may contain cryptic instructions +X like "jnz .+39". As a user convenience, all relative jump and +X call opcodes are output with a comment which identifies the +X physical target address. +X +X By convention, the release level of the program as a whole +X is the SID of the file disrel.c, and this SID string appears in +X each disassembly. Release 2.1 of the program is the first beta +X release to be distributed on Usenet. +X +END_OF_FILE +if test 4898 -ne `wc -c <'README'`; then + echo shar: \"'README'\" unpacked with wrong size! +fi +# end of 'README' +fi +if test -f 'dis.h' -a "${1}" != "-c" ; then + echo shar: Will not clobber existing file \"'dis.h'\" +else +echo shar: Extracting \"'dis.h'\" \(7563 characters\) +sed "s/^X//" >'dis.h' <<'END_OF_FILE' +X /* +X ** @(#) dis.h, Ver. 2.1 created 00:00:00 87/09/01 +X */ +X +X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +X * * +X * Copyright (C) 1987 G. M. Harding, all rights reserved * +X * * +X * Permission to copy and redistribute is hereby granted, * +X * provided full source code, with all copyright notices, * +X * accompanies any redistribution. * +X * * +X * This file contains declarations and definitions used by * +X * the 8088 disassembler program. The program was designed * +X * for execution on a machine of its own type (i.e., it is * +X * not designed as a cross-disassembler); consequently, A * +X * SIXTEEN-BIT INTEGER SIZE HAS BEEN ASSUMED. This assump- * +X * tion is not particularly important, however, except in * +X * the machine-specific portions of the code (i.e., the * +X * handler routines and the optab[] array). It should be * +X * possible to override this assumption, for execution on * +X * 32-bit machines, by use of a pre-processor directive * +X * (see below); however, this has not been tested. * +X * * +X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +X +X#include /* System standard I/O definitions */ +X#include /* System file-control definitions */ +X#include /* Object file format definitions */ +X +X#if i8086 || i8088 /* For CPU's with 16-bit integers */ +X#undef int +X#else /* Defaults (for 32-bit CPU types) */ +X#define int short +X#endif +X +X#define MAXSYM 1500 /* Maximum entries in symbol table */ +X +extern struct nlist /* Array to hold the symbol table */ +X symtab[MAXSYM]; +X +extern struct reloc /* Array to hold relocation table */ +X relo[MAXSYM]; +X +extern int symptr; /* Index into the symtab[] array */ +X +extern int relptr; /* Index into the relo[] array */ +X +struct opcode /* Format for opcode data records */ +X { +X char *text; /* Pointer to mnemonic text */ +X void (*func)(); /* Pointer to handler routine */ +X unsigned min; /* Minimum # of object bytes */ +X unsigned max; /* Maximum # of object bytes */ +X }; +X +extern struct opcode /* Array to hold the opcode table */ +X optab[256]; +X +X /* +X +--------------------------------------------- +X | The following functions are the specialized +X | handlers for each opcode group. They are, of +X | course, highly MACHINE-SPECIFIC. Each entry +X | in the opcode[] array contains a pointer to +X | one of these handlers. The handlers in the +X | first group are in dishand.c; those in the +X | second group are in disfp.c. +X +--------------------------------------------- +X */ +X +extern void dfhand(), /* Default handler routine */ +X sbhand(), /* Single-byte handler */ +X aohand(), /* Arithmetic-op handler */ +X sjhand(), /* Short-jump handler */ +X imhand(), /* Immediate-operand handler */ +X mvhand(), /* Simple move handler */ +X mshand(), /* Segreg-move handler */ +X pohand(), /* Pop memory/reg handler */ +X cihand(), /* Intersegment call handler */ +X mihand(), /* Immediate-move handler */ +X mqhand(), /* Quick-move handler */ +X tqhand(), /* Quick-test handler */ +X rehand(), /* Return handler */ +X mmhand(), /* Move-to-memory handler */ +X srhand(), /* Shift and rotate handler */ +X aahand(), /* ASCII-adjust handler */ +X iohand(), /* Immediate port I/O handler */ +X ljhand(), /* Long-jump handler */ +X mahand(), /* Misc. arithmetic handler */ +X mjhand(); /* Miscellaneous jump handler */ +X +extern void eshand(), /* Bus-escape opcode handler */ +X fphand(), /* Floating-point handler */ +X inhand(); /* Interrupt-opcode handler */ +X +extern char *REGS[]; /* Table of register names */ +X +extern char *REGS0[]; /* Mode 0 register name table */ +X +extern char *REGS1[]; /* Mode 1 register name table */ +X +X#define AL REGS[0] /* CPU register manifests */ +X#define CL REGS[1] +X#define DL REGS[2] +X#define BL REGS[3] +X#define AH REGS[4] +X#define CH REGS[5] +X#define DH REGS[6] +X#define BH REGS[7] +X#define AX REGS[8] +X#define CX REGS[9] +X#define DX REGS[10] +X#define BX REGS[11] +X#define SP REGS[12] +X#define BP REGS[13] +X#define SI REGS[14] +X#define DI REGS[15] +X#define ES REGS[16] +X#define CS REGS[17] +X#define SS REGS[18] +X#define DS REGS[19] +X#define BX_SI REGS0[0] +X#define BX_DI REGS0[1] +X#define BP_SI REGS0[2] +X#define BP_DI REGS0[3] +X +extern int symrank[6][6]; /* Symbol type/rank matrix */ +X +extern unsigned long PC; /* Current program counter */ +X +extern int segflg; /* Flag: segment override in effect */ +X +extern int objflg; /* Flag: output object as a comment */ +X +X#define OBJMAX 8 /* Size of the object code buffer */ +X +extern unsigned char /* Internal buffer for object code */ +X objbuf[OBJMAX]; +X +extern void objini(), /* Object-buffer init routine */ +X objout(); /* Object-code output routine */ +X +extern int objptr; /* Index into the objbuf[] array */ +X +extern void badseq(); /* Bad-code-sequence function */ +X +extern char *getnam(); /* Symbol-name string function */ +X +extern char *lookup(); /* Symbol-table lookup function */ +X +extern int lookext(); /* Extern-definition lookup routine */ +X +extern char *mtrans(); /* Interpreter for the mode byte */ +X +extern void mtrunc(); /* Mode string truncator function */ +X +extern char ADD[], /* Opcode family mnemonic strings */ +X OR[], +X ADC[], +X SBB[], +X AND[], +X SUB[], +X XOR[], +X CMP[], +X NOT[], +X NEG[], +X MUL[], +X DIV[], +X MOV[], +X ESC[], +X TEST[], +X AMBIG[]; +X +extern char *OPFAM[]; /* Indexed mnemonic family table */ +X +extern struct exec HDR; /* Holds the object file's header */ +X +X#define LOOK_ABS 0 /* Arguments to lookup() function */ +X#define LOOK_REL 1 +X#define LOOK_LNG 2 +X +X#define TR_STD 0 /* Arguments to mtrans() function */ +X#define TR_SEG 8 +X +X /* Macro for byte input primitive */ +X#define FETCH(p) \ +X ++PC; p = getchar() & 0xff; objbuf[objptr++] = p +X +extern int close(); /* System file-close primitive */ +extern int fprintf(); /* Library file-output function */ +extern long lseek(); /* System file-position primitive */ +extern int open(); /* System file-open primitive */ +extern int printf(); /* Library output-format function */ +extern int read(); /* System file-read primitive */ +extern int sprintf(); /* Library string-output function */ +extern char *strcat(); /* Library string-join function */ +extern char *strcpy(); /* Library string-copy function */ +extern int strlen(); /* Library string-length function */ +X +X /* * * * * * * * * * * END OF dis.h * * * * * * * * * * */ +X +X +END_OF_FILE +if test 7563 -ne `wc -c <'dis.h'`; then + echo shar: \"'dis.h'\" unpacked with wrong size! +fi +# end of 'dis.h' +fi +if test -f 'dis88.1' -a "${1}" != "-c" ; then + echo shar: Will not clobber existing file \"'dis88.1'\" +else +echo shar: Extracting \"'dis88.1'\" \(6174 characters\) +sed "s/^X//" >'dis88.1' <<'END_OF_FILE' +X.TH dis88 1 LOCAL +X.SH "NAME" +dis88 \- 8088 symbolic disassembler +X.SH "SYNOPSIS" +X\fBdis88\fP [ -o ] ifile [ ofile ] +X.SH "DESCRIPTION" +Dis88 reads ifile, which must be in PC/IX a.out format. +It interprets the binary opcodes and data locations, and +writes corresponding assembler source code to stdout, or +to ofile if specified. The program's output is in the +format of, and fully compatible with, the PC/IX assembler, +as(1). If a symbol table is present in ifile, labels and +references will be symbolic in the output. If the input +file lacks a symbol table, the fact will be noted, and the +disassembly will proceed, with the disassembler generating +synthetic labels as needed. If the input file has split +I/D space, or if it is executable, the disassembler will +make all necessary adjustments in address-reference calculations. +X.PP +If the "-o" option appears, object code will be included +in comments during disassembly of the text segment. This +feature is used primarily for debugging the disassembler +itself, but may provide information of passing interest +to users. +X.PP +The program always outputs the current machine address +before disassembling an opcode. If a symbol table is +present, this address is output as an assembler comment; +otherwise, it is incorporated into the synthetic label +which is generated internally. Since relative jumps, +especially short ones, may target unlabelled locations, +the program always outputs the physical target address +as a comment, to assist the user in following the code. +X.PP +The text segment of an object file is always padded to +an even machine address. In addition, if the file has +split I/D space, the text segment will be padded to a +paragraph boundary (i.e., an address divisible by 16). +As a result of this padding, the disassembler may produce +a few spurious, but harmless, instructions at the +end of the text segment. +X.PP +Disassembly of the data segment is a difficult matter. +The information to which initialized data refers cannot +be inferred from context, except in the special case +of an external data or address reference, which will be +reflected in the relocation table. Internal data and +address references will already be resolved in the object file, +and cannot be recreated. Therefore, the data +segment is disassembled as a byte stream, with long +stretches of null data represented by an appropriate +X".zerow" pseudo-op. This limitation notwithstanding, +labels (as opposed to symbolic references) are always +output at appropriate points within the data segment. +X.PP +If disassembly of the data segment is difficult, disassembly of the +bss segment is quite easy, because uninitialized data is all +zero by definition. No data +is output in the bss segment, but symbolic labels are +output as appropriate. +X.PP +XFor each opcode which takes an operand, a particular +symbol type (text, data, or bss) is appropriate. This +tidy correspondence is complicated somewhat, however, +by the existence of assembler symbolic constants and +segment override opcodes. Therefore, the disassembler's +symbol lookup routine attempts to apply a certain amount +of intelligence when it is asked to find a symbol. If +it cannot match on a symbol of the preferred type, it +may return a symbol of some other type, depending on +preassigned (and somewhat arbitrary) rankings within +each type. Finally, if all else fails, it returns a +string containing the address sought as a hex constant; +this behavior allows calling routines to use the output +of the lookup function regardless of the success of its +search. +X.PP +It is worth noting, at this point, that the symbol lookup +routine operates linearly, and has not been optimized in +any way. Execution time is thus likely to increase +geometrically with input file size. The disassembler is +internally limited to 1500 symbol table entries and 1500 +relocation table entries; while these limits are generous +X(/unix, itself, has fewer than 800 symbols), they are not +guaranteed to be adequate in all cases. If the symbol +table or the relocation table overflows, the disassembly +aborts. +X.PP +XFinally, users should be aware of a bug in the assembler, +which causes it not to parse the "esc" mnemonic, even +though "esc" is a completely legitimate opcode which is +documented in all the Intel literature. To accommodate +this deficiency, the disassembler translates opcodes of +the "esc" family to .byte directives, but notes the +correct mnemonic in a comment for reference. +X.PP +In all cases, it should be possible to submit the output +of the disassembler program to the assembler, and assemble +it without error. In most cases, the resulting object +code will be identical to the original; in any event, it +will be functionally equivalent. +X.SH "SEE ALSO" +adb(1), as(1), cc(1), ld(1). +X.br +X"Assembler Reference Manual" in the PC/IX Programmer's +Guide. +X.SH "DIAGNOSTICS" +X"can't access input file" if the input file cannot be +found, opened, or read. +X.sp +X"can't open output file" if the output file cannot be +created. +X.sp +X"warning: host/cpu clash" if the program is run on a +machine with a different CPU. +X.sp +X"input file not in object format" if the magic number +does not correspond to that of a PC/IX object file. +X.sp +X"not an 8086/8088 object file" if the CPU ID of the +file header is incorrect. +X.sp +X"reloc table overflow" if there are more than 1500 +entries in the relocation table. +X.sp +X"symbol table overflow" if there are more than 1500 +entries in the symbol table. +X.sp +X"lseek error" if the input file is corrupted (should +never happen). +X.sp +X"warning: no symbols" if the symbol table is missing. +X.sp +X"can't reopen input file" if the input file is removed +or altered during program execution (should never happen). +X.SH "BUGS" +Numeric co-processor (i.e., 8087) mnemonics are not currently supported. +Instructions for the co-processor are +disassembled as CPU escape sequences, or as interrupts, +depending on how they were assembled in the first place. +X.sp +Despite the program's best efforts, a symbol retrieved +from the symbol table may sometimes be different from +the symbol used in the original assembly. +X.sp +The disassembler's internal tables are of fixed size, +and the program aborts if they overflow. +END_OF_FILE +if test 6174 -ne `wc -c <'dis88.1'`; then + echo shar: \"'dis88.1'\" unpacked with wrong size! +fi +# end of 'dis88.1' +fi +if test -f 'disfp.c' -a "${1}" != "-c" ; then + echo shar: Will not clobber existing file \"'disfp.c'\" +else +echo shar: Extracting \"'disfp.c'\" \(5589 characters\) +sed "s/^X//" >'disfp.c' <<'END_OF_FILE' +static char *sccsid = +X "@(#) disfp.c, Ver. 2.1 created 00:00:00 87/09/01"; +X +X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +X * * +X * Copyright (C) 1987 G. M. Harding, all rights reserved * +X * * +X * Permission to copy and redistribute is hereby granted, * +X * provided full source code, with all copyright notices, * +X * accompanies any redistribution. * +X * * +X * This file contains handler routines for the numeric op- * +X * codes of the 8087 co-processor, as well as a few other * +X * opcodes which are related to 8087 emulation. * +X * * +X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +X +X#include "dis.h" /* Disassembler declarations */ +X +X#define FPINT0 0xd8 /* Floating-point interrupts */ +X#define FPINT1 0xd9 +X#define FPINT2 0xda +X#define FPINT3 0xdb +X#define FPINT4 0xdc +X#define FPINT5 0xdd +X#define FPINT6 0xde +X#define FPINT7 0xdf +X +X /* Test for floating opcodes */ +X#define ISFLOP(x) \ +X (((x) >= FPINT0) && ((x) <= FPINT7)) +X +X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +X * * +X * This is the handler for the escape family of opcodes. * +X * These opcodes place the contents of a specified memory * +X * location on the system bus, for access by a peripheral * +X * or by a co-processor such as the 8087. (The 8087 NDP is * +X * accessed only via bus escapes.) Due to a bug in the * +X * PC/IX assembler, the "esc" mnemonic is not recognized; * +X * consequently, escape opcodes are disassembled as .byte * +X * directives, with the appropriate mnemonic and operand * +X * included as a comment. FOR NOW, those escape sequences * +X * corresponding to 8087 opcodes are treated as simple * +X * escapes. * +X * * +X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +X +void +eshand(j) +X +X register int j; /* Pointer to optab[] entry */ +X +X{/* * * * * * * * * * START OF eshand() * * * * * * * * * */ +X +X register char *a; +X register int k; +X +X objini(j); +X +X FETCH(k); +X +X a = mtrans((j & 0xfd),(k & 0xc7),TR_STD); +X +X mtrunc(a); +X +X printf("\t.byte\t0x%02.2x\t\t| esc\t%s\n",j,a); +X +X for (k = 1; k < objptr; ++k) +X printf("\t.byte\t0x%02.2x\n",objbuf[k]); +X +X}/* * * * * * * * * * * END OF eshand() * * * * * * * * * * */ +X +X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +X * * +X * This is the handler routine for floating-point opcodes. * +X * Since PC/IX must accommodate systems with and without * +X * 8087 co-processors, it allows floating-point operations * +X * to be initiated in either of two ways: by a software * +X * interrput whose type is in the range 0xd8 through 0xdf, * +X * or by a CPU escape sequence, which is invoked by an op- * +X * code in the same range. In either case, the subsequent * +X * byte determines the actual numeric operation to be per- * +X * formed. However, depending on the method of access, * +X * either one or two code bytes will precede that byte, * +X * and the fphand() routine has no way of knowing whether * +X * it was invoked by interrupt or by an escape sequence. * +X * Therefore, unlike all of the other handler routines ex- * +X * cept dfhand(), fphand() does not initialize the object * +X * buffer, leaving that chore to the caller. * +X * * +X * FOR NOW, fphand() does not disassemble floating-point * +X * opcodes to floating mnemonics, but simply outputs the * +X * object code as .byte directives. * +X * * +X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +X +void +fphand(j) +X +X register int j; /* Pointer to optab[] entry */ +X +X{/* * * * * * * * * * START OF fphand() * * * * * * * * * */ +X +X register int k; +X +X segflg = 0; +X +X FETCH(k); +X +X printf("\t.byte\t0x%02.2x\t\t| 8087 code sequence\n", +X objbuf[0]); +X +X for (k = 1; k < objptr; ++k) +X printf("\t.byte\t0x%02.2x\n",objbuf[k]); +X +X/* objout(); FOR NOW */ +X +X}/* * * * * * * * * * * END OF fphand() * * * * * * * * * * */ +X +X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +X * * +X * This is the handler for variable software interrupt * +X * opcodes. It is included in this file because PC/IX im- * +X * plements its software floating-point emulation by means * +X * of interrupts. Any interrupt in the range 0xd8 through * +X * 0xdf is an NDP-emulation interrupt, and is specially * +X * handled by the assembler. * +X * * +X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +X +void +inhand(j) +X +X register int j; /* Pointer to optab[] entry */ +X +X{/* * * * * * * * * * START OF inhand() * * * * * * * * * */ +X +X register int k; +X +X objini(j); +X +X FETCH(k); +X +X if (ISFLOP(k)) +X { +X fphand(k); +X return; +X } +X +X printf("%s\t%d\n",optab[j].text,k); +X +X objout(); +X +X}/* * * * * * * * * * * END OF inhand() * * * * * * * * * * */ +X +X +END_OF_FILE +if test 5589 -ne `wc -c <'disfp.c'`; then + echo shar: \"'disfp.c'\" unpacked with wrong size! +fi +# end of 'disfp.c' +fi +if test -f 'dismain.c' -a "${1}" != "-c" ; then + echo shar: Will not clobber existing file \"'dismain.c'\" +else +echo shar: Extracting \"'dismain.c'\" \(17384 characters\) +sed "s/^X//" >'dismain.c' <<'END_OF_FILE' +static char *sccsid = +X "@(#) dismain.c, Ver. 2.1 created 00:00:00 87/09/01"; +X +X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +X * * +X * Copyright (C) 1987 G. M. Harding, all rights reserved * +X * * +X * Permission to copy and redistribute is hereby granted, * +X * provided full source code, with all copyright notices, * +X * accompanies any redistribution. * +X * * +X * This file contains the source code for the machine- * +X * independent portions of a disassembler program to run * +X * in a Unix (System III) environment. It expects, as its * +X * input, a file in standard a.out format, optionally con- * +X * taining symbol table information. If a symbol table is * +X * present, it will be used in the disassembly; otherwise, * +X * all address references will be literal (absolute). * +X * * +X * The disassembler program was originally written for an * +X * Intel 8088 CPU. However, all details of the actual CPU * +X * architecture are hidden in three machine-specific files * +X * named distabs.c, dishand.c, and disfp.c (the latter * +X * file is specific to the 8087 numeric co-processor). The * +X * code in this file is generic, and should require mini- * +X * mal revision if a different CPU is to be targeted. If a * +X * different version of Unix is to be targeted, changes to * +X * this file may be necessary, and if a completely differ- * +X * ent OS is to be targeted, all bets are off. * +X * * +X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +X +X#include "dis.h" /* Disassembler declarations */ +X +extern char *release; /* Contains release string */ +X +static char *IFILE = NULL; /* Points to input file name */ +X +static char *OFILE = NULL; /* Points to output file name */ +X +static char *PRG; /* Name of invoking program */ +X +static unsigned long zcount; /* Consecutive "0" byte count */ +X +int objflg = 0; /* Flag: output object bytes */ +X +X#if unix && i8086 && ibmpc /* Set the CPU identifier */ +static int cpuid = 1; +X#else +static int cpuid = 0; +X#endif +X +X /* * * * * * * MISCELLANEOUS UTILITY FUNCTIONS * * * * * * */ +X +static void +usage(s) +X register char *s; +X{ +X fprintf(stderr,"\07usage: %s [-o] ifile [ofile]\n",s); +X exit(-1); +X} +X +static void +fatal(s,t) +X register char *s, *t; +X{ +X fprintf(stderr,"\07%s: %s\n",s,t); +X exit(-1); +X} +X +static void +zdump(beg) +X unsigned long beg; +X{ +X beg = PC - beg; +X if (beg > 1L) +X printf("\t.zerow\t%ld\n",(beg >> 1)); +X if (beg & 1L) +X printf("\t.byte\t0\n"); +X} +X +static char * +invoker(s) +X register char *s; +X{ +X extern int strlen(); +X register int k; +X +X k = strlen(s); +X +X while (k--) +X if (s[k] == '/') +X { +X s += k; +X ++s; +X break; +X } +X +X return (s); +X} +X +X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +X * * +X * This rather tricky routine supports the disdata() func- * +X * tion. Its job is to output the code for a sequence of * +X * data bytes whenever the object buffer is full, or when * +X * a symbolic label is to be output. However, it must also * +X * keep track of consecutive zero words so that lengthy * +X * stretches of null data can be compressed by the use of * +X * an appropriate assembler pseudo-op. It does this by * +X * setting and testing a file-wide flag which counts suc- * +X * cessive full buffers of null data. The function returns * +X * a logical TRUE value if it outputs anything, logical * +X * FALSE otherwise. (This enables disdata() to determine * +X * whether to output a new synthetic label when there is * +X * no symbol table.) * +X * * +X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +X +static int +objdump(c) +X +X register char *c; +X +X{/* * * * * * * * * * START OF objdump() * * * * * * * * * */ +X +X register int k; +X int retval = 0; +X +X if (objptr == OBJMAX) +X { +X for (k = 0; k < OBJMAX; ++k) +X if (objbuf[k]) +X break; +X if (k == OBJMAX) +X { +X zcount += k; +X objptr = 0; +X if (c == NULL) +X return (retval); +X } +X } +X +X if (zcount) +X { +X printf("\t.zerow\t%ld\n",(zcount >> 1)); +X ++retval; +X zcount = 0L; +X } +X +X if (objptr) +X { +X printf("\t.byte\t"); +X ++retval; +X } +X else +X return (retval); +X +X for (k = 0; k < objptr; ++k) +X { +X printf("0x%02.2x",objbuf[k]); +X if (k < (objptr - 1)) +X putchar(','); +X else +X putchar('\n'); +X } +X +X objptr = 0; +X +X return (retval); +X +X}/* * * * * * * * * * END OF objdump() * * * * * * * * * */ +X +X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +X * * +X * This routine, called at the beginning of the input * +X * cycle for each object byte, and before any interpreta- * +X * tion is attempted, searches the symbol table for any * +X * symbolic name with a value corresponding to the cur- * +X * rent PC and a type corresponding to the segment type * +X * (i.e., text, data, or bss) specified by the function's * +X * argument. If any such name is found, a pointer to it is * +X * returned; otherwise, a NULL pointer is returned. * +X * * +X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +X +static char * +getlab(type) +X +X register int type; +X +X{/* * * * * * * * * * START OF getlab() * * * * * * * * * */ +X +X register int k; +X static char b[32], c[10]; +X +X if (symptr < 0) +X if ((type == N_TEXT) +X || ((type == N_DATA) && ( ! objptr ) && ( ! zcount ))) +X { +X if (type == N_TEXT) +X sprintf(b,"T%05.5lx:",PC); +X else +X sprintf(b,"D%05.5lx:",PC); +X return (b); +X } +X else +X return (NULL); +X +X for (k = 0; k <= symptr; ++k) +X if ((symtab[k].n_value == PC) +X && ((symtab[k].n_sclass & N_SECT) == type)) +X { +X sprintf(b,"%s:\n",getnam(k)); +X if (objflg && (type != N_TEXT)) +X sprintf(c,"| %05.5lx\n",PC); +X strcat(b,c); +X return (b); +X } +X +X return (NULL); +X +X}/* * * * * * * * * * * END OF getlab() * * * * * * * * * * */ +X +X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +X * * +X * This routine performs a preliminary scan of the symbol * +X * table, before disassembly begins, and outputs declara- * +X * tions of globals and constants. * +X * * +X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +X +static void +prolog() +X +X{/* * * * * * * * * * START OF prolog() * * * * * * * * * */ +X +X register int j, flag; +X +X if (symptr < 0) +X return; +X +X for (j = flag = 0; j <= symptr; ++j) +X if ((symtab[j].n_sclass & N_CLASS) == C_EXT) +X if (((symtab[j].n_sclass & N_SECT) > N_UNDF) +X && ((symtab[j].n_sclass & N_SECT) < N_COMM)) +X { +X char *c = getnam(j); +X printf("\t.globl\t%s",c); +X if (++flag == 1) +X { +X putchar('\t'); +X if (strlen(c) < 8) +X putchar('\t'); +X printf("| Internal global\n"); +X } +X else +X putchar('\n'); +X } +X else +X if (symtab[j].n_value) +X { +X char *c = getnam(j); +X printf("\t.comm\t%s,0x%08.8lx",c, +X symtab[j].n_value); +X if (++flag == 1) +X printf("\t| Internal global\n"); +X else +X putchar('\n'); +X } +X +X if (flag) +X putchar('\n'); +X +X for (j = flag = 0; j <= relptr; ++j) +X if (relo[j].r_symndx < S_BSS) +X { +X char *c = getnam(relo[j].r_symndx); +X ++flag; +X printf("\t.globl\t%s",c); +X putchar('\t'); +X if (strlen(c) < 8) +X putchar('\t'); +X printf("| Undef: %05.5lx\n",relo[j].r_vaddr); +X } +X +X if (flag) +X putchar('\n'); +X +X for (j = flag = 0; j <= symptr; ++j) +X if ((symtab[j].n_sclass & N_SECT) == N_ABS) +X { +X char *c = getnam(j); +X printf("%s=0x%08.8lx",c,symtab[j].n_value); +X if (++flag == 1) +X { +X printf("\t\t"); +X if (strlen(c) < 5) +X putchar('\t'); +X printf("| Literal\n"); +X } +X else +X putchar('\n'); +X } +X +X if (flag) +X putchar('\n'); +X +X}/* * * * * * * * * * * END OF prolog() * * * * * * * * * * */ +X +X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +X * * +X * This function is responsible for disassembly of the * +X * object file's text segment. * +X * * +X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +X +static void +distext() +X +X{/* * * * * * * * * * START OF distext() * * * * * * * * * */ +X +X char *c; +X register int j; +X register void (*f)(); +X +X for (j = 0; j < (int)(HDR.a_hdrlen); ++j) +X getchar(); +X +X printf("| %s, %s\n\n",PRG,release); +X +X printf("| @("); +X +X printf("#)\tDisassembly of %s",IFILE); +X +X if (symptr < 0) +X printf(" (no symbols)\n\n"); +X else +X printf("\n\n"); +X +X if (HDR.a_flags & A_EXEC) +X printf("| File is executable\n\n"); +X +X if (HDR.a_flags & A_SEP) +X { +X printf("| File has split I/D space, and may have\n"); +X printf("| extraneous instructions in text segment\n\n"); +X } +X +X prolog(); +X +X printf("\t.text\t\t\t| loc = %05.5lx, size = %05.5lx\n\n", +X PC,HDR.a_text); +X +X segflg = 0; +X +X for (PC = 0L; PC < HDR.a_text; ++PC) +X { +X j = getchar() & 0xff; +X if ((j == 0) && ((PC + 1L) == HDR.a_text)) +X { +X ++PC; +X break; +X } +X if ((c = getlab(N_TEXT)) != NULL) +X printf("%s",c); +X f = optab[j].func; +X (*f)(j); +X } +X +X}/* * * * * * * * * * END OF distext() * * * * * * * * * */ +X +X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +X * * +X * This function handles the object file's data segment. * +X * There is no good way to disassemble a data segment, be- * +X * cause it is impossible to tell, from the object code * +X * alone, what each data byte refers to. If it refers to * +X * an external symbol, the reference can be resolved from * +X * the relocation table, if there is one. However, if it * +X * refers to a static symbol, it cannot be distinguished * +X * from numeric, character, or other pointer data. In some * +X * cases, one might make a semi-educated guess as to the * +X * nature of the data, but such guesses are inherently * +X * haphazard, and they are bound to be wrong a good por- * +X * tion of the time. Consequently, the data segment is * +X * disassembled as a byte stream, which will satisfy no * +X * one but which, at least, will never mislead anyone. * +X * * +X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +X +static void +disdata() +X +X{/* * * * * * * * * * START OF disdata() * * * * * * * * * */ +X +X register char *c; +X register int j; +X unsigned long end; +X +X putchar('\n'); +X +X if (HDR.a_flags & A_SEP) +X { +X PC = 0L; +X end = HDR.a_data; +X } +X else +X end = HDR.a_text + HDR.a_data; +X +X printf("\t.data\t\t\t| loc = %05.5lx, size = %05.5lx\n\n", +X PC,HDR.a_data); +X +X segflg = 0; +X +X for (objptr = 0, zcount = 0L; PC < end; ++PC) +X { +X if ((c = getlab(N_DATA)) != NULL) +X { +X objdump(c); +X printf("%s",c); +X } +X if (objptr >= OBJMAX) +X if (objdump(NULL) && (symptr < 0)) +X printf("D%05.5lx:",PC); +X j = getchar() & 0xff; +X objbuf[objptr++] = j; +X } +X +X objdump(""); +X +X}/* * * * * * * * * * END OF disdata() * * * * * * * * * */ +X +X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +X * * +X * This function handles the object file's bss segment. * +X * Disassembly of the bss segment is easy, because every- * +X * thing in it is zero by definition. * +X * * +X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +X +static void +disbss() +X +X{/* * * * * * * * * * START OF disbss() * * * * * * * * * */ +X +X register int j; +X register char *c; +X unsigned long beg, end; +X +X putchar('\n'); +X +X if (HDR.a_flags & A_SEP) +X end = HDR.a_data + HDR.a_bss; +X else +X end = HDR.a_text + HDR.a_data + HDR.a_bss; +X +X printf("\t.bss\t\t\t| loc = %05.5lx, size = %05.5lx\n\n", +X PC,HDR.a_bss); +X +X segflg = 0; +X +X for (beg = PC; PC < end; ++PC) +X if ((c = getlab(N_BSS)) != NULL) +X { +X if (PC > beg) +X { +X zdump(beg); +X beg = PC; +X } +X printf("%s",c); +X } +X +X if (PC > beg) +X zdump(beg); +X +X}/* * * * * * * * * * * END OF disbss() * * * * * * * * * * */ +X +X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +X * * +X * This is the program entry point. The command line is * +X * searched for an input file name, which must be present. * +X * An optional output file name is also permitted; if none * +X * is found, standard output is the default. One command- * +X * line option is available: "-o", which causes the pro- * +X * gram to include object code in comments along with its * +X * mnemonic output. * +X * * +X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +X +void +main(argc,argv) +X +X int argc; /* Command-line args from OS */ +X register char **argv; +X +X{/* * * * * * * * * * * START OF main() * * * * * * * * * * */ +X +X char a[1024]; +X register int fd; +X long taboff, tabnum; +X long reloff, relnum; +X +X PRG = invoker(*argv); +X +X while (*++argv != NULL) /* Process command-line args */ +X if (**argv == '-') +X switch (*++*argv) +X { +X case 'o' : +X if (*++*argv) +X usage(PRG); +X else +X ++objflg; +X break; +X default : +X usage(PRG); +X } +X else +X if (IFILE == NULL) +X IFILE = *argv; +X else if (OFILE == NULL) +X OFILE = *argv; +X else +X usage(PRG); +X +X if (IFILE == NULL) +X usage(PRG); +X else +X if ((fd = open(IFILE,O_RDONLY)) < 0) +X { +X sprintf(a,"can't access input file %s",IFILE); +X fatal(PRG,a); +X } +X +X if (OFILE != NULL) +X if (freopen(OFILE,"w",stdout) == NULL) +X { +X sprintf(a,"can't open output file %s",OFILE); +X fatal(PRG,a); +X } +X +X if ( ! cpuid ) +X fprintf(stderr,"\07%s: warning: host/cpu clash\n",PRG); +X +X read(fd,&HDR,sizeof(struct exec)); +X +X if (BADMAG(HDR)) +X { +X sprintf(a,"input file %s not in object format",IFILE); +X fatal(PRG,a); +X } +X +X if (HDR.a_cpu != A_I8086) +X { +X sprintf(a,"%s is not an 8086/8088 object file",IFILE); +X fatal(PRG,a); +X } +X +X if (HDR.a_hdrlen <= A_MINHDR) +X HDR.a_trsize = HDR.a_drsize = +X HDR.a_tbase = HDR.a_dbase = +X HDR.a_lnums = HDR.a_toffs = 0L; +X +X reloff = HDR.a_text /* Compute reloc data offset */ +X + HDR.a_data +X + (long)(HDR.a_hdrlen); +X +X relnum = +X (HDR.a_trsize + HDR.a_drsize) / sizeof(struct reloc); +X +X taboff = reloff /* Compute name table offset */ +X + HDR.a_trsize +X + HDR.a_drsize; +X +X tabnum = HDR.a_syms / sizeof(struct nlist); +X +X if (relnum > MAXSYM) +X fatal(PRG,"reloc table overflow"); +X +X if (tabnum > MAXSYM) +X fatal(PRG,"symbol table overflow"); +X +X if (relnum) /* Get reloc data */ +X if (lseek(fd,reloff,0) != reloff) +X fatal(PRG,"lseek error"); +X else +X { +X for (relptr = 0; relptr < relnum; ++relptr) +X read(fd,&relo[relptr],sizeof(struct reloc)); +X relptr--; +X } +X +X if (tabnum) /* Read in symtab */ +X if (lseek(fd,taboff,0) != taboff) +X fatal(PRG,"lseek error"); +X else +X { +X for (symptr = 0; symptr < tabnum; ++symptr) +X read(fd,&symtab[symptr],sizeof(struct nlist)); +X symptr--; +X } +X else +X fprintf(stderr,"\07%s: warning: no symbols\n",PRG); +X +X close(fd); +X +X if (freopen(IFILE,"r",stdin) == NULL) +X { +X sprintf(a,"can't reopen input file %s",IFILE); +X fatal(PRG,a); +X } +X +X distext(); +X +X disdata(); +X +X disbss(); +X +X exit(0); +X +X}/* * * * * * * * * * * END OF main() * * * * * * * * * * */ +X +X +END_OF_FILE +if test 17384 -ne `wc -c <'dismain.c'`; then + echo shar: \"'dismain.c'\" unpacked with wrong size! +fi +# end of 'dismain.c' +fi +if test -f 'disrel.c' -a "${1}" != "-c" ; then + echo shar: Will not clobber existing file \"'disrel.c'\" +else +echo shar: Extracting \"'disrel.c'\" \(742 characters\) +sed "s/^X//" >'disrel.c' <<'END_OF_FILE' +static char *copyright = +X "@(#) Copyright (C) 1987 G. M. Harding, all rights reserved"; +X +static char *sccsid = +X "@(#) disrel.c, Ver. 2.1 created 00:00:00 87/09/01"; +X +char *release = +X "release 2.1 (PC/IX)"; +X +X /* +X ** +X ** This file documents the major revisions to the 8088 sym- +X ** bolic disassembler. It also contains the release string +X ** which is output at the head of each disassembly, and the +X ** copyright string which must be incorporated in any code +X ** distribution. +X ** +X ** Permission to copy and redistribute is hereby granted, +X ** provided full source code, with all copyright notices, +X ** accompanies any redistribution. +X ** +X ** REVISION HISTORY: +X ** +X ** SEP 87: +X ** After internal shakeout, released on Usenet. +X ** +X */ +X +END_OF_FILE +if test 742 -ne `wc -c <'disrel.c'`; then + echo shar: \"'disrel.c'\" unpacked with wrong size! +fi +# end of 'disrel.c' +fi +echo shar: End of archive 1 \(of 2\). +cp /dev/null ark1isdone +MISSING="" +for I in 1 2 ; do + if test ! -f ark${I}isdone ; then + MISSING="${MISSING} ${I}" + fi +done +if test "${MISSING}" = "" ; then + echo You have unpacked both archives. + rm -f ark[1-9]isdone +else + echo You still need to unpack the following archives: + echo " " ${MISSING} +fi +## End of shell archive. +exit 0 diff --git a/part02 b/part02 new file mode 100644 index 0000000..34ca663 --- /dev/null +++ b/part02 @@ -0,0 +1,1812 @@ +Subject: v15i007: Symbolic disassembler for PC/IX, Part02/02 +Newsgroups: comp.sources.unix +Approved: rsalz@uunet.UU.NET + +Submitted-by: "G. M. Harding" +Posting-number: Volume 15, Issue 7 +Archive-name: dis88/part02 + +#! /bin/sh +# This is a shell archive. Remove anything before this line, then unpack +# it by saving it into a file and typing "sh file". To overwrite existing +# files, type "sh file -c". You can also feed this as standard input via +# unshar, or by typing "sh 'dishand.c' <<'END_OF_FILE' +static char *sccsid = +X "@(#) dishand.c, Ver. 2.1 created 00:00:00 87/09/01"; +X +X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +X * * +X * Copyright (C) 1987 G. M. Harding, all rights reserved * +X * * +X * Permission to copy and redistribute is hereby granted, * +X * provided full source code, with all copyright notices, * +X * accompanies any redistribution. * +X * * +X * This file contains the source code for most of the spe- * +X * cialized handler routines of the disassembler program. * +X * (The file disfp.c contains handler routines specific to * +X * the 8087 numeric co-processor.) Each handler routine * +X * interprets the opcode byte (and subsequent data bytes, * +X * if any) of a particular family of opcodes, and is re- * +X * sponsible for generating appropriate output. All of the * +X * code in this file is highly MACHINE-SPECIFIC, and would * +X * have to be rewritten for a different CPU. The handler * +X * routines are accessed only via pointers in the optab[] * +X * array, however, so machine dependencies are confined to * +X * this file, its sister file "disfp.c", and the data file * +X * "distabs.c". * +X * * +X * All of the code in this file is based on the assumption * +X * of sixteen-bit integers. * +X * * +X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +X +X#include "dis.h" /* Disassembler declarations */ +X +int segflg; /* Segment-override flag */ +X +unsigned char objbuf[OBJMAX]; /* Buffer for object code */ +X +int objptr; /* Index into objbuf[] */ +X +unsigned long PC; /* Current program counter */ +X +X /* * * * * * MISCELLANEOUS SUPPORTING ROUTINES * * * * * */ +X +X +void +objini(j) /* Object code init routine */ +X +X register int j; +X +X{ +X if ((segflg == 1) || (segflg == 2)) +X segflg *= 3; +X else +X segflg = 0; +X objptr = 0; +X objbuf[objptr++] = (unsigned char)(j); +X} +X +X +void +objout() /* Object-code output routine */ +X +X{ +X register int k; +X +X if ( ! objflg ) +X return; +X else +X { +X printf("\t|"); +X if (symptr >= 0) +X printf(" %05.5lx:",(PC + 1L - (long)(objptr))); +X for (k = 0; k < objptr; ++k) +X printf(" %02.2x",objbuf[k]); +X putchar('\n'); +X } +X} +X +X +void +badseq(j,k) /* Invalid-sequence routine */ +X +X register int j, k; +X +X{ +X printf("\t.byte\t0x%02.2x\t\t| invalid code sequence\n",j); +X printf("\t.byte\t0x%02.2x\n",k); +X} +X +X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +X * * +X * This routine is the first of several opcode-specific * +X * handlers, each of which is dedicated to a particular * +X * opcode family. A pointer to a handler routine is con- * +X * tained in the second field of each optab[] entry. The * +X * dfhand() routine is the default handler, invoked when * +X * no other handler is appropriate (generally, when an in- * +X * valid opcode is encountered). * +X * * +X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +X +void +dfhand(j) +X +X register int j; /* Pointer to optab[] entry */ +X +X{/* * * * * * * * * * START OF dfhand() * * * * * * * * * */ +X +X segflg = 0; +X +X printf("\t.byte\t0x%02.2x",j); +X +X if (optab[j].min || optab[j].max) +X putchar('\n'); +X else +X printf("\t\t| unimplemented opcode\n"); +X +X}/* * * * * * * * * * * END OF dfhand() * * * * * * * * * * */ +X +X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +X * * +X * This is the single-byte handler, invoked whenever a * +X * one-byte opcode is encountered. * +X * * +X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +X +void +sbhand(j) +X +X register int j; /* Pointer to optab[] entry */ +X +X{/* * * * * * * * * * START OF sbhand() * * * * * * * * * */ +X +X objini(j); +X +X if (j == 0x2e) /* seg cs */ +X segflg = 1; +X +X if ((j == 0x26) /* seg es */ +X || (j == 0x36) /* seg ss */ +X || (j == 0x3e)) /* seg ds */ +X segflg = 2; +X +X printf("%s\n",optab[j].text); +X +X objout(); +X +X}/* * * * * * * * * * * END OF sbhand() * * * * * * * * * * */ +X +X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +X * * +X * This is the handler for most of the processor's regular * +X * arithmetic operations. * +X * * +X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +X +void +aohand(j) +X +X register int j; /* Pointer to optab[] entry */ +X +X{/* * * * * * * * * * START OF aohand() * * * * * * * * * */ +X +X register int k; +X int m, n; +X char b[64]; +X +X objini(j); +X +X switch (j & 7) +X { +X case 0 : +X case 1 : +X case 2 : +X case 3 : +X printf("%s\t",optab[j].text); +X FETCH(k); +X printf("%s\n",mtrans(j,k,TR_STD)); +X break; +X case 4 : +X FETCH(k); +X printf("%s\tal,*0x%02.2x\n",optab[j].text,k); +X break; +X case 5 : +X FETCH(m); +X FETCH(n); +X k = (n << 8) | m; +X if (lookext((long)(k),(PC - 1),b)) +X printf("%s\tax,#%s\n",optab[j].text,b); +X else +X printf("%s\tax,#0x%04.4x\n",optab[j].text,k); +X break; +X default : +X dfhand(j); +X break; +X } +X +X objout(); +X +X}/* * * * * * * * * * * END OF aohand() * * * * * * * * * * */ +X +X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +X * * +X * This is the handler for opcodes which perform short * +X * (eight-bit) relative jumps. * +X * * +X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +X +void +sjhand(j) +X +X register int j; /* Pointer to optab[] entry */ +X +X{/* * * * * * * * * * START OF sjhand() * * * * * * * * * */ +X +X register int k; +X int m; +X +X objini(j); +X +X FETCH(m); +X +X if (m & 0x80) +X k = 0xff00; +X else +X k = 0; +X +X k |= m; +X +X printf("%s\t%s\t\t| loc %05.5lx\n",optab[j].text, +X lookup((PC + k + 1L),N_TEXT,LOOK_REL,-1L), +X (PC + k + 1L)); +X +X objout(); +X +X}/* * * * * * * * * * * END OF sjhand() * * * * * * * * * * */ +X +X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +X * * +X * This is the handler for a loosely-knit family of op- * +X * codes which perform arithmetic and logical operations, * +X * and which take immediate data. The routine's logic is * +X * rather complex, so, in an effort to avoid additional * +X * complexity, the search for external references in the * +X * relocation table has been dispensed with. Eager hackers * +X * can try their hand at coding such a search. * +X * * +X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +X +void +imhand(j) +X +X register int j; /* Pointer to optab[] entry */ +X +X{/* * * * * * * * * * START OF imhand() * * * * * * * * * */ +X +X unsigned long pc; +X register int k; +X int offset, oflag, immed, iflag, mod, opi, w, rm; +X int m, n; +X static char a[100], b[30]; +X +X objini(j); +X +X FETCH(k); +X +X pc = PC + 1; +X +X offset = 0; +X mod = (k & 0xc0) >> 6; +X opi = (k & 0x38) >> 3; +X w = j & 1; +X rm = k & 7; +X +X if ((j & 2) +X && ((opi == 1) +X || (opi == 4) +X || (opi == 6))) +X { +X badseq(j,k); +X return; +X } +X +X strcpy(a,OPFAM[opi]); +X +X if ( ! w ) +X strcat(a,"b"); +X +X if ((oflag = mod) > 2) +X oflag = 0; +X +X if ((mod == 0) && (rm == 6)) +X { +X FETCH(m); +X FETCH(n); +X offset = (n << 8) | m; +X } +X else if (oflag) +X if (oflag == 2) +X { +X FETCH(m); +X FETCH(n); +X offset = (n << 8) | m; +X } +X else +X { +X FETCH(m); +X if (m & 0x80) +X n = 0xff00; +X else +X n = 0; +X offset = n | m; +X } +X +X switch (j & 3) +X { +X case 0 : +X case 2 : +X FETCH(immed); +X iflag = 0; +X break; +X case 1 : +X FETCH(m); +X FETCH(n); +X immed = (n << 8) | m; +X iflag = 1; +X break; +X case 3 : +X FETCH(immed); +X if (immed & 0x80) +X immed &= 0xff00; +X iflag = 0; +X break; +X } +X +X strcat(a,"\t"); +X +X switch (mod) +X { +X case 0 : +X if (rm == 6) +X strcat(a, +X lookup((long)(offset),N_DATA,LOOK_ABS,pc)); +X else +X { +X sprintf(b,"(%s)",REGS0[rm]); +X strcat(a,b); +X } +X break; +X case 1 : +X case 2 : +X if (mod == 1) +X strcat(a,"*"); +X else +X strcat(a,"#"); +X sprintf(b,"%d(",offset); +X strcat(a,b); +X strcat(a,REGS1[rm]); +X strcat(a,")"); +X break; +X case 3 : +X strcat(a,REGS[(w << 3) | rm]); +X break; +X } +X +X strcat(a,","); +X if (iflag) +X strcat(a,"#"); +X else +X strcat(a,"*"); +X sprintf(b,"%d",immed); +X strcat(a,b); +X +X printf("%s\n",a); +X +X objout(); +X +X}/* * * * * * * * * * * END OF imhand() * * * * * * * * * * */ +X +X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +X * * +X * This is the handler for various "mov"-type opcodes * +X * which use the mod, reg, and r/m fields of the second * +X * code byte in a standard, straightforward way. * +X * * +X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +X +void +mvhand(j) +X +X int j; /* Pointer to optab[] entry */ +X +X{/* * * * * * * * * * START OF mvhand() * * * * * * * * * */ +X +X register int k, m = j; +X +X objini(j); +X +X FETCH(k); +X +X if ((m == 0x84) || (m == 0x85) /* Kind of kludgey */ +X || (m == 0xc4) || (m == 0xc5) +X || (m == 0x8d)) +X if (m & 0x40) +X m |= 0x03; +X else +X m |= 0x02; +X +X printf("%s\t%s\n",optab[j].text,mtrans(m,k,TR_STD)); +X +X objout(); +X +X}/* * * * * * * * * * * END OF mvhand() * * * * * * * * * * */ +X +X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +X * * +X * This is the handler for segment-register "mov" opcodes. * +X * * +X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +X +void +mshand(j) +X +X register int j; /* Pointer to optab[] entry */ +X +X{/* * * * * * * * * * START OF mshand() * * * * * * * * * */ +X +X register int k; +X +X objini(j); +X +X FETCH(k); +X +X if (k & 0x20) +X { +X badseq(j,k); +X return; +X } +X +X printf("%s\t%s\n",optab[j].text,mtrans(j,k,TR_SEG)); +X +X objout(); +X +X}/* * * * * * * * * * * END OF mshand() * * * * * * * * * * */ +X +X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +X * * +X * This is the handler for pops, other than single-byte * +X * pops. (The 8088 allows popping into any register, or * +X * directly into memory, accessed either immediately or * +X * through a register and an index.) * +X * * +X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +X +void +pohand(j) +X +X register int j; /* Pointer to optab[] entry */ +X +X{/* * * * * * * * * * START OF pohand() * * * * * * * * * */ +X +X char *a; +X register int k; +X +X objini(j); +X +X FETCH(k); +X +X if (k & 0x38) +X { +X badseq(j,k); +X return; +X } +X +X printf("%s\t",optab[j].text); +X +X a = mtrans((j & 0xfd),k,TR_STD); +X +X mtrunc(a); +X +X printf("%s\n",a); +X +X objout(); +X +X}/* * * * * * * * * * * END OF pohand() * * * * * * * * * * */ +X +X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +X * * +X * This is the handler routine for intersegment calls and * +X * jumps. Its output is never symbolic, because the host * +X * linker does not allow symbolic intersegment address * +X * references except by means of symbolic constants, and * +X * any such constants in the symbol table, even if they * +X * are of the appropriate value, may be misleading. In * +X * compiled code, intersegment references should not be * +X * encountered, and even in assembled code, they should * +X * occur infrequently. If and when they do occur, however, * +X * they will be disassembled in absolute form. * +X * * +X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +X +void +cihand(j) +X +X int j; /* Pointer to optab[] entry */ +X +X{/* * * * * * * * * * START OF cihand() * * * * * * * * * */ +X +X register int m, n; +X +X objini(j); +X +X printf("%s\t",optab[j].text); +X +X FETCH(m); +X FETCH(n); +X +X printf("#0x%04.4x,",((n << 8) | m)); +X +X FETCH(m); +X FETCH(n); +X +X printf("#0x%04.4x\n",((n << 8) | m)); +X +X objout(); +X +X}/* * * * * * * * * * * END OF cihand() * * * * * * * * * * */ +X +X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +X * * +X * This is the handler for "mov" opcodes with immediate * +X * data. * +X * * +X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +X +void +mihand(j) +X +X register int j; /* Pointer to optab[] entry */ +X +X{/* * * * * * * * * * START OF mihand() * * * * * * * * * */ +X +X register int k; +X int m, n; +X char b[64]; +X +X objini(j); +X +X printf("%s",optab[j].text); +X +X if (j & 8) +X { +X FETCH(m); +X FETCH(n); +X k = ((n << 8) | m); +X if (lookext((long)(k),(PC - 1),b)) +X printf("#%s\n",b); +X else +X printf("#%d\n",k); +X } +X else +X { +X FETCH(m); +X printf("*%d\n",m); +X } +X +X objout(); +X +X}/* * * * * * * * * * * END OF mihand() * * * * * * * * * * */ +X +X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +X * * +X * This is the handler for a family of quick-move opcodes. * +X * * +X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +X +void +mqhand(j) +X +X int j; /* Pointer to optab[] entry */ +X +X{/* * * * * * * * * * START OF mqhand() * * * * * * * * * */ +X +X unsigned long pc; +X register int m, n; +X +X objini(j); +X +X pc = PC + 1; +X +X FETCH(m); +X FETCH(n); +X +X m = (n << 8) | m; +X +X printf("%s\t",optab[j].text); +X +X if (j & 2) +X printf("%s,%s\n", +X lookup((long)(m),N_DATA,LOOK_ABS,pc), +X REGS[(j & 1) << 3]); +X else +X printf("%s,%s\n", +X REGS[(j & 1) << 3], +X lookup((long)(m),N_DATA,LOOK_ABS,pc)); +X +X objout(); +X +X}/* * * * * * * * * * * END OF mqhand() * * * * * * * * * * */ +X +X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +X * * +X * This is the handler for a family of quick-test opcodes. * +X * * +X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +X +void +tqhand(j) +X +X int j; /* Pointer to optab[] entry */ +X +X{/* * * * * * * * * * START OF tqhand() * * * * * * * * * */ +X +X register int m, n; +X int k; +X char b[64]; +X +X objini(j); +X +X printf("%s\t%s,",optab[j].text,REGS[(j & 1) << 3]); +X +X FETCH(m); +X +X if (j & 1) +X { +X FETCH(n); +X k = ((n << 8) | m); +X if (lookext((long)(k),(PC - 1),b)) +X printf("#%s\n",b); +X else +X printf("#%d\n",k); +X } +X else +X { +X if (m & 80) +X m |= 0xff00; +X printf("*%d\n",m); +X } +X +X objout(); +X +X}/* * * * * * * * * * * END OF tqhand() * * * * * * * * * * */ +X +X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +X * * +X * This is the handler for multiple-byte "return" opcodes. * +X * The 8088 allows returns to take an optional 16-bit ar- * +X * gument, which reflects the amount to be added to SP * +X * after the pop of the return address. The idea is to * +X * facilitate the use of local parameters on the stack. * +X * After some rumination, it was decided to disassemble * +X * any such arguments as absolute quantities, rather than * +X * rummaging through the symbol table for possible corre- * +X * sponding constants. * +X * * +X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +X +void +rehand(j) +X +X int j; /* Pointer to optab[] entry */ +X +X{/* * * * * * * * * * START OF rehand() * * * * * * * * * */ +X +X register int m, n; +X +X objini(j); +X +X FETCH(m); +X FETCH(n); +X +X m = (n << 8) | m; +X +X printf("%s\t#0x%04.4x\n",optab[j].text,m); +X +X objout(); +X +X}/* * * * * * * * * * * END OF rehand() * * * * * * * * * * */ +X +X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +X * * +X * This is the handler for "mov" opcodes involving memory * +X * and immediate data. * +X * * +X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +X +void +mmhand(j) +X +X register int j; /* Pointer to optab[] entry */ +X +X{/* * * * * * * * * * START OF mmhand() * * * * * * * * * */ +X +X char *a; +X register int k; +X char b[64]; +X +X objini(j); +X +X FETCH(k); +X +X if (k & 0x38) +X { +X badseq(j,k); +X return; +X } +X +X printf("%s",optab[j].text); +X +X if ( ! (j & 1) ) +X putchar('b'); +X +X a = mtrans((j & 0xfd),(k & 0xc7),TR_STD); +X +X mtrunc(a); +X +X printf("\t%s,",a); +X +X if (j & 1) +X { +X FETCH(j); +X FETCH(k); +X k = (k << 8) | j; +X if (lookext((long)(k),(PC - 1),b)) +X printf("#%s\n",b); +X else +X printf("#%d\n",k); +X } +X else +X { +X FETCH(k); +X printf("*%d\n",k); +X } +X +X objout(); +X +X}/* * * * * * * * * * * END OF mmhand() * * * * * * * * * * */ +X +X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +X * * +X * This is the handler for the 8088 family of shift and * +X * rotate instructions. * +X * * +X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +X +void +srhand(j) +X +X register int j; /* Pointer to optab[] entry */ +X +X{/* * * * * * * * * * START OF srhand() * * * * * * * * * */ +X +X char *a; +X register int k; +X +X objini(j); +X +X FETCH(k); +X +X if ((k & 0x38) == 0x30) +X { +X badseq(j,k); +X return; +X } +X +X printf("%s",OPFAM[((k & 0x38) >> 3) + 16]); +X +X if ( ! (j & 1) ) +X putchar('b'); +X +X a = mtrans((j & 0xfd),(k & 0xc7),TR_STD); +X +X mtrunc(a); +X +X printf("\t%s",a); +X +X if (j & 2) +X printf(",cl\n"); +X else +X printf(",*1\n"); +X +X objout(); +X +X}/* * * * * * * * * * * END OF srhand() * * * * * * * * * * */ +X +X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +X * * +X * This is the handler for the ASCII-adjust opcodes. * +X * * +X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +X +void +aahand(j) +X +X register int j; /* Pointer to optab[] entry */ +X +X{/* * * * * * * * * * START OF aahand() * * * * * * * * * */ +X +X register int k; +X +X objini(j); +X +X FETCH(k); +X +X if (k != 0x0a) +X { +X badseq(j,k); +X return; +X } +X +X printf("%s\n",optab[j].text); +X +X objout(); +X +X}/* * * * * * * * * * * END OF aahand() * * * * * * * * * * */ +X +X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +X * * +X * This is the handler for port I/O opcodes which specify * +X * the port address as an immediate operand. * +X * * +X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +X +void +iohand(j) +X +X register int j; /* Pointer to optab[] entry */ +X +X{/* * * * * * * * * * START OF iohand() * * * * * * * * * */ +X +X register int k; +X +X objini(j); +X +X FETCH(k); +X +X printf("%s\t0x%02.2x\n",optab[j].text,k); +X +X objout(); +X +X}/* * * * * * * * * * * END OF iohand() * * * * * * * * * * */ +X +X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +X * * +X * This is the handler for opcodes which perform long * +X * (sixteen-bit) relative jumps and calls. * +X * * +X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +X +void +ljhand(j) +X +X register int j; /* Pointer to optab[] entry */ +X +X{/* * * * * * * * * * START OF ljhand() * * * * * * * * * */ +X +X register int k; +X int m, n; +X +X objini(j); +X +X FETCH(m); +X FETCH(n); +X +X k = (n << 8) | m; +X +X printf("%s\t%s\t\t| loc %05.5lx\n",optab[j].text, +X lookup((PC + k + 1L),N_TEXT,LOOK_LNG,(PC - 1L)), +X (PC + k + 1L)); +X +X objout(); +X +X}/* * * * * * * * * * * END OF ljhand() * * * * * * * * * * */ +X +X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +X * * +X * This is the handler for a pair of oddball opcodes (0xf6 * +X * and 0xf7) which perform miscellaneous arithmetic opera- * +X * tions not dealt with elsewhere. * +X * * +X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +X +void +mahand(j) +X +X register int j; /* Pointer to optab[] entry */ +X +X{/* * * * * * * * * * START OF mahand() * * * * * * * * * */ +X +X char *a; +X register int k; +X char b[64]; +X +X objini(j); +X +X FETCH(k); +X +X a = mtrans((j & 0xfd),(k & 0xc7),TR_STD); +X +X mtrunc(a); +X +X switch (((k = objbuf[1]) & 0x38) >> 3) +X { +X case 0 : +X printf("\ttest"); +X break; +X case 1 : +X badseq(j,k); +X return; +X case 2 : +X printf("\tnot"); +X break; +X case 3 : +X printf("\tneg"); +X break; +X case 4 : +X printf("\tmul"); +X break; +X case 5 : +X printf("\timul"); +X break; +X case 6 : +X printf("\tdiv"); +X break; +X case 7 : +X printf("\tidiv"); +X break; +X } +X +X if ( ! (j & 1) ) +X putchar('b'); +X +X printf("\t%s",a); +X +X if (k & 0x38) +X putchar('\n'); +X else +X if (j & 1) +X { +X FETCH(j); +X FETCH(k); +X k = (k << 8) | j; +X if (lookext((long)(k),(PC - 1),b)) +X printf(",#%s\n",b); +X else +X printf(",#%d\n",k); +X } +X else +X { +X FETCH(k); +X printf(",*%d\n",k); +X } +X +X objout(); +X +X}/* * * * * * * * * * * END OF mahand() * * * * * * * * * * */ +X +X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +X * * +X * This is the handler for miscellaneous jump, call, push, * +X * and increment/decrement opcodes (0xfe and 0xff) which * +X * are not dealt with elsewhere. * +X * * +X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +X +void +mjhand(j) +X +X register int j; /* Pointer to optab[] entry */ +X +X{/* * * * * * * * * * START OF mjhand() * * * * * * * * * */ +X +X char *a; +X register int k; +X +X objini(j); +X +X FETCH(k); +X +X a = mtrans((j & 0xfd),(k & 0xc7),TR_STD); +X +X mtrunc(a); +X +X switch (((k = objbuf[1]) & 0x38) >> 3) +X { +X case 0 : +X printf("\tinc"); +X if ( ! (j & 1) ) +X putchar('b'); +X putchar('\t'); +X break; +X case 1 : +X printf("\tdec"); +X if ( ! (j & 1) ) +X putchar('b'); +X putchar('\t'); +X break; +X case 2 : +X if (j & 1) +X printf("\tcall\t@"); +X else +X goto BAD; +X break; +X case 3 : +X if (j & 1) +X printf("\tcalli\t@"); +X else +X goto BAD; +X break; +X case 4 : +X if (j & 1) +X printf("\tjmp\t@"); +X else +X goto BAD; +X break; +X case 5 : +X if (j & 1) +X printf("\tjmpi\t@"); +X else +X goto BAD; +X break; +X case 6 : +X if (j & 1) +X printf("\tpush\t"); +X else +X goto BAD; +X break; +X case 7 : +X BAD : +X badseq(j,k); +X return; +X } +X +X printf("%s\n",a); +X +X objout(); +X +X}/* * * * * * * * * * * END OF mjhand() * * * * * * * * * * */ +X +X +END_OF_FILE +if test 25688 -ne `wc -c <'dishand.c'`; then + echo shar: \"'dishand.c'\" unpacked with wrong size! +fi +# end of 'dishand.c' +fi +if test -f 'distabs.c' -a "${1}" != "-c" ; then + echo shar: Will not clobber existing file \"'distabs.c'\" +else +echo shar: Extracting \"'distabs.c'\" \(30238 characters\) +sed "s/^X//" >'distabs.c' <<'END_OF_FILE' +static char *sccsid = +X "@(#) distabs.c, Ver. 2.1 created 00:00:00 87/09/01"; +X +X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +X * * +X * Copyright (C) 1987 G. M. Harding, all rights reserved * +X * * +X * Permission to copy and redistribute is hereby granted, * +X * provided full source code, with all copyright notices, * +X * accompanies any redistribution. * +X * * +X * This file contains the lookup tables and other data * +X * structures for the Intel 8088 symbolic disassembler. It * +X * also contains a few global routines which facilitate * +X * access to the tables, for use primarily by the handler * +X * functions. * +X * * +X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +X +X#include "dis.h" /* Disassembler declarations */ +X +struct exec HDR; /* Used to hold header info */ +X +struct nlist symtab[MAXSYM]; /* Array of symbol table info */ +X +struct reloc relo[MAXSYM]; /* Array of relocation info */ +X +int symptr = -1, /* Index into symtab[] */ +X relptr = -1; /* Index into relo[] */ +X +char *REGS[] = /* Table of register names */ +X { +X "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh", +X "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", +X "es", "cs", "ss", "ds" +X }; +X +char *REGS0[] = /* Mode 0 register name table */ +X { +X "bx_si", "bx_di", "bp_si", "bp_di", "si", "di", "", "bx" +X }; +X +char *REGS1[] = /* Mode 1 register name table */ +X { +X "bx_si", "bx_di", "bp_si", "bp_di", "si", "di", "bp", "bx" +X }; +X +int symrank[6][6] = /* Symbol type/rank matrix */ +X { +X /* UND ABS TXT DAT BSS COM */ +X /* UND */ 5, 4, 1, 2, 3, 0, +X /* ABS */ 1, 5, 4, 3, 2, 0, +X /* TXT */ 4, 1, 5, 3, 2, 0, +X /* DAT */ 3, 1, 2, 5, 4, 0, +X /* BSS */ 3, 1, 2, 4, 5, 0, +X /* COM */ 2, 0, 1, 3, 4, 5 +X }; +X +X /* * * * * * * * * * * * OPCODE DATA * * * * * * * * * * * */ +X +char ADD[] = "\tadd", /* Mnemonics by family */ +X OR[] = "\tor", +X ADC[] = "\tadc", +X SBB[] = "\tsbb", +X AND[] = "\tand", +X SUB[] = "\tsub", +X XOR[] = "\txor", +X CMP[] = "\tcmp", +X NOT[] = "\tnot", +X NEG[] = "\tneg", +X MUL[] = "\tmul", +X DIV[] = "\tdiv", +X MOV[] = "\tmov", +X ESC[] = "\tesc", +X TEST[] = "\ttest", +X AMBIG[] = "", +X ROL[] = "\trol", +X ROR[] = "\tror", +X RCL[] = "\trcl", +X RCR[] = "\trcr", +X SAL[] = "\tsal", +X SHR[] = "\tshr", +X SHL[] = "\tshl", +X SAR[] = "\tsar"; +X +char *OPFAM[] = /* Family lookup table */ +X { +X ADD, OR, ADC, SBB, AND, SUB, XOR, CMP, +X NOT, NEG, MUL, DIV, MOV, ESC, TEST, AMBIG, +X ROL, ROR, RCL, RCR, SAL, SHR, SHL, SAR +X }; +X +struct opcode optab[] = /* Table of opcode data */ +X { +X ADD, aohand, 2, 4, /* 0x00 */ +X ADD, aohand, 2, 4, /* 0x01 */ +X ADD, aohand, 2, 4, /* 0x02 */ +X ADD, aohand, 2, 4, /* 0x03 */ +X ADD, aohand, 2, 2, /* 0x04 */ +X ADD, aohand, 3, 3, /* 0x05 */ +X "\tpush\tes", sbhand, 1, 1, /* 0x06 */ +X "\tpop\tes", sbhand, 1, 1, /* 0x07 */ +X OR, aohand, 2, 4, /* 0x08 */ +X OR, aohand, 2, 4, /* 0x09 */ +X OR, aohand, 2, 4, /* 0x0a */ +X OR, aohand, 2, 4, /* 0x0b */ +X OR, aohand, 2, 2, /* 0x0c */ +X OR, aohand, 3, 3, /* 0x0d */ +X "\tpush\tcs", sbhand, 1, 1, /* 0x0e */ +X NULL, dfhand, 0, 0, /* 0x0f */ +X ADC, aohand, 2, 4, /* 0x10 */ +X ADC, aohand, 2, 4, /* 0x11 */ +X ADC, aohand, 2, 4, /* 0x12 */ +X ADC, aohand, 2, 4, /* 0x13 */ +X ADC, aohand, 2, 2, /* 0x14 */ +X ADC, aohand, 3, 3, /* 0x15 */ +X "\tpush\tss", sbhand, 1, 1, /* 0x16 */ +X "\tpop\tss", sbhand, 1, 1, /* 0x17 */ +X SBB, aohand, 2, 4, /* 0x18 */ +X SBB, aohand, 2, 4, /* 0x19 */ +X SBB, aohand, 2, 4, /* 0x1a */ +X SBB, aohand, 2, 4, /* 0x1b */ +X SBB, aohand, 2, 2, /* 0x1c */ +X SBB, aohand, 3, 3, /* 0x1d */ +X "\tpush\tds", sbhand, 1, 1, /* 0x1e */ +X "\tpop\tds", sbhand, 1, 1, /* 0x1f */ +X AND, aohand, 2, 4, /* 0x20 */ +X AND, aohand, 2, 4, /* 0x21 */ +X AND, aohand, 2, 4, /* 0x22 */ +X AND, aohand, 2, 4, /* 0x23 */ +X AND, aohand, 2, 2, /* 0x24 */ +X AND, aohand, 3, 3, /* 0x25 */ +X "\tseg\tes", sbhand, 1, 1, /* 0x26 */ +X "\tdaa", sbhand, 1, 1, /* 0x27 */ +X SUB, aohand, 2, 4, /* 0x28 */ +X SUB, aohand, 2, 4, /* 0x29 */ +X SUB, aohand, 2, 4, /* 0x2a */ +X SUB, aohand, 2, 4, /* 0x2b */ +X SUB, aohand, 2, 2, /* 0x2c */ +X SUB, aohand, 3, 3, /* 0x2d */ +X "\tseg\tcs", sbhand, 1, 1, /* 0x2e */ +X "\tdas", sbhand, 1, 1, /* 0x2f */ +X XOR, aohand, 2, 4, /* 0x30 */ +X XOR, aohand, 2, 4, /* 0x31 */ +X XOR, aohand, 2, 4, /* 0x32 */ +X XOR, aohand, 2, 4, /* 0x33 */ +X XOR, aohand, 2, 2, /* 0x34 */ +X XOR, aohand, 3, 3, /* 0x35 */ +X "\tseg\tss", sbhand, 1, 1, /* 0x36 */ +X "\taaa", sbhand, 1, 1, /* 0x37 */ +X CMP, aohand, 2, 4, /* 0x38 */ +X CMP, aohand, 2, 4, /* 0x39 */ +X CMP, aohand, 2, 4, /* 0x3a */ +X CMP, aohand, 2, 4, /* 0x3b */ +X CMP, aohand, 2, 2, /* 0x3c */ +X CMP, aohand, 3, 3, /* 0x3d */ +X "\tseg\tds", sbhand, 1, 1, /* 0x3e */ +X "\taas", sbhand, 1, 1, /* 0x3f */ +X "\tinc\tax", sbhand, 1, 1, /* 0x40 */ +X "\tinc\tcx", sbhand, 1, 1, /* 0x41 */ +X "\tinc\tdx", sbhand, 1, 1, /* 0x42 */ +X "\tinc\tbx", sbhand, 1, 1, /* 0x43 */ +X "\tinc\tsp", sbhand, 1, 1, /* 0x44 */ +X "\tinc\tbp", sbhand, 1, 1, /* 0x45 */ +X "\tinc\tsi", sbhand, 1, 1, /* 0x46 */ +X "\tinc\tdi", sbhand, 1, 1, /* 0x47 */ +X "\tdec\tax", sbhand, 1, 1, /* 0x48 */ +X "\tdec\tcx", sbhand, 1, 1, /* 0x49 */ +X "\tdec\tdx", sbhand, 1, 1, /* 0x4a */ +X "\tdec\tbx", sbhand, 1, 1, /* 0x4b */ +X "\tdec\tsp", sbhand, 1, 1, /* 0x4c */ +X "\tdec\tbp", sbhand, 1, 1, /* 0x4d */ +X "\tdec\tsi", sbhand, 1, 1, /* 0x4e */ +X "\tdec\tdi", sbhand, 1, 1, /* 0x4f */ +X "\tpush\tax", sbhand, 1, 1, /* 0x50 */ +X "\tpush\tcx", sbhand, 1, 1, /* 0x51 */ +X "\tpush\tdx", sbhand, 1, 1, /* 0x52 */ +X "\tpush\tbx", sbhand, 1, 1, /* 0x53 */ +X "\tpush\tsp", sbhand, 1, 1, /* 0x54 */ +X "\tpush\tbp", sbhand, 1, 1, /* 0x55 */ +X "\tpush\tsi", sbhand, 1, 1, /* 0x56 */ +X "\tpush\tdi", sbhand, 1, 1, /* 0x57 */ +X "\tpop\tax", sbhand, 1, 1, /* 0x58 */ +X "\tpop\tcx", sbhand, 1, 1, /* 0x59 */ +X "\tpop\tdx", sbhand, 1, 1, /* 0x5a */ +X "\tpop\tbx", sbhand, 1, 1, /* 0x5b */ +X "\tpop\tsp", sbhand, 1, 1, /* 0x5c */ +X "\tpop\tbp", sbhand, 1, 1, /* 0x5d */ +X "\tpop\tsi", sbhand, 1, 1, /* 0x5e */ +X "\tpop\tdi", sbhand, 1, 1, /* 0x5f */ +X NULL, dfhand, 0, 0, /* 0x60 */ +X NULL, dfhand, 0, 0, /* 0x61 */ +X NULL, dfhand, 0, 0, /* 0x62 */ +X NULL, dfhand, 0, 0, /* 0x63 */ +X NULL, dfhand, 0, 0, /* 0x64 */ +X NULL, dfhand, 0, 0, /* 0x65 */ +X NULL, dfhand, 0, 0, /* 0x66 */ +X NULL, dfhand, 0, 0, /* 0x67 */ +X NULL, dfhand, 0, 0, /* 0x68 */ +X NULL, dfhand, 0, 0, /* 0x69 */ +X NULL, dfhand, 0, 0, /* 0x6a */ +X NULL, dfhand, 0, 0, /* 0x6b */ +X NULL, dfhand, 0, 0, /* 0x6c */ +X NULL, dfhand, 0, 0, /* 0x6d */ +X NULL, dfhand, 0, 0, /* 0x6e */ +X NULL, dfhand, 0, 0, /* 0x6f */ +X "\tjo", sjhand, 2, 2, /* 0x70 */ +X "\tjno", sjhand, 2, 2, /* 0x71 */ +X "\tjc", sjhand, 2, 2, /* 0x72 */ +X "\tjnc", sjhand, 2, 2, /* 0x73 */ +X "\tjz", sjhand, 2, 2, /* 0x74 */ +X "\tjnz", sjhand, 2, 2, /* 0x75 */ +X "\tjna", sjhand, 2, 2, /* 0x76 */ +X "\tja", sjhand, 2, 2, /* 0x77 */ +X "\tjs", sjhand, 2, 2, /* 0x78 */ +X "\tjns", sjhand, 2, 2, /* 0x79 */ +X "\tjp", sjhand, 2, 2, /* 0x7a */ +X "\tjnp", sjhand, 2, 2, /* 0x7b */ +X "\tjl", sjhand, 2, 2, /* 0x7c */ +X "\tjnl", sjhand, 2, 2, /* 0x7d */ +X "\tjng", sjhand, 2, 2, /* 0x7e */ +X "\tjg", sjhand, 2, 2, /* 0x7f */ +X AMBIG, imhand, 3, 5, /* 0x80 */ +X AMBIG, imhand, 4, 6, /* 0x81 */ +X AMBIG, imhand, 3, 5, /* 0x82 */ +X AMBIG, imhand, 3, 5, /* 0x83 */ +X TEST, mvhand, 2, 4, /* 0x84 */ +X TEST, mvhand, 2, 4, /* 0x85 */ +X "\txchg", mvhand, 2, 4, /* 0x86 */ +X "\txchg", mvhand, 2, 4, /* 0x87 */ +X MOV, mvhand, 2, 4, /* 0x88 */ +X MOV, mvhand, 2, 4, /* 0x89 */ +X MOV, mvhand, 2, 4, /* 0x8a */ +X MOV, mvhand, 2, 4, /* 0x8b */ +X MOV, mshand, 2, 4, /* 0x8c */ +X "\tlea", mvhand, 2, 4, /* 0x8d */ +X MOV, mshand, 2, 4, /* 0x8e */ +X "\tpop", pohand, 2, 4, /* 0x8f */ +X "\tnop", sbhand, 1, 1, /* 0x90 */ +X "\txchg\tax,cx", sbhand, 1, 1, /* 0x91 */ +X "\txchg\tax,dx", sbhand, 1, 1, /* 0x92 */ +X "\txchg\tax,bx", sbhand, 1, 1, /* 0x93 */ +X "\txchg\tax,sp", sbhand, 1, 1, /* 0x94 */ +X "\txchg\tax,bp", sbhand, 1, 1, /* 0x95 */ +X "\txchg\tax,si", sbhand, 1, 1, /* 0x96 */ +X "\txchg\tax,di", sbhand, 1, 1, /* 0x97 */ +X "\tcbw", sbhand, 1, 1, /* 0x98 */ +X "\tcwd", sbhand, 1, 1, /* 0x99 */ +X "\tcalli", cihand, 5, 5, /* 0x9a */ +X "\twait", sbhand, 1, 1, /* 0x9b */ +X "\tpushf", sbhand, 1, 1, /* 0x9c */ +X "\tpopf", sbhand, 1, 1, /* 0x9d */ +X "\tsahf", sbhand, 1, 1, /* 0x9e */ +X "\tlahf", sbhand, 1, 1, /* 0x9f */ +X MOV, mqhand, 3, 3, /* 0xa0 */ +X MOV, mqhand, 3, 3, /* 0xa1 */ +X MOV, mqhand, 3, 3, /* 0xa2 */ +X MOV, mqhand, 3, 3, /* 0xa3 */ +X "\tmovb", sbhand, 1, 1, /* 0xa4 */ +X "\tmovw", sbhand, 1, 1, /* 0xa5 */ +X "\tcmpb", sbhand, 1, 1, /* 0xa6 */ +X "\tcmpw", sbhand, 1, 1, /* 0xa7 */ +X TEST, tqhand, 2, 2, /* 0xa8 */ +X TEST, tqhand, 3, 3, /* 0xa9 */ +X "\tstob", sbhand, 1, 1, /* 0xaa */ +X "\tstow", sbhand, 1, 1, /* 0xab */ +X "\tlodb", sbhand, 1, 1, /* 0xac */ +X "\tlodw", sbhand, 1, 1, /* 0xad */ +X "\tscab", sbhand, 1, 1, /* 0xae */ +X "\tscaw", sbhand, 1, 1, /* 0xaf */ +X "\tmov\tal,", mihand, 2, 2, /* 0xb0 */ +X "\tmov\tcl,", mihand, 2, 2, /* 0xb1 */ +X "\tmov\tdl,", mihand, 2, 2, /* 0xb2 */ +X "\tmov\tbl,", mihand, 2, 2, /* 0xb3 */ +X "\tmov\tah,", mihand, 2, 2, /* 0xb4 */ +X "\tmov\tch,", mihand, 2, 2, /* 0xb5 */ +X "\tmov\tdh,", mihand, 2, 2, /* 0xb6 */ +X "\tmov\tbh,", mihand, 2, 2, /* 0xb7 */ +X "\tmov\tax,", mihand, 3, 3, /* 0xb8 */ +X "\tmov\tcx,", mihand, 3, 3, /* 0xb9 */ +X "\tmov\tdx,", mihand, 3, 3, /* 0xba */ +X "\tmov\tbx,", mihand, 3, 3, /* 0xbb */ +X "\tmov\tsp,", mihand, 3, 3, /* 0xbc */ +X "\tmov\tbp,", mihand, 3, 3, /* 0xbd */ +X "\tmov\tsi,", mihand, 3, 3, /* 0xbe */ +X "\tmov\tdi,", mihand, 3, 3, /* 0xbf */ +X NULL, dfhand, 0, 0, /* 0xc0 */ +X NULL, dfhand, 0, 0, /* 0xc1 */ +X "\tret", rehand, 3, 3, /* 0xc2 */ +X "\tret", sbhand, 1, 1, /* 0xc3 */ +X "\tles", mvhand, 2, 4, /* 0xc4 */ +X "\tlds", mvhand, 2, 4, /* 0xc5 */ +X MOV, mmhand, 3, 5, /* 0xc6 */ +X MOV, mmhand, 4, 6, /* 0xc7 */ +X NULL, dfhand, 0, 0, /* 0xc8 */ +X NULL, dfhand, 0, 0, /* 0xc9 */ +X "\treti", rehand, 3, 3, /* 0xca */ +X "\treti", sbhand, 1, 1, /* 0xcb */ +X "\tint", sbhand, 1, 1, /* 0xcc */ +X "\tint", inhand, 2, 2, /* 0xcd */ +X "\tinto", sbhand, 1, 1, /* 0xce */ +X "\tiret", sbhand, 1, 1, /* 0xcf */ +X AMBIG, srhand, 2, 4, /* 0xd0 */ +X AMBIG, srhand, 2, 4, /* 0xd1 */ +X AMBIG, srhand, 2, 4, /* 0xd2 */ +X AMBIG, srhand, 2, 4, /* 0xd3 */ +X "\taam", aahand, 2, 2, /* 0xd4 */ +X "\taad", aahand, 2, 2, /* 0xd5 */ +X NULL, dfhand, 0, 0, /* 0xd6 */ +X "\txlat", sbhand, 1, 1, /* 0xd7 */ +X ESC, eshand, 2, 2, /* 0xd8 */ +X ESC, eshand, 2, 2, /* 0xd9 */ +X ESC, eshand, 2, 2, /* 0xda */ +X ESC, eshand, 2, 2, /* 0xdb */ +X ESC, eshand, 2, 2, /* 0xdc */ +X ESC, eshand, 2, 2, /* 0xdd */ +X ESC, eshand, 2, 2, /* 0xde */ +X ESC, eshand, 2, 2, /* 0xdf */ +X "\tloopne", sjhand, 2, 2, /* 0xe0 */ +X "\tloope", sjhand, 2, 2, /* 0xe1 */ +X "\tloop", sjhand, 2, 2, /* 0xe2 */ +X "\tjcxz", sjhand, 2, 2, /* 0xe3 */ +X "\tin", iohand, 2, 2, /* 0xe4 */ +X "\tinw", iohand, 2, 2, /* 0xe5 */ +X "\tout", iohand, 2, 2, /* 0xe6 */ +X "\toutw", iohand, 2, 2, /* 0xe7 */ +X "\tcall", ljhand, 3, 3, /* 0xe8 */ +X "\tjmp", ljhand, 3, 3, /* 0xe9 */ +X "\tjmpi", cihand, 5, 5, /* 0xea */ +X "\tj", sjhand, 2, 2, /* 0xeb */ +X "\tin", sbhand, 1, 1, /* 0xec */ +X "\tinw", sbhand, 1, 1, /* 0xed */ +X "\tout", sbhand, 1, 1, /* 0xee */ +X "\toutw", sbhand, 1, 1, /* 0xef */ +X "\tlock", sbhand, 1, 1, /* 0xf0 */ +X NULL, dfhand, 0, 0, /* 0xf1 */ +X "\trepnz", sbhand, 1, 1, /* 0xf2 */ +X "\trepz", sbhand, 1, 1, /* 0xf3 */ +X "\thlt", sbhand, 1, 1, /* 0xf4 */ +X "\tcmc", sbhand, 1, 1, /* 0xf5 */ +X AMBIG, mahand, 2, 5, /* 0xf6 */ +X AMBIG, mahand, 2, 6, /* 0xf7 */ +X "\tclc", sbhand, 1, 1, /* 0xf8 */ +X "\tstc", sbhand, 1, 1, /* 0xf9 */ +X "\tcli", sbhand, 1, 1, /* 0xfa */ +X "\tsti", sbhand, 1, 1, /* 0xfb */ +X "\tcld", sbhand, 1, 1, /* 0xfc */ +X "\tstd", sbhand, 1, 1, /* 0xfd */ +X AMBIG, mjhand, 2, 4, /* 0xfe */ +X AMBIG, mjhand, 2, 4 /* 0xff */ +X }; +X +X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +X * * +X * This simple routine returns the name field of a symbol * +X * table entry as a printable string. * +X * * +X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +X +char * +getnam(k) +X +X register int k; +X +X{/* * * * * * * * * * START OF getnam() * * * * * * * * * */ +X +X register int j; +X static char a[9]; +X +X for (j = 0; j < 8; ++j) +X if ( ! symtab[k].n_name[j] ) +X break; +X else +X a[j] = symtab[k].n_name[j]; +X +X a[j] = '\0'; +X +X return (a); +X +X}/* * * * * * * * * * * END OF getnam() * * * * * * * * * * */ +X +X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +X * * +X * This function is responsible for mucking through the * +X * relocation table in search of externally referenced * +X * symbols to be output as operands. It accepts two long * +X * arguments: the code-segment location at which an extern * +X * reference is expected, and the offset value which is * +X * embedded in the object code and used at link time to * +X * bias the external value. In the most typical case, the * +X * function will be called by lookup(), which always makes * +X * a check for external names before searching the symbol * +X * table proper. However, it may also be called directly * +X * by any function (such as the move-immediate handler) * +X * which wants to make an independent check for externals. * +X * The caller is expected to supply, as the third argument * +X * to the function, a pointer to a character buffer large * +X * enough to hold any possible output string. Lookext() * +X * will fill this buffer and return a logical TRUE if it * +X * finds an extern reference; otherwise, it will return a * +X * logical FALSE, leaving the buffer undisturbed. * +X * * +X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +X +int +lookext(off,loc,buf) +X +X long off, loc; +X char *buf; +X +X{/* * * * * * * * * * START OF lookext() * * * * * * * * * */ +X +X register int k; +X char c[16]; +X +X if ((loc != -1L) && (relptr >= 0)) +X for (k = 0; k <= relptr; ++k) +X if ((relo[k].r_vaddr == loc) +X && (relo[k].r_symndx < S_BSS)) +X { +X strcpy(buf,getnam(relo[k].r_symndx)); +X if (off) +X { +X if (off < 0) +X sprintf(c,"%ld",off); +X else +X sprintf(c,"+%ld",off); +X strcat(buf,c); +X } +X return (1); +X } +X +X return (0); +X +X}/* * * * * * * * * * END OF lookext() * * * * * * * * * */ +X +X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +X * * +X * This function finds an entry in the symbol table by * +X * value. Its input is a (long) machine address, and its * +X * output is a pointer to a string containing the corre- * +X * sponding symbolic name. The function first searches the * +X * relocation table for a possible external reference; if * +X * none is found, a linear search of the symbol table is * +X * undertaken. If no matching symbol has been found at the * +X * end of these searches, the function returns a pointer * +X * to a string containing the ASCII equivalent of the ad- * +X * dress which was to be located, so that, regardless of * +X * the success of the search, the function's return value * +X * is suitable for use as a memory-reference operand. The * +X * caller specifies the type of symbol to be found (text, * +X * data, bss, undefined, absolute, or common) by means of * +X * the function's second parameter. The third parameter * +X * specifies the format to be used in the event of a nu- * +X * meric output: zero for absolute format, one for short * +X * relative format, two for long relative format. The * +X * fourth parameter is the address which would appear in * +X * the relocation table for the reference in question, or * +X * -1 if the relocation table is not to be searched. The * +X * function attempts to apply a certain amount of intelli- * +X * gence in its selection of symbols, so it is possible * +X * that, in the absence of a type match, a symbol of the * +X * correct value but different type will be returned. * +X * * +X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +X +char * +lookup(addr,type,kind,ext) +X +X long addr; /* Machine address to be located */ +X +X int type, /* Type of symbol to be matched */ +X kind; /* Addressing output mode to use */ +X +X long ext; /* Value for extern ref, if any */ +X +X{/* * * * * * * * * * START OF lookup() * * * * * * * * * */ +X +X register int j, k; +X static char b[64]; +X +X struct +X { +X int i; +X int t; +X } +X best; +X +X if (lookext(addr,ext,b)) +X return (b); +X +X if (segflg) +X if (segflg & 1) +X type = N_TEXT; +X else +X type = N_DATA; +X +X for (k = 0, best.i = -1; k <= symptr; ++k) +X if (symtab[k].n_value == addr) +X if ((j = symtab[k].n_sclass & N_SECT) == type) +X { +X best.t = j; +X best.i = k; +X break; +X } +X else if (segflg || (HDR.a_flags & A_SEP)) +X continue; +X else if (best.i < 0) +X best.t = j, best.i = k; +X else if (symrank[type][j] > symrank[type][best.t]) +X best.t = j, best.i = k; +X +X if (best.i >= 0) +X return (getnam(best.i)); +X +X if (kind == LOOK_ABS) +X sprintf(b,"0x%05.5x",addr); +X else +X { +X long x = addr - (PC - kind); +X if (x < 0) +X sprintf(b,".%ld",x); +X else +X sprintf(b,".+%ld",x); +X } +X +X return (b); +X +X}/* * * * * * * * * * * END OF lookup() * * * * * * * * * * */ +X +X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +X * * +X * This function translates an 8088 addressing mode byte * +X * to an equivalent assembler string, returning a pointer * +X * thereto. If necessary, it performs successive inputs * +X * of bytes from the object file in order to obtain offset * +X * data, adjusting PC accordingly. (The addressing mode * +X * byte appears in several 8088 opcodes; it is used to * +X * specify source and destination operand locations.) The * +X * third argument to the function is zero if the standard * +X * registers are to be used, or eight if the segment reg- * +X * isters are to be used; these constants are defined sym- * +X * bolically in dis.h. NOTE: The mtrans() function must * +X * NEVER be called except immediately after fetching the * +X * mode byte. If any additional object bytes are fetched * +X * after the fetch of the mode byte, mtrans() will not * +X * produce correct output! * +X * * +X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +X +char * +mtrans(c,m,type) +X +X register int c; /* Primary instruction byte */ +X register int m; /* Addressing mode byte */ +X +X int type; /* Type code: standard or seg */ +X +X{/* * * * * * * * * * START OF mtrans() * * * * * * * * * */ +X +X unsigned long pc; +X int offset, oflag, dir, w, mod, reg, rm; +X static char a[100]; +X static char b[30]; +X +X offset = 0; +X dir = c & 2; +X w = c & 1; +X mod = (m & 0xc0) >> 6; +X reg = (m & 0x38) >> 3; +X rm = m & 7; +X pc = PC + 1; +X +X if (type) +X w = 1; +X +X if ((oflag = mod) > 2) +X oflag = 0; +X +X if (oflag) +X { +X int j, k; +X if (oflag == 2) +X { +X FETCH(j); +X FETCH(k); +X offset = (k << 8) | j; +X } +X else +X { +X FETCH(j); +X if (j & 0x80) +X k = 0xff00; +X else +X k = 0; +X offset = k | j; +X } +X } +X +X if (dir) +X { +X strcpy(a,REGS[type + ((w << 3) | reg)]); +X strcat(a,","); +X switch (mod) +X { +X case 0 : +X if (rm == 6) +X { +X int j, k; +X FETCH(j); +X FETCH(k); +X offset = (k << 8) | j; +X strcat(a, +X lookup((long)(offset),N_DATA,LOOK_ABS,pc)); +X } +X else +X { +X sprintf(b,"(%s)",REGS0[rm]); +X strcat(a,b); +X } +X break; +X case 1 : +X case 2 : +X if (mod == 1) +X strcat(a,"*"); +X else +X strcat(a,"#"); +X sprintf(b,"%d(",offset); +X strcat(a,b); +X strcat(a,REGS1[rm]); +X strcat(a,")"); +X break; +X case 3 : +X strcat(a,REGS[(w << 3) | rm]); +X break; +X } +X } +X else +X { +X switch (mod) +X { +X case 0 : +X if (rm == 6) +X { +X int j, k; +X FETCH(j); +X FETCH(k); +X offset = (k << 8) | j; +X strcpy(a, +X lookup((long)(offset),N_DATA,LOOK_ABS,pc)); +X } +X else +X { +X sprintf(b,"(%s)",REGS0[rm]); +X strcpy(a,b); +X } +X break; +X case 1 : +X case 2 : +X if (mod == 1) +X strcpy(a,"*"); +X else +X strcpy(a,"#"); +X sprintf(b,"%d(",offset); +X strcat(a,b); +X strcat(a,REGS1[rm]); +X strcat(a,")"); +X break; +X case 3 : +X strcpy(a,REGS[(w << 3) | rm]); +X break; +X } +X strcat(a,","); +X strcat(a,REGS[type + ((w << 3) | reg)]); +X } +X +X return (a); +X +X}/* * * * * * * * * * * END OF mtrans() * * * * * * * * * * */ +X +X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +X * * +X * This simple routine truncates a string returned by the * +X * mtrans() function, removing its source operand. This is * +X * useful in handlers which ignore the "reg" field of the * +X * mode byte. * +X * * +X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +X +void +mtrunc(a) +X +X register char *a; /* Ptr. to string to truncate */ +X +X{/* * * * * * * * * * START OF mtrunc() * * * * * * * * * */ +X +X register int k; +X +X for (k = strlen(a) - 1; k >= 0; --k) +X if (a[k] == ',') +X { +X a[k] = '\0'; +X break; +X } +X +X}/* * * * * * * * * * * END OF mtrunc() * * * * * * * * * * */ +X +X +END_OF_FILE +if test 30238 -ne `wc -c <'distabs.c'`; then + echo shar: \"'distabs.c'\" unpacked with wrong size! +fi +# end of 'distabs.c' +fi +echo shar: End of archive 2 \(of 2\). +cp /dev/null ark2isdone +MISSING="" +for I in 1 2 ; do + if test ! -f ark${I}isdone ; then + MISSING="${MISSING} ${I}" + fi +done +if test "${MISSING}" = "" ; then + echo You have unpacked both archives. + rm -f ark[1-9]isdone +else + echo You still need to unpack the following archives: + echo " " ${MISSING} +fi +## End of shell archive. +exit 0 -- cgit v1.2.1 From 42192453ea219b80d0bf9f41e51e36d3d4d0740b Mon Sep 17 00:00:00 2001 From: Robert de Bath Date: Tue, 1 Oct 1996 14:00:00 +0200 Subject: Import dis88-minix --- MANIFEST | 12 - Makefile | 30 +- README | 148 +++++ dis.h | 144 ++--- dis88.1 | 147 ----- dismain.c | 67 ++- disrel.c | 4 +- part01 | 1448 ------------------------------------------------ part02 | 1812 ------------------------------------------------------------- 9 files changed, 259 insertions(+), 3553 deletions(-) delete mode 100644 MANIFEST delete mode 100644 dis88.1 delete mode 100644 part01 delete mode 100644 part02 diff --git a/MANIFEST b/MANIFEST deleted file mode 100644 index f6b6e33..0000000 --- a/MANIFEST +++ /dev/null @@ -1,12 +0,0 @@ - File Name Archive # Description ------------------------------------------------------------ - MANIFEST 1 - Makefile 1 - README 1 - dis.h 1 - dis88.1 1 - disfp.c 1 - dishand.c 2 - dismain.c 1 - disrel.c 1 - distabs.c 2 diff --git a/Makefile b/Makefile index c1352f0..05d2488 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,5 @@ +# Makefile for dis + # @(#) Makefile, Ver. 2.1 created 00:00:00 87/09/01 # Makefile for 8088 symbolic disassembler @@ -22,24 +24,26 @@ # the initialization data in the lookup tables. It should not # be necessary to alter the formats of the tables. +CFLAGS =-O -wo OBJ = disrel.o dismain.o distabs.o dishand.o disfp.o -dis88 : $(OBJ) - ld -i -s -o dis88 /lib/crt0.o $(OBJ) -lc - size dis88 - @echo "\07Build of 'dis88' complete." > /dev/tty - -.c.o : - cc -O -c $< - chmod 600 $*.o +all: dis88 -disrel.o : disrel.c +dis88: $(OBJ) + cc -i -o dis88 $(OBJ) + install -S 5kw dis88 -dismain.o : dismain.c dis.h +install: /usr/bin/dis88 -distabs.o : distabs.c dis.h +/usr/bin/dis88: dis88 + install -cs -o bin dis88 $@ -dishand.o : dishand.c dis.h +disrel.o: disrel.c +dismain.o: dismain.c dis.h +distabs.o: distabs.c dis.h +dishand.o: dishand.c dis.h +disfp.o: disfp.c dis.h -disfp.o : disfp.c dis.h +clean: + rm -f *.bak *.o core dis88 diff --git a/README b/README index d0c80dc..a007634 100644 --- a/README +++ b/README @@ -89,3 +89,151 @@ each disassembly. Release 2.1 of the program is the first beta release to be distributed on Usenet. + +.TH dis88 1 LOCAL +.SH "NAME" +dis88 \- 8088 symbolic disassembler +.SH "SYNOPSIS" +\fBdis88\fP [ -o ] ifile [ ofile ] +.SH "DESCRIPTION" +Dis88 reads ifile, which must be in PC/IX a.out format. +It interprets the binary opcodes and data locations, and +writes corresponding assembler source code to stdout, or +to ofile if specified. The program's output is in the +format of, and fully compatible with, the PC/IX assembler, +as(1). If a symbol table is present in ifile, labels and +references will be symbolic in the output. If the input +file lacks a symbol table, the fact will be noted, and the +disassembly will proceed, with the disassembler generating +synthetic labels as needed. If the input file has split +I/D space, or if it is executable, the disassembler will +make all necessary adjustments in address-reference calculations. +.PP +If the "-o" option appears, object code will be included +in comments during disassembly of the text segment. This +feature is used primarily for debugging the disassembler +itself, but may provide information of passing interest +to users. +.PP +The program always outputs the current machine address +before disassembling an opcode. If a symbol table is +present, this address is output as an assembler comment; +otherwise, it is incorporated into the synthetic label +which is generated internally. Since relative jumps, +especially short ones, may target unlabelled locations, +the program always outputs the physical target address +as a comment, to assist the user in following the code. +.PP +The text segment of an object file is always padded to +an even machine address. In addition, if the file has +split I/D space, the text segment will be padded to a +paragraph boundary (i.e., an address divisible by 16). +As a result of this padding, the disassembler may produce +a few spurious, but harmless, instructions at the +end of the text segment. +.PP +Disassembly of the data segment is a difficult matter. +The information to which initialized data refers cannot +be inferred from context, except in the special case +of an external data or address reference, which will be +reflected in the relocation table. Internal data and +address references will already be resolved in the object file, +and cannot be recreated. Therefore, the data +segment is disassembled as a byte stream, with long +stretches of null data represented by an appropriate +".zerow" pseudo-op. This limitation notwithstanding, +labels (as opposed to symbolic references) are always +output at appropriate points within the data segment. +.PP +If disassembly of the data segment is difficult, disassembly of the +bss segment is quite easy, because uninitialized data is all +zero by definition. No data +is output in the bss segment, but symbolic labels are +output as appropriate. +.PP +For each opcode which takes an operand, a particular +symbol type (text, data, or bss) is appropriate. This +tidy correspondence is complicated somewhat, however, +by the existence of assembler symbolic constants and +segment override opcodes. Therefore, the disassembler's +symbol lookup routine attempts to apply a certain amount +of intelligence when it is asked to find a symbol. If +it cannot match on a symbol of the preferred type, it +may return a symbol of some other type, depending on +preassigned (and somewhat arbitrary) rankings within +each type. Finally, if all else fails, it returns a +string containing the address sought as a hex constant; +this behavior allows calling routines to use the output +of the lookup function regardless of the success of its +search. +.PP +It is worth noting, at this point, that the symbol lookup +routine operates linearly, and has not been optimized in +any way. Execution time is thus likely to increase +geometrically with input file size. The disassembler is +internally limited to 1500 symbol table entries and 1500 +relocation table entries; while these limits are generous +(/unix, itself, has fewer than 800 symbols), they are not +guaranteed to be adequate in all cases. If the symbol +table or the relocation table overflows, the disassembly +aborts. +.PP +Finally, users should be aware of a bug in the assembler, +which causes it not to parse the "esc" mnemonic, even +though "esc" is a completely legitimate opcode which is +documented in all the Intel literature. To accommodate +this deficiency, the disassembler translates opcodes of +the "esc" family to .byte directives, but notes the +correct mnemonic in a comment for reference. +.PP +In all cases, it should be possible to submit the output +of the disassembler program to the assembler, and assemble +it without error. In most cases, the resulting object +code will be identical to the original; in any event, it +will be functionally equivalent. +.SH "SEE ALSO" +adb(1), as(1), cc(1), ld(1). +.br +"Assembler Reference Manual" in the PC/IX Programmer's +Guide. +.SH "DIAGNOSTICS" +"can't access input file" if the input file cannot be +found, opened, or read. +.sp +"can't open output file" if the output file cannot be +created. +.sp +"warning: host/cpu clash" if the program is run on a +machine with a different CPU. +.sp +"input file not in object format" if the magic number +does not correspond to that of a PC/IX object file. +.sp +"not an 8086/8088 object file" if the CPU ID of the +file header is incorrect. +.sp +"reloc table overflow" if there are more than 1500 +entries in the relocation table. +.sp +"symbol table overflow" if there are more than 1500 +entries in the symbol table. +.sp +"lseek error" if the input file is corrupted (should +never happen). +.sp +"warning: no symbols" if the symbol table is missing. +.sp +"can't reopen input file" if the input file is removed +or altered during program execution (should never happen). +.SH "BUGS" +Numeric co-processor (i.e., 8087) mnemonics are not currently supported. +Instructions for the co-processor are +disassembled as CPU escape sequences, or as interrupts, +depending on how they were assembled in the first place. +.sp +Despite the program's best efforts, a symbol retrieved +from the symbol table may sometimes be different from +the symbol used in the original assembly. +.sp +The disassembler's internal tables are of fixed size, +and the program aborts if they overflow. diff --git a/dis.h b/dis.h index 9f93b38..d8fc245 100644 --- a/dis.h +++ b/dis.h @@ -24,15 +24,13 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -#include /* System standard I/O definitions */ -#include /* System file-control definitions */ +#include #include /* Object file format definitions */ - -#if i8086 || i8088 /* For CPU's with 16-bit integers */ -#undef int -#else /* Defaults (for 32-bit CPU types) */ -#define int short -#endif +#include /* System file-control definitions */ +#include +#include +#include +#include /* System standard I/O definitions */ #define MAXSYM 1500 /* Maximum entries in symbol table */ @@ -43,61 +41,21 @@ extern struct reloc /* Array to hold relocation table */ relo[MAXSYM]; extern int symptr; /* Index into the symtab[] array */ - extern int relptr; /* Index into the relo[] array */ struct opcode /* Format for opcode data records */ - { - char *text; /* Pointer to mnemonic text */ - void (*func)(); /* Pointer to handler routine */ - unsigned min; /* Minimum # of object bytes */ - unsigned max; /* Maximum # of object bytes */ - }; +{ + char *text; /* Pointer to mnemonic text */ + void (*func)(); /* Pointer to handler routine */ + unsigned min; /* Minimum # of object bytes */ + unsigned max; /* Maximum # of object bytes */ +}; extern struct opcode /* Array to hold the opcode table */ optab[256]; - /* - +--------------------------------------------- - | The following functions are the specialized - | handlers for each opcode group. They are, of - | course, highly MACHINE-SPECIFIC. Each entry - | in the opcode[] array contains a pointer to - | one of these handlers. The handlers in the - | first group are in dishand.c; those in the - | second group are in disfp.c. - +--------------------------------------------- - */ - -extern void dfhand(), /* Default handler routine */ - sbhand(), /* Single-byte handler */ - aohand(), /* Arithmetic-op handler */ - sjhand(), /* Short-jump handler */ - imhand(), /* Immediate-operand handler */ - mvhand(), /* Simple move handler */ - mshand(), /* Segreg-move handler */ - pohand(), /* Pop memory/reg handler */ - cihand(), /* Intersegment call handler */ - mihand(), /* Immediate-move handler */ - mqhand(), /* Quick-move handler */ - tqhand(), /* Quick-test handler */ - rehand(), /* Return handler */ - mmhand(), /* Move-to-memory handler */ - srhand(), /* Shift and rotate handler */ - aahand(), /* ASCII-adjust handler */ - iohand(), /* Immediate port I/O handler */ - ljhand(), /* Long-jump handler */ - mahand(), /* Misc. arithmetic handler */ - mjhand(); /* Miscellaneous jump handler */ - -extern void eshand(), /* Bus-escape opcode handler */ - fphand(), /* Floating-point handler */ - inhand(); /* Interrupt-opcode handler */ - extern char *REGS[]; /* Table of register names */ - extern char *REGS0[]; /* Mode 0 register name table */ - extern char *REGS1[]; /* Mode 1 register name table */ #define AL REGS[0] /* CPU register manifests */ @@ -126,11 +84,8 @@ extern char *REGS1[]; /* Mode 1 register name table */ #define BP_DI REGS0[3] extern int symrank[6][6]; /* Symbol type/rank matrix */ - extern unsigned long PC; /* Current program counter */ - extern int segflg; /* Flag: segment override in effect */ - extern int objflg; /* Flag: output object as a comment */ #define OBJMAX 8 /* Size of the object code buffer */ @@ -138,23 +93,8 @@ extern int objflg; /* Flag: output object as a comment */ extern unsigned char /* Internal buffer for object code */ objbuf[OBJMAX]; -extern void objini(), /* Object-buffer init routine */ - objout(); /* Object-code output routine */ - extern int objptr; /* Index into the objbuf[] array */ -extern void badseq(); /* Bad-code-sequence function */ - -extern char *getnam(); /* Symbol-name string function */ - -extern char *lookup(); /* Symbol-table lookup function */ - -extern int lookext(); /* Extern-definition lookup routine */ - -extern char *mtrans(); /* Interpreter for the mode byte */ - -extern void mtrunc(); /* Mode string truncator function */ - extern char ADD[], /* Opcode family mnemonic strings */ OR[], ADC[], @@ -173,7 +113,6 @@ extern char ADD[], /* Opcode family mnemonic strings */ AMBIG[]; extern char *OPFAM[]; /* Indexed mnemonic family table */ - extern struct exec HDR; /* Holds the object file's header */ #define LOOK_ABS 0 /* Arguments to lookup() function */ @@ -184,20 +123,45 @@ extern struct exec HDR; /* Holds the object file's header */ #define TR_SEG 8 /* Macro for byte input primitive */ -#define FETCH(p) \ - ++PC; p = getchar() & 0xff; objbuf[objptr++] = p - -extern int close(); /* System file-close primitive */ -extern int fprintf(); /* Library file-output function */ -extern long lseek(); /* System file-position primitive */ -extern int open(); /* System file-open primitive */ -extern int printf(); /* Library output-format function */ -extern int read(); /* System file-read primitive */ -extern int sprintf(); /* Library string-output function */ -extern char *strcat(); /* Library string-join function */ -extern char *strcpy(); /* Library string-copy function */ -extern int strlen(); /* Library string-length function */ - - /* * * * * * * * * * * END OF dis.h * * * * * * * * * * */ - - +#define FETCH(p) ++PC; p = getchar() & 0xff; objbuf[objptr++] = p + + +/* disfp.c */ +_PROTOTYPE(void eshand, (int j )); +_PROTOTYPE(void fphand, (int j )); +_PROTOTYPE(void inhand, (int j )); + +/* dishand.c */ +_PROTOTYPE(void objini, (int j )); +_PROTOTYPE(void objout, (void)); +_PROTOTYPE(void badseq, (int j, int k )); +_PROTOTYPE(void dfhand, (int j )); +_PROTOTYPE(void sbhand, (int j )); +_PROTOTYPE(void aohand, (int j )); +_PROTOTYPE(void sjhand, (int j )); +_PROTOTYPE(void imhand, (int j )); +_PROTOTYPE(void mvhand, (int j )); +_PROTOTYPE(void mshand, (int j )); +_PROTOTYPE(void pohand, (int j )); +_PROTOTYPE(void cihand, (int j )); +_PROTOTYPE(void mihand, (int j )); +_PROTOTYPE(void mqhand, (int j )); +_PROTOTYPE(void tqhand, (int j )); +_PROTOTYPE(void rehand, (int j )); +_PROTOTYPE(void mmhand, (int j )); +_PROTOTYPE(void srhand, (int j )); +_PROTOTYPE(void aahand, (int j )); +_PROTOTYPE(void iohand, (int j )); +_PROTOTYPE(void ljhand, (int j )); +_PROTOTYPE(void mahand, (int j )); +_PROTOTYPE(void mjhand, (int j )); + +/* dismain.c */ +_PROTOTYPE(void main, (int argc, char **argv )); + +/* distabs.c */ +_PROTOTYPE(char *getnam, (int k )); +_PROTOTYPE(int lookext, (long off, long loc, char *buf )); +_PROTOTYPE(char *lookup, (long addr, int type, int kind, long ext )); +_PROTOTYPE(char *mtrans, (int c, int m, int type )); +_PROTOTYPE(void mtrunc, (char *a )); diff --git a/dis88.1 b/dis88.1 deleted file mode 100644 index c991ad7..0000000 --- a/dis88.1 +++ /dev/null @@ -1,147 +0,0 @@ -.TH dis88 1 LOCAL -.SH "NAME" -dis88 \- 8088 symbolic disassembler -.SH "SYNOPSIS" -\fBdis88\fP [ -o ] ifile [ ofile ] -.SH "DESCRIPTION" -Dis88 reads ifile, which must be in PC/IX a.out format. -It interprets the binary opcodes and data locations, and -writes corresponding assembler source code to stdout, or -to ofile if specified. The program's output is in the -format of, and fully compatible with, the PC/IX assembler, -as(1). If a symbol table is present in ifile, labels and -references will be symbolic in the output. If the input -file lacks a symbol table, the fact will be noted, and the -disassembly will proceed, with the disassembler generating -synthetic labels as needed. If the input file has split -I/D space, or if it is executable, the disassembler will -make all necessary adjustments in address-reference calculations. -.PP -If the "-o" option appears, object code will be included -in comments during disassembly of the text segment. This -feature is used primarily for debugging the disassembler -itself, but may provide information of passing interest -to users. -.PP -The program always outputs the current machine address -before disassembling an opcode. If a symbol table is -present, this address is output as an assembler comment; -otherwise, it is incorporated into the synthetic label -which is generated internally. Since relative jumps, -especially short ones, may target unlabelled locations, -the program always outputs the physical target address -as a comment, to assist the user in following the code. -.PP -The text segment of an object file is always padded to -an even machine address. In addition, if the file has -split I/D space, the text segment will be padded to a -paragraph boundary (i.e., an address divisible by 16). -As a result of this padding, the disassembler may produce -a few spurious, but harmless, instructions at the -end of the text segment. -.PP -Disassembly of the data segment is a difficult matter. -The information to which initialized data refers cannot -be inferred from context, except in the special case -of an external data or address reference, which will be -reflected in the relocation table. Internal data and -address references will already be resolved in the object file, -and cannot be recreated. Therefore, the data -segment is disassembled as a byte stream, with long -stretches of null data represented by an appropriate -".zerow" pseudo-op. This limitation notwithstanding, -labels (as opposed to symbolic references) are always -output at appropriate points within the data segment. -.PP -If disassembly of the data segment is difficult, disassembly of the -bss segment is quite easy, because uninitialized data is all -zero by definition. No data -is output in the bss segment, but symbolic labels are -output as appropriate. -.PP -For each opcode which takes an operand, a particular -symbol type (text, data, or bss) is appropriate. This -tidy correspondence is complicated somewhat, however, -by the existence of assembler symbolic constants and -segment override opcodes. Therefore, the disassembler's -symbol lookup routine attempts to apply a certain amount -of intelligence when it is asked to find a symbol. If -it cannot match on a symbol of the preferred type, it -may return a symbol of some other type, depending on -preassigned (and somewhat arbitrary) rankings within -each type. Finally, if all else fails, it returns a -string containing the address sought as a hex constant; -this behavior allows calling routines to use the output -of the lookup function regardless of the success of its -search. -.PP -It is worth noting, at this point, that the symbol lookup -routine operates linearly, and has not been optimized in -any way. Execution time is thus likely to increase -geometrically with input file size. The disassembler is -internally limited to 1500 symbol table entries and 1500 -relocation table entries; while these limits are generous -(/unix, itself, has fewer than 800 symbols), they are not -guaranteed to be adequate in all cases. If the symbol -table or the relocation table overflows, the disassembly -aborts. -.PP -Finally, users should be aware of a bug in the assembler, -which causes it not to parse the "esc" mnemonic, even -though "esc" is a completely legitimate opcode which is -documented in all the Intel literature. To accommodate -this deficiency, the disassembler translates opcodes of -the "esc" family to .byte directives, but notes the -correct mnemonic in a comment for reference. -.PP -In all cases, it should be possible to submit the output -of the disassembler program to the assembler, and assemble -it without error. In most cases, the resulting object -code will be identical to the original; in any event, it -will be functionally equivalent. -.SH "SEE ALSO" -adb(1), as(1), cc(1), ld(1). -.br -"Assembler Reference Manual" in the PC/IX Programmer's -Guide. -.SH "DIAGNOSTICS" -"can't access input file" if the input file cannot be -found, opened, or read. -.sp -"can't open output file" if the output file cannot be -created. -.sp -"warning: host/cpu clash" if the program is run on a -machine with a different CPU. -.sp -"input file not in object format" if the magic number -does not correspond to that of a PC/IX object file. -.sp -"not an 8086/8088 object file" if the CPU ID of the -file header is incorrect. -.sp -"reloc table overflow" if there are more than 1500 -entries in the relocation table. -.sp -"symbol table overflow" if there are more than 1500 -entries in the symbol table. -.sp -"lseek error" if the input file is corrupted (should -never happen). -.sp -"warning: no symbols" if the symbol table is missing. -.sp -"can't reopen input file" if the input file is removed -or altered during program execution (should never happen). -.SH "BUGS" -Numeric co-processor (i.e., 8087) mnemonics are not currently supported. -Instructions for the co-processor are -disassembled as CPU escape sequences, or as interrupts, -depending on how they were assembled in the first place. -.sp -Despite the program's best efforts, a symbol retrieved -from the symbol table may sometimes be different from -the symbol used in the original assembly. -.sp -The disassembler's internal tables are of fixed size, -and the program aborts if they overflow. diff --git a/dismain.c b/dismain.c index b511785..d317f00 100644 --- a/dismain.c +++ b/dismain.c @@ -1,5 +1,4 @@ -static char *sccsid = - "@(#) dismain.c, Ver. 2.1 created 00:00:00 87/09/01"; +static char *sccsid = "@(#) dismain.c, Ver. 2.1 created 00:00:00 87/09/01"; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * @@ -33,30 +32,42 @@ static char *sccsid = #include "dis.h" /* Disassembler declarations */ extern char *release; /* Contains release string */ - static char *IFILE = NULL; /* Points to input file name */ - static char *OFILE = NULL; /* Points to output file name */ - static char *PRG; /* Name of invoking program */ - static unsigned long zcount; /* Consecutive "0" byte count */ - int objflg = 0; /* Flag: output object bytes */ +#define unix 1 +#define i8086 1 +#define ibmpc 1 + #if unix && i8086 && ibmpc /* Set the CPU identifier */ static int cpuid = 1; #else static int cpuid = 0; #endif - + +_PROTOTYPE(static void usage, (char *s )); +_PROTOTYPE(static void fatal, (char *s, char *t )); +_PROTOTYPE(static void zdump, (unsigned long beg )); +_PROTOTYPE(static void prolog, (void)); +_PROTOTYPE(static void distext, (void)); +_PROTOTYPE(static void disdata, (void)); +_PROTOTYPE(static void disbss, (void)); + +_PROTOTYPE(static char *invoker, (char *s)); +_PROTOTYPE(static int objdump, (char *c)); +_PROTOTYPE(static char *getlab, (int type)); +_PROTOTYPE(static void prolog, (void)); + /* * * * * * * MISCELLANEOUS UTILITY FUNCTIONS * * * * * * */ static void usage(s) register char *s; { - fprintf(stderr,"\07usage: %s [-o] ifile [ofile]\n",s); + fprintf(stderr,"Usage: %s [-o] ifile [ofile]\n",s); exit(-1); } @@ -83,7 +94,6 @@ static char * invoker(s) register char *s; { - extern int strlen(); register int k; k = strlen(s); @@ -98,7 +108,7 @@ invoker(s) return (s); } - + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This rather tricky routine supports the disdata() func- * @@ -170,7 +180,7 @@ objdump(c) return (retval); }/* * * * * * * * * * END OF objdump() * * * * * * * * * */ - + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This routine, called at the beginning of the input * @@ -186,9 +196,7 @@ objdump(c) static char * getlab(type) - - register int type; - +register int type; {/* * * * * * * * * * START OF getlab() * * * * * * * * * */ register int k; @@ -221,7 +229,7 @@ getlab(type) return (NULL); }/* * * * * * * * * * * END OF getlab() * * * * * * * * * * */ - + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This routine performs a preliminary scan of the symbol * @@ -307,7 +315,7 @@ prolog() putchar('\n'); }/* * * * * * * * * * * END OF prolog() * * * * * * * * * * */ - + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This function is responsible for disassembly of the * @@ -369,7 +377,7 @@ distext() } }/* * * * * * * * * * END OF distext() * * * * * * * * * */ - + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This function handles the object file's data segment. * @@ -430,7 +438,7 @@ disdata() objdump(""); }/* * * * * * * * * * END OF disdata() * * * * * * * * * */ - + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This function handles the object file's bss segment. * @@ -439,8 +447,7 @@ disdata() * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -static void -disbss() +static void disbss() {/* * * * * * * * * * START OF disbss() * * * * * * * * * */ @@ -475,7 +482,7 @@ disbss() zdump(beg); }/* * * * * * * * * * * END OF disbss() * * * * * * * * * * */ - + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This is the program entry point. The command line is * @@ -527,7 +534,7 @@ main(argc,argv) if (IFILE == NULL) usage(PRG); else - if ((fd = open(IFILE,O_RDONLY)) < 0) + if ((fd = open(IFILE,0)) < 0) { sprintf(a,"can't access input file %s",IFILE); fatal(PRG,a); @@ -543,7 +550,7 @@ main(argc,argv) if ( ! cpuid ) fprintf(stderr,"\07%s: warning: host/cpu clash\n",PRG); - read(fd,&HDR,sizeof(struct exec)); + read(fd, (char *) &HDR,sizeof(struct exec)); if (BADMAG(HDR)) { @@ -558,9 +565,11 @@ main(argc,argv) } if (HDR.a_hdrlen <= A_MINHDR) - HDR.a_trsize = HDR.a_drsize = - HDR.a_tbase = HDR.a_dbase = + HDR.a_trsize = HDR.a_drsize = 0L; + HDR.a_tbase = HDR.a_dbase = 0L; +/* AST emergency patch HDR.a_lnums = HDR.a_toffs = 0L; +*/ reloff = HDR.a_text /* Compute reloc data offset */ + HDR.a_data @@ -587,7 +596,7 @@ main(argc,argv) else { for (relptr = 0; relptr < relnum; ++relptr) - read(fd,&relo[relptr],sizeof(struct reloc)); + read(fd, (char *) &relo[relptr],sizeof(struct reloc)); relptr--; } @@ -597,7 +606,7 @@ main(argc,argv) else { for (symptr = 0; symptr < tabnum; ++symptr) - read(fd,&symtab[symptr],sizeof(struct nlist)); + read(fd, (char *) &symtab[symptr],sizeof(struct nlist)); symptr--; } else @@ -620,5 +629,3 @@ main(argc,argv) exit(0); }/* * * * * * * * * * * END OF main() * * * * * * * * * * */ - - diff --git a/disrel.c b/disrel.c index 1e28155..37f3221 100644 --- a/disrel.c +++ b/disrel.c @@ -5,7 +5,7 @@ static char *sccsid = "@(#) disrel.c, Ver. 2.1 created 00:00:00 87/09/01"; char *release = - "release 2.1 (PC/IX)"; + "release 2.1 (MINIX)"; /* ** @@ -24,5 +24,7 @@ char *release = ** SEP 87: ** After internal shakeout, released on Usenet. ** + ** JUN 88: + ** Ported to MINIX */ diff --git a/part01 b/part01 deleted file mode 100644 index f78b652..0000000 --- a/part01 +++ /dev/null @@ -1,1448 +0,0 @@ -Subject: v15i006: Symbolic disassembler for PC/IX, Part01/02 -Newsgroups: comp.sources.unix -Sender: sources -Approved: rsalz@uunet.UU.NET - -Submitted-by: "G. M. Harding" -Posting-number: Volume 15, Issue 6 -Archive-name: dis88/part01 - -[ I packed up the archives and turned the formatted manpage - into an unformatted one. --r$ ] - - "Dis88" is a symbolic disassembler for the Intel 8088 CPU, - designed to run under the PC/IX operating system on an IBM XT - or fully-compatible clone. Its output is in the format of, and - is completely compatible with, the PC/IX assembler, "as". The - program is copyrighted by its author, but may be copied and re- - distributed freely provided that complete source code, with all - copyright notices, accompanies any distribution. This provision - also applies to any modifications you may make. You are urged - to comment such changes, giving, as a miminum, your name and - complete address. - - --- - G. M. HARDING - POB 4142 - Santa Clara CA 95054-0142 - -#! /bin/sh -# This is a shell archive. Remove anything before this line, then unpack -# it by saving it into a file and typing "sh file". To overwrite existing -# files, type "sh file -c". You can also feed this as standard input via -# unshar, or by typing "sh 'MANIFEST' <<'END_OF_FILE' -X File Name Archive # Description -X----------------------------------------------------------- -X MANIFEST 1 -X Makefile 1 -X README 1 -X dis.h 1 -X dis88.1 1 -X disfp.c 1 -X dishand.c 2 -X dismain.c 1 -X disrel.c 1 -X distabs.c 2 -END_OF_FILE -if test 406 -ne `wc -c <'MANIFEST'`; then - echo shar: \"'MANIFEST'\" unpacked with wrong size! -fi -# end of 'MANIFEST' -fi -if test -f 'Makefile' -a "${1}" != "-c" ; then - echo shar: Will not clobber existing file \"'Makefile'\" -else -echo shar: Extracting \"'Makefile'\" \(1593 characters\) -sed "s/^X//" >'Makefile' <<'END_OF_FILE' -X# @(#) Makefile, Ver. 2.1 created 00:00:00 87/09/01 -X# Makefile for 8088 symbolic disassembler -X -X# Copyright (C) 1987 G. M. Harding, all rights reserved. -X# Permission to copy and redistribute is hereby granted, -X# provided full source code, with all copyright notices, -X# accompanies any redistribution. -X -X# This Makefile automates the process of compiling and linking -X# a symbolic object-file disassembler program for the Intel -X# 8088 CPU. Relatively machine-independent code is contained in -X# the file dismain.c; lookup tables and handler routines, which -X# are by their nature machine-specific, are contained in two -X# files named distabs.c and dishand.c, respectively. (A third -X# machine-specific file, disfp.c, contains handler routines for -X# floating-point coprocessor opcodes.) A header file, dis.h, -X# attempts to mediate between the machine-specific and machine- -X# independent portions of the code. An attempt has been made to -X# isolate machine dependencies and to deal with them in fairly -X# straightforward ways. Thus, it should be possible to target a -X# different CPU by rewriting the handler routines and changing -X# the initialization data in the lookup tables. It should not -X# be necessary to alter the formats of the tables. -X -OBJ = disrel.o dismain.o distabs.o dishand.o disfp.o -X -dis88 : $(OBJ) -X ld -i -s -o dis88 /lib/crt0.o $(OBJ) -lc -X size dis88 -X @echo "\07Build of 'dis88' complete." > /dev/tty -X -X.c.o : -X cc -O -c $< -X chmod 600 $*.o -X -disrel.o : disrel.c -X -dismain.o : dismain.c dis.h -X -distabs.o : distabs.c dis.h -X -dishand.o : dishand.c dis.h -X -disfp.o : disfp.c dis.h -X -END_OF_FILE -if test 1593 -ne `wc -c <'Makefile'`; then - echo shar: \"'Makefile'\" unpacked with wrong size! -fi -# end of 'Makefile' -fi -if test -f 'README' -a "${1}" != "-c" ; then - echo shar: Will not clobber existing file \"'README'\" -else -echo shar: Extracting \"'README'\" \(4898 characters\) -sed "s/^X//" >'README' <<'END_OF_FILE' -X dis88 -X Beta Release -X 87/09/01 -X --- -X G. M. HARDING -X POB 4142 -X Santa Clara CA 95054-0142 -X -X -X "Dis88" is a symbolic disassembler for the Intel 8088 CPU, -X designed to run under the PC/IX operating system on an IBM XT -X or fully-compatible clone. Its output is in the format of, and -X is completely compatible with, the PC/IX assembler, "as". The -X program is copyrighted by its author, but may be copied and re- -X distributed freely provided that complete source code, with all -X copyright notices, accompanies any distribution. This provision -X also applies to any modifications you may make. You are urged -X to comment such changes, giving, as a miminum, your name and -X complete address. -X -X This release of the program is a beta release, which means -X that it has been extensively, but not exhaustively, tested. -X User comments, recommendations, and bug fixes are welcome. The -X principal features of the current release are: -X -X (a) The ability to disassemble any file in PC/IX object -X format, making full use of symbol and relocation information if -X it is present, regardless of whether the file is executable or -X linkable, and regardless of whether it has continuous or split -X I/D space; -X -X (b) Automatic generation of synthetic labels when no sym- -X bol table is available; and -X -X (c) Optional output of address and object-code informa- -X tion as assembler comment text. -X -X Limitations of the current release are: -X -X (a) Numeric co-processor (i.e., 8087) mnemonics are not -X supported. Instructions for the co-processor are disassembled -X as CPU escape sequences, or as interrupts, depending on how -X they were assembled in the first place. This limitation will be -X addressed in a future release. -X -X (b) Symbolic references within the object file's data -X segment are not supported. Thus, for example, if a data segment -X location is initialized to point to a text segment address, no -X reference to a text segment symbol will be detected. This limi- -X tation is likely to remain in future releases, because object -X code does not, in most cases, contain sufficient information to -X allow meaningful interpretation of pure data. (Note, however, -X that symbolic references to the data segment from within the -X text segment are always supported.) -X -X As a final caveat, be aware that the PC/IX assembler does -X not recognize the "esc" mnemonic, even though it refers to a -X completely valid CPU operation which is documented in all the -X Intel literature. Thus, the corresponding opcodes (0xd8 through -X 0xdf) are disassembled as .byte directives. For reference, how- -X ever, the syntactically-correct "esc" instruction is output as -X a comment. -X -X To build the disassembler program, transfer all the source -X files, together with the Makefile, to a suitable (preferably -X empty) PC/IX directory. Then, simply type "make". -X -X To use dis88, place it in a directory which appears in -X your $PATH list. It may then be invoked by name from whatever -X directory you happen to be in. As a minimum, the program must -X be invoked with one command-line argument: the name of the ob- -X ject file to be disassembled. (Dis88 will complain if the file -X specified is not an object file.) Optionally, you may specify -X an output file; stdout is the default. One command-line switch -X is available: "-o", which makes the program display addresses -X and object code along with its mnemonic disassembly. -X -X The "-o" option is useful primarily for verifying the cor- -X rectness of the program's output. In particular, it may be used -X to check the accuracy of local relative jump opcodes. These -X jumps often target local labels, which are lost at assembly -X time; thus, the disassembly may contain cryptic instructions -X like "jnz .+39". As a user convenience, all relative jump and -X call opcodes are output with a comment which identifies the -X physical target address. -X -X By convention, the release level of the program as a whole -X is the SID of the file disrel.c, and this SID string appears in -X each disassembly. Release 2.1 of the program is the first beta -X release to be distributed on Usenet. -X -END_OF_FILE -if test 4898 -ne `wc -c <'README'`; then - echo shar: \"'README'\" unpacked with wrong size! -fi -# end of 'README' -fi -if test -f 'dis.h' -a "${1}" != "-c" ; then - echo shar: Will not clobber existing file \"'dis.h'\" -else -echo shar: Extracting \"'dis.h'\" \(7563 characters\) -sed "s/^X//" >'dis.h' <<'END_OF_FILE' -X /* -X ** @(#) dis.h, Ver. 2.1 created 00:00:00 87/09/01 -X */ -X -X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -X * * -X * Copyright (C) 1987 G. M. Harding, all rights reserved * -X * * -X * Permission to copy and redistribute is hereby granted, * -X * provided full source code, with all copyright notices, * -X * accompanies any redistribution. * -X * * -X * This file contains declarations and definitions used by * -X * the 8088 disassembler program. The program was designed * -X * for execution on a machine of its own type (i.e., it is * -X * not designed as a cross-disassembler); consequently, A * -X * SIXTEEN-BIT INTEGER SIZE HAS BEEN ASSUMED. This assump- * -X * tion is not particularly important, however, except in * -X * the machine-specific portions of the code (i.e., the * -X * handler routines and the optab[] array). It should be * -X * possible to override this assumption, for execution on * -X * 32-bit machines, by use of a pre-processor directive * -X * (see below); however, this has not been tested. * -X * * -X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -X -X#include /* System standard I/O definitions */ -X#include /* System file-control definitions */ -X#include /* Object file format definitions */ -X -X#if i8086 || i8088 /* For CPU's with 16-bit integers */ -X#undef int -X#else /* Defaults (for 32-bit CPU types) */ -X#define int short -X#endif -X -X#define MAXSYM 1500 /* Maximum entries in symbol table */ -X -extern struct nlist /* Array to hold the symbol table */ -X symtab[MAXSYM]; -X -extern struct reloc /* Array to hold relocation table */ -X relo[MAXSYM]; -X -extern int symptr; /* Index into the symtab[] array */ -X -extern int relptr; /* Index into the relo[] array */ -X -struct opcode /* Format for opcode data records */ -X { -X char *text; /* Pointer to mnemonic text */ -X void (*func)(); /* Pointer to handler routine */ -X unsigned min; /* Minimum # of object bytes */ -X unsigned max; /* Maximum # of object bytes */ -X }; -X -extern struct opcode /* Array to hold the opcode table */ -X optab[256]; -X -X /* -X +--------------------------------------------- -X | The following functions are the specialized -X | handlers for each opcode group. They are, of -X | course, highly MACHINE-SPECIFIC. Each entry -X | in the opcode[] array contains a pointer to -X | one of these handlers. The handlers in the -X | first group are in dishand.c; those in the -X | second group are in disfp.c. -X +--------------------------------------------- -X */ -X -extern void dfhand(), /* Default handler routine */ -X sbhand(), /* Single-byte handler */ -X aohand(), /* Arithmetic-op handler */ -X sjhand(), /* Short-jump handler */ -X imhand(), /* Immediate-operand handler */ -X mvhand(), /* Simple move handler */ -X mshand(), /* Segreg-move handler */ -X pohand(), /* Pop memory/reg handler */ -X cihand(), /* Intersegment call handler */ -X mihand(), /* Immediate-move handler */ -X mqhand(), /* Quick-move handler */ -X tqhand(), /* Quick-test handler */ -X rehand(), /* Return handler */ -X mmhand(), /* Move-to-memory handler */ -X srhand(), /* Shift and rotate handler */ -X aahand(), /* ASCII-adjust handler */ -X iohand(), /* Immediate port I/O handler */ -X ljhand(), /* Long-jump handler */ -X mahand(), /* Misc. arithmetic handler */ -X mjhand(); /* Miscellaneous jump handler */ -X -extern void eshand(), /* Bus-escape opcode handler */ -X fphand(), /* Floating-point handler */ -X inhand(); /* Interrupt-opcode handler */ -X -extern char *REGS[]; /* Table of register names */ -X -extern char *REGS0[]; /* Mode 0 register name table */ -X -extern char *REGS1[]; /* Mode 1 register name table */ -X -X#define AL REGS[0] /* CPU register manifests */ -X#define CL REGS[1] -X#define DL REGS[2] -X#define BL REGS[3] -X#define AH REGS[4] -X#define CH REGS[5] -X#define DH REGS[6] -X#define BH REGS[7] -X#define AX REGS[8] -X#define CX REGS[9] -X#define DX REGS[10] -X#define BX REGS[11] -X#define SP REGS[12] -X#define BP REGS[13] -X#define SI REGS[14] -X#define DI REGS[15] -X#define ES REGS[16] -X#define CS REGS[17] -X#define SS REGS[18] -X#define DS REGS[19] -X#define BX_SI REGS0[0] -X#define BX_DI REGS0[1] -X#define BP_SI REGS0[2] -X#define BP_DI REGS0[3] -X -extern int symrank[6][6]; /* Symbol type/rank matrix */ -X -extern unsigned long PC; /* Current program counter */ -X -extern int segflg; /* Flag: segment override in effect */ -X -extern int objflg; /* Flag: output object as a comment */ -X -X#define OBJMAX 8 /* Size of the object code buffer */ -X -extern unsigned char /* Internal buffer for object code */ -X objbuf[OBJMAX]; -X -extern void objini(), /* Object-buffer init routine */ -X objout(); /* Object-code output routine */ -X -extern int objptr; /* Index into the objbuf[] array */ -X -extern void badseq(); /* Bad-code-sequence function */ -X -extern char *getnam(); /* Symbol-name string function */ -X -extern char *lookup(); /* Symbol-table lookup function */ -X -extern int lookext(); /* Extern-definition lookup routine */ -X -extern char *mtrans(); /* Interpreter for the mode byte */ -X -extern void mtrunc(); /* Mode string truncator function */ -X -extern char ADD[], /* Opcode family mnemonic strings */ -X OR[], -X ADC[], -X SBB[], -X AND[], -X SUB[], -X XOR[], -X CMP[], -X NOT[], -X NEG[], -X MUL[], -X DIV[], -X MOV[], -X ESC[], -X TEST[], -X AMBIG[]; -X -extern char *OPFAM[]; /* Indexed mnemonic family table */ -X -extern struct exec HDR; /* Holds the object file's header */ -X -X#define LOOK_ABS 0 /* Arguments to lookup() function */ -X#define LOOK_REL 1 -X#define LOOK_LNG 2 -X -X#define TR_STD 0 /* Arguments to mtrans() function */ -X#define TR_SEG 8 -X -X /* Macro for byte input primitive */ -X#define FETCH(p) \ -X ++PC; p = getchar() & 0xff; objbuf[objptr++] = p -X -extern int close(); /* System file-close primitive */ -extern int fprintf(); /* Library file-output function */ -extern long lseek(); /* System file-position primitive */ -extern int open(); /* System file-open primitive */ -extern int printf(); /* Library output-format function */ -extern int read(); /* System file-read primitive */ -extern int sprintf(); /* Library string-output function */ -extern char *strcat(); /* Library string-join function */ -extern char *strcpy(); /* Library string-copy function */ -extern int strlen(); /* Library string-length function */ -X -X /* * * * * * * * * * * END OF dis.h * * * * * * * * * * */ -X -X -END_OF_FILE -if test 7563 -ne `wc -c <'dis.h'`; then - echo shar: \"'dis.h'\" unpacked with wrong size! -fi -# end of 'dis.h' -fi -if test -f 'dis88.1' -a "${1}" != "-c" ; then - echo shar: Will not clobber existing file \"'dis88.1'\" -else -echo shar: Extracting \"'dis88.1'\" \(6174 characters\) -sed "s/^X//" >'dis88.1' <<'END_OF_FILE' -X.TH dis88 1 LOCAL -X.SH "NAME" -dis88 \- 8088 symbolic disassembler -X.SH "SYNOPSIS" -X\fBdis88\fP [ -o ] ifile [ ofile ] -X.SH "DESCRIPTION" -Dis88 reads ifile, which must be in PC/IX a.out format. -It interprets the binary opcodes and data locations, and -writes corresponding assembler source code to stdout, or -to ofile if specified. The program's output is in the -format of, and fully compatible with, the PC/IX assembler, -as(1). If a symbol table is present in ifile, labels and -references will be symbolic in the output. If the input -file lacks a symbol table, the fact will be noted, and the -disassembly will proceed, with the disassembler generating -synthetic labels as needed. If the input file has split -I/D space, or if it is executable, the disassembler will -make all necessary adjustments in address-reference calculations. -X.PP -If the "-o" option appears, object code will be included -in comments during disassembly of the text segment. This -feature is used primarily for debugging the disassembler -itself, but may provide information of passing interest -to users. -X.PP -The program always outputs the current machine address -before disassembling an opcode. If a symbol table is -present, this address is output as an assembler comment; -otherwise, it is incorporated into the synthetic label -which is generated internally. Since relative jumps, -especially short ones, may target unlabelled locations, -the program always outputs the physical target address -as a comment, to assist the user in following the code. -X.PP -The text segment of an object file is always padded to -an even machine address. In addition, if the file has -split I/D space, the text segment will be padded to a -paragraph boundary (i.e., an address divisible by 16). -As a result of this padding, the disassembler may produce -a few spurious, but harmless, instructions at the -end of the text segment. -X.PP -Disassembly of the data segment is a difficult matter. -The information to which initialized data refers cannot -be inferred from context, except in the special case -of an external data or address reference, which will be -reflected in the relocation table. Internal data and -address references will already be resolved in the object file, -and cannot be recreated. Therefore, the data -segment is disassembled as a byte stream, with long -stretches of null data represented by an appropriate -X".zerow" pseudo-op. This limitation notwithstanding, -labels (as opposed to symbolic references) are always -output at appropriate points within the data segment. -X.PP -If disassembly of the data segment is difficult, disassembly of the -bss segment is quite easy, because uninitialized data is all -zero by definition. No data -is output in the bss segment, but symbolic labels are -output as appropriate. -X.PP -XFor each opcode which takes an operand, a particular -symbol type (text, data, or bss) is appropriate. This -tidy correspondence is complicated somewhat, however, -by the existence of assembler symbolic constants and -segment override opcodes. Therefore, the disassembler's -symbol lookup routine attempts to apply a certain amount -of intelligence when it is asked to find a symbol. If -it cannot match on a symbol of the preferred type, it -may return a symbol of some other type, depending on -preassigned (and somewhat arbitrary) rankings within -each type. Finally, if all else fails, it returns a -string containing the address sought as a hex constant; -this behavior allows calling routines to use the output -of the lookup function regardless of the success of its -search. -X.PP -It is worth noting, at this point, that the symbol lookup -routine operates linearly, and has not been optimized in -any way. Execution time is thus likely to increase -geometrically with input file size. The disassembler is -internally limited to 1500 symbol table entries and 1500 -relocation table entries; while these limits are generous -X(/unix, itself, has fewer than 800 symbols), they are not -guaranteed to be adequate in all cases. If the symbol -table or the relocation table overflows, the disassembly -aborts. -X.PP -XFinally, users should be aware of a bug in the assembler, -which causes it not to parse the "esc" mnemonic, even -though "esc" is a completely legitimate opcode which is -documented in all the Intel literature. To accommodate -this deficiency, the disassembler translates opcodes of -the "esc" family to .byte directives, but notes the -correct mnemonic in a comment for reference. -X.PP -In all cases, it should be possible to submit the output -of the disassembler program to the assembler, and assemble -it without error. In most cases, the resulting object -code will be identical to the original; in any event, it -will be functionally equivalent. -X.SH "SEE ALSO" -adb(1), as(1), cc(1), ld(1). -X.br -X"Assembler Reference Manual" in the PC/IX Programmer's -Guide. -X.SH "DIAGNOSTICS" -X"can't access input file" if the input file cannot be -found, opened, or read. -X.sp -X"can't open output file" if the output file cannot be -created. -X.sp -X"warning: host/cpu clash" if the program is run on a -machine with a different CPU. -X.sp -X"input file not in object format" if the magic number -does not correspond to that of a PC/IX object file. -X.sp -X"not an 8086/8088 object file" if the CPU ID of the -file header is incorrect. -X.sp -X"reloc table overflow" if there are more than 1500 -entries in the relocation table. -X.sp -X"symbol table overflow" if there are more than 1500 -entries in the symbol table. -X.sp -X"lseek error" if the input file is corrupted (should -never happen). -X.sp -X"warning: no symbols" if the symbol table is missing. -X.sp -X"can't reopen input file" if the input file is removed -or altered during program execution (should never happen). -X.SH "BUGS" -Numeric co-processor (i.e., 8087) mnemonics are not currently supported. -Instructions for the co-processor are -disassembled as CPU escape sequences, or as interrupts, -depending on how they were assembled in the first place. -X.sp -Despite the program's best efforts, a symbol retrieved -from the symbol table may sometimes be different from -the symbol used in the original assembly. -X.sp -The disassembler's internal tables are of fixed size, -and the program aborts if they overflow. -END_OF_FILE -if test 6174 -ne `wc -c <'dis88.1'`; then - echo shar: \"'dis88.1'\" unpacked with wrong size! -fi -# end of 'dis88.1' -fi -if test -f 'disfp.c' -a "${1}" != "-c" ; then - echo shar: Will not clobber existing file \"'disfp.c'\" -else -echo shar: Extracting \"'disfp.c'\" \(5589 characters\) -sed "s/^X//" >'disfp.c' <<'END_OF_FILE' -static char *sccsid = -X "@(#) disfp.c, Ver. 2.1 created 00:00:00 87/09/01"; -X -X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -X * * -X * Copyright (C) 1987 G. M. Harding, all rights reserved * -X * * -X * Permission to copy and redistribute is hereby granted, * -X * provided full source code, with all copyright notices, * -X * accompanies any redistribution. * -X * * -X * This file contains handler routines for the numeric op- * -X * codes of the 8087 co-processor, as well as a few other * -X * opcodes which are related to 8087 emulation. * -X * * -X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -X -X#include "dis.h" /* Disassembler declarations */ -X -X#define FPINT0 0xd8 /* Floating-point interrupts */ -X#define FPINT1 0xd9 -X#define FPINT2 0xda -X#define FPINT3 0xdb -X#define FPINT4 0xdc -X#define FPINT5 0xdd -X#define FPINT6 0xde -X#define FPINT7 0xdf -X -X /* Test for floating opcodes */ -X#define ISFLOP(x) \ -X (((x) >= FPINT0) && ((x) <= FPINT7)) -X -X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -X * * -X * This is the handler for the escape family of opcodes. * -X * These opcodes place the contents of a specified memory * -X * location on the system bus, for access by a peripheral * -X * or by a co-processor such as the 8087. (The 8087 NDP is * -X * accessed only via bus escapes.) Due to a bug in the * -X * PC/IX assembler, the "esc" mnemonic is not recognized; * -X * consequently, escape opcodes are disassembled as .byte * -X * directives, with the appropriate mnemonic and operand * -X * included as a comment. FOR NOW, those escape sequences * -X * corresponding to 8087 opcodes are treated as simple * -X * escapes. * -X * * -X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -X -void -eshand(j) -X -X register int j; /* Pointer to optab[] entry */ -X -X{/* * * * * * * * * * START OF eshand() * * * * * * * * * */ -X -X register char *a; -X register int k; -X -X objini(j); -X -X FETCH(k); -X -X a = mtrans((j & 0xfd),(k & 0xc7),TR_STD); -X -X mtrunc(a); -X -X printf("\t.byte\t0x%02.2x\t\t| esc\t%s\n",j,a); -X -X for (k = 1; k < objptr; ++k) -X printf("\t.byte\t0x%02.2x\n",objbuf[k]); -X -X}/* * * * * * * * * * * END OF eshand() * * * * * * * * * * */ -X -X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -X * * -X * This is the handler routine for floating-point opcodes. * -X * Since PC/IX must accommodate systems with and without * -X * 8087 co-processors, it allows floating-point operations * -X * to be initiated in either of two ways: by a software * -X * interrput whose type is in the range 0xd8 through 0xdf, * -X * or by a CPU escape sequence, which is invoked by an op- * -X * code in the same range. In either case, the subsequent * -X * byte determines the actual numeric operation to be per- * -X * formed. However, depending on the method of access, * -X * either one or two code bytes will precede that byte, * -X * and the fphand() routine has no way of knowing whether * -X * it was invoked by interrupt or by an escape sequence. * -X * Therefore, unlike all of the other handler routines ex- * -X * cept dfhand(), fphand() does not initialize the object * -X * buffer, leaving that chore to the caller. * -X * * -X * FOR NOW, fphand() does not disassemble floating-point * -X * opcodes to floating mnemonics, but simply outputs the * -X * object code as .byte directives. * -X * * -X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -X -void -fphand(j) -X -X register int j; /* Pointer to optab[] entry */ -X -X{/* * * * * * * * * * START OF fphand() * * * * * * * * * */ -X -X register int k; -X -X segflg = 0; -X -X FETCH(k); -X -X printf("\t.byte\t0x%02.2x\t\t| 8087 code sequence\n", -X objbuf[0]); -X -X for (k = 1; k < objptr; ++k) -X printf("\t.byte\t0x%02.2x\n",objbuf[k]); -X -X/* objout(); FOR NOW */ -X -X}/* * * * * * * * * * * END OF fphand() * * * * * * * * * * */ -X -X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -X * * -X * This is the handler for variable software interrupt * -X * opcodes. It is included in this file because PC/IX im- * -X * plements its software floating-point emulation by means * -X * of interrupts. Any interrupt in the range 0xd8 through * -X * 0xdf is an NDP-emulation interrupt, and is specially * -X * handled by the assembler. * -X * * -X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -X -void -inhand(j) -X -X register int j; /* Pointer to optab[] entry */ -X -X{/* * * * * * * * * * START OF inhand() * * * * * * * * * */ -X -X register int k; -X -X objini(j); -X -X FETCH(k); -X -X if (ISFLOP(k)) -X { -X fphand(k); -X return; -X } -X -X printf("%s\t%d\n",optab[j].text,k); -X -X objout(); -X -X}/* * * * * * * * * * * END OF inhand() * * * * * * * * * * */ -X -X -END_OF_FILE -if test 5589 -ne `wc -c <'disfp.c'`; then - echo shar: \"'disfp.c'\" unpacked with wrong size! -fi -# end of 'disfp.c' -fi -if test -f 'dismain.c' -a "${1}" != "-c" ; then - echo shar: Will not clobber existing file \"'dismain.c'\" -else -echo shar: Extracting \"'dismain.c'\" \(17384 characters\) -sed "s/^X//" >'dismain.c' <<'END_OF_FILE' -static char *sccsid = -X "@(#) dismain.c, Ver. 2.1 created 00:00:00 87/09/01"; -X -X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -X * * -X * Copyright (C) 1987 G. M. Harding, all rights reserved * -X * * -X * Permission to copy and redistribute is hereby granted, * -X * provided full source code, with all copyright notices, * -X * accompanies any redistribution. * -X * * -X * This file contains the source code for the machine- * -X * independent portions of a disassembler program to run * -X * in a Unix (System III) environment. It expects, as its * -X * input, a file in standard a.out format, optionally con- * -X * taining symbol table information. If a symbol table is * -X * present, it will be used in the disassembly; otherwise, * -X * all address references will be literal (absolute). * -X * * -X * The disassembler program was originally written for an * -X * Intel 8088 CPU. However, all details of the actual CPU * -X * architecture are hidden in three machine-specific files * -X * named distabs.c, dishand.c, and disfp.c (the latter * -X * file is specific to the 8087 numeric co-processor). The * -X * code in this file is generic, and should require mini- * -X * mal revision if a different CPU is to be targeted. If a * -X * different version of Unix is to be targeted, changes to * -X * this file may be necessary, and if a completely differ- * -X * ent OS is to be targeted, all bets are off. * -X * * -X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -X -X#include "dis.h" /* Disassembler declarations */ -X -extern char *release; /* Contains release string */ -X -static char *IFILE = NULL; /* Points to input file name */ -X -static char *OFILE = NULL; /* Points to output file name */ -X -static char *PRG; /* Name of invoking program */ -X -static unsigned long zcount; /* Consecutive "0" byte count */ -X -int objflg = 0; /* Flag: output object bytes */ -X -X#if unix && i8086 && ibmpc /* Set the CPU identifier */ -static int cpuid = 1; -X#else -static int cpuid = 0; -X#endif -X -X /* * * * * * * MISCELLANEOUS UTILITY FUNCTIONS * * * * * * */ -X -static void -usage(s) -X register char *s; -X{ -X fprintf(stderr,"\07usage: %s [-o] ifile [ofile]\n",s); -X exit(-1); -X} -X -static void -fatal(s,t) -X register char *s, *t; -X{ -X fprintf(stderr,"\07%s: %s\n",s,t); -X exit(-1); -X} -X -static void -zdump(beg) -X unsigned long beg; -X{ -X beg = PC - beg; -X if (beg > 1L) -X printf("\t.zerow\t%ld\n",(beg >> 1)); -X if (beg & 1L) -X printf("\t.byte\t0\n"); -X} -X -static char * -invoker(s) -X register char *s; -X{ -X extern int strlen(); -X register int k; -X -X k = strlen(s); -X -X while (k--) -X if (s[k] == '/') -X { -X s += k; -X ++s; -X break; -X } -X -X return (s); -X} -X -X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -X * * -X * This rather tricky routine supports the disdata() func- * -X * tion. Its job is to output the code for a sequence of * -X * data bytes whenever the object buffer is full, or when * -X * a symbolic label is to be output. However, it must also * -X * keep track of consecutive zero words so that lengthy * -X * stretches of null data can be compressed by the use of * -X * an appropriate assembler pseudo-op. It does this by * -X * setting and testing a file-wide flag which counts suc- * -X * cessive full buffers of null data. The function returns * -X * a logical TRUE value if it outputs anything, logical * -X * FALSE otherwise. (This enables disdata() to determine * -X * whether to output a new synthetic label when there is * -X * no symbol table.) * -X * * -X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -X -static int -objdump(c) -X -X register char *c; -X -X{/* * * * * * * * * * START OF objdump() * * * * * * * * * */ -X -X register int k; -X int retval = 0; -X -X if (objptr == OBJMAX) -X { -X for (k = 0; k < OBJMAX; ++k) -X if (objbuf[k]) -X break; -X if (k == OBJMAX) -X { -X zcount += k; -X objptr = 0; -X if (c == NULL) -X return (retval); -X } -X } -X -X if (zcount) -X { -X printf("\t.zerow\t%ld\n",(zcount >> 1)); -X ++retval; -X zcount = 0L; -X } -X -X if (objptr) -X { -X printf("\t.byte\t"); -X ++retval; -X } -X else -X return (retval); -X -X for (k = 0; k < objptr; ++k) -X { -X printf("0x%02.2x",objbuf[k]); -X if (k < (objptr - 1)) -X putchar(','); -X else -X putchar('\n'); -X } -X -X objptr = 0; -X -X return (retval); -X -X}/* * * * * * * * * * END OF objdump() * * * * * * * * * */ -X -X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -X * * -X * This routine, called at the beginning of the input * -X * cycle for each object byte, and before any interpreta- * -X * tion is attempted, searches the symbol table for any * -X * symbolic name with a value corresponding to the cur- * -X * rent PC and a type corresponding to the segment type * -X * (i.e., text, data, or bss) specified by the function's * -X * argument. If any such name is found, a pointer to it is * -X * returned; otherwise, a NULL pointer is returned. * -X * * -X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -X -static char * -getlab(type) -X -X register int type; -X -X{/* * * * * * * * * * START OF getlab() * * * * * * * * * */ -X -X register int k; -X static char b[32], c[10]; -X -X if (symptr < 0) -X if ((type == N_TEXT) -X || ((type == N_DATA) && ( ! objptr ) && ( ! zcount ))) -X { -X if (type == N_TEXT) -X sprintf(b,"T%05.5lx:",PC); -X else -X sprintf(b,"D%05.5lx:",PC); -X return (b); -X } -X else -X return (NULL); -X -X for (k = 0; k <= symptr; ++k) -X if ((symtab[k].n_value == PC) -X && ((symtab[k].n_sclass & N_SECT) == type)) -X { -X sprintf(b,"%s:\n",getnam(k)); -X if (objflg && (type != N_TEXT)) -X sprintf(c,"| %05.5lx\n",PC); -X strcat(b,c); -X return (b); -X } -X -X return (NULL); -X -X}/* * * * * * * * * * * END OF getlab() * * * * * * * * * * */ -X -X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -X * * -X * This routine performs a preliminary scan of the symbol * -X * table, before disassembly begins, and outputs declara- * -X * tions of globals and constants. * -X * * -X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -X -static void -prolog() -X -X{/* * * * * * * * * * START OF prolog() * * * * * * * * * */ -X -X register int j, flag; -X -X if (symptr < 0) -X return; -X -X for (j = flag = 0; j <= symptr; ++j) -X if ((symtab[j].n_sclass & N_CLASS) == C_EXT) -X if (((symtab[j].n_sclass & N_SECT) > N_UNDF) -X && ((symtab[j].n_sclass & N_SECT) < N_COMM)) -X { -X char *c = getnam(j); -X printf("\t.globl\t%s",c); -X if (++flag == 1) -X { -X putchar('\t'); -X if (strlen(c) < 8) -X putchar('\t'); -X printf("| Internal global\n"); -X } -X else -X putchar('\n'); -X } -X else -X if (symtab[j].n_value) -X { -X char *c = getnam(j); -X printf("\t.comm\t%s,0x%08.8lx",c, -X symtab[j].n_value); -X if (++flag == 1) -X printf("\t| Internal global\n"); -X else -X putchar('\n'); -X } -X -X if (flag) -X putchar('\n'); -X -X for (j = flag = 0; j <= relptr; ++j) -X if (relo[j].r_symndx < S_BSS) -X { -X char *c = getnam(relo[j].r_symndx); -X ++flag; -X printf("\t.globl\t%s",c); -X putchar('\t'); -X if (strlen(c) < 8) -X putchar('\t'); -X printf("| Undef: %05.5lx\n",relo[j].r_vaddr); -X } -X -X if (flag) -X putchar('\n'); -X -X for (j = flag = 0; j <= symptr; ++j) -X if ((symtab[j].n_sclass & N_SECT) == N_ABS) -X { -X char *c = getnam(j); -X printf("%s=0x%08.8lx",c,symtab[j].n_value); -X if (++flag == 1) -X { -X printf("\t\t"); -X if (strlen(c) < 5) -X putchar('\t'); -X printf("| Literal\n"); -X } -X else -X putchar('\n'); -X } -X -X if (flag) -X putchar('\n'); -X -X}/* * * * * * * * * * * END OF prolog() * * * * * * * * * * */ -X -X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -X * * -X * This function is responsible for disassembly of the * -X * object file's text segment. * -X * * -X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -X -static void -distext() -X -X{/* * * * * * * * * * START OF distext() * * * * * * * * * */ -X -X char *c; -X register int j; -X register void (*f)(); -X -X for (j = 0; j < (int)(HDR.a_hdrlen); ++j) -X getchar(); -X -X printf("| %s, %s\n\n",PRG,release); -X -X printf("| @("); -X -X printf("#)\tDisassembly of %s",IFILE); -X -X if (symptr < 0) -X printf(" (no symbols)\n\n"); -X else -X printf("\n\n"); -X -X if (HDR.a_flags & A_EXEC) -X printf("| File is executable\n\n"); -X -X if (HDR.a_flags & A_SEP) -X { -X printf("| File has split I/D space, and may have\n"); -X printf("| extraneous instructions in text segment\n\n"); -X } -X -X prolog(); -X -X printf("\t.text\t\t\t| loc = %05.5lx, size = %05.5lx\n\n", -X PC,HDR.a_text); -X -X segflg = 0; -X -X for (PC = 0L; PC < HDR.a_text; ++PC) -X { -X j = getchar() & 0xff; -X if ((j == 0) && ((PC + 1L) == HDR.a_text)) -X { -X ++PC; -X break; -X } -X if ((c = getlab(N_TEXT)) != NULL) -X printf("%s",c); -X f = optab[j].func; -X (*f)(j); -X } -X -X}/* * * * * * * * * * END OF distext() * * * * * * * * * */ -X -X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -X * * -X * This function handles the object file's data segment. * -X * There is no good way to disassemble a data segment, be- * -X * cause it is impossible to tell, from the object code * -X * alone, what each data byte refers to. If it refers to * -X * an external symbol, the reference can be resolved from * -X * the relocation table, if there is one. However, if it * -X * refers to a static symbol, it cannot be distinguished * -X * from numeric, character, or other pointer data. In some * -X * cases, one might make a semi-educated guess as to the * -X * nature of the data, but such guesses are inherently * -X * haphazard, and they are bound to be wrong a good por- * -X * tion of the time. Consequently, the data segment is * -X * disassembled as a byte stream, which will satisfy no * -X * one but which, at least, will never mislead anyone. * -X * * -X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -X -static void -disdata() -X -X{/* * * * * * * * * * START OF disdata() * * * * * * * * * */ -X -X register char *c; -X register int j; -X unsigned long end; -X -X putchar('\n'); -X -X if (HDR.a_flags & A_SEP) -X { -X PC = 0L; -X end = HDR.a_data; -X } -X else -X end = HDR.a_text + HDR.a_data; -X -X printf("\t.data\t\t\t| loc = %05.5lx, size = %05.5lx\n\n", -X PC,HDR.a_data); -X -X segflg = 0; -X -X for (objptr = 0, zcount = 0L; PC < end; ++PC) -X { -X if ((c = getlab(N_DATA)) != NULL) -X { -X objdump(c); -X printf("%s",c); -X } -X if (objptr >= OBJMAX) -X if (objdump(NULL) && (symptr < 0)) -X printf("D%05.5lx:",PC); -X j = getchar() & 0xff; -X objbuf[objptr++] = j; -X } -X -X objdump(""); -X -X}/* * * * * * * * * * END OF disdata() * * * * * * * * * */ -X -X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -X * * -X * This function handles the object file's bss segment. * -X * Disassembly of the bss segment is easy, because every- * -X * thing in it is zero by definition. * -X * * -X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -X -static void -disbss() -X -X{/* * * * * * * * * * START OF disbss() * * * * * * * * * */ -X -X register int j; -X register char *c; -X unsigned long beg, end; -X -X putchar('\n'); -X -X if (HDR.a_flags & A_SEP) -X end = HDR.a_data + HDR.a_bss; -X else -X end = HDR.a_text + HDR.a_data + HDR.a_bss; -X -X printf("\t.bss\t\t\t| loc = %05.5lx, size = %05.5lx\n\n", -X PC,HDR.a_bss); -X -X segflg = 0; -X -X for (beg = PC; PC < end; ++PC) -X if ((c = getlab(N_BSS)) != NULL) -X { -X if (PC > beg) -X { -X zdump(beg); -X beg = PC; -X } -X printf("%s",c); -X } -X -X if (PC > beg) -X zdump(beg); -X -X}/* * * * * * * * * * * END OF disbss() * * * * * * * * * * */ -X -X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -X * * -X * This is the program entry point. The command line is * -X * searched for an input file name, which must be present. * -X * An optional output file name is also permitted; if none * -X * is found, standard output is the default. One command- * -X * line option is available: "-o", which causes the pro- * -X * gram to include object code in comments along with its * -X * mnemonic output. * -X * * -X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -X -void -main(argc,argv) -X -X int argc; /* Command-line args from OS */ -X register char **argv; -X -X{/* * * * * * * * * * * START OF main() * * * * * * * * * * */ -X -X char a[1024]; -X register int fd; -X long taboff, tabnum; -X long reloff, relnum; -X -X PRG = invoker(*argv); -X -X while (*++argv != NULL) /* Process command-line args */ -X if (**argv == '-') -X switch (*++*argv) -X { -X case 'o' : -X if (*++*argv) -X usage(PRG); -X else -X ++objflg; -X break; -X default : -X usage(PRG); -X } -X else -X if (IFILE == NULL) -X IFILE = *argv; -X else if (OFILE == NULL) -X OFILE = *argv; -X else -X usage(PRG); -X -X if (IFILE == NULL) -X usage(PRG); -X else -X if ((fd = open(IFILE,O_RDONLY)) < 0) -X { -X sprintf(a,"can't access input file %s",IFILE); -X fatal(PRG,a); -X } -X -X if (OFILE != NULL) -X if (freopen(OFILE,"w",stdout) == NULL) -X { -X sprintf(a,"can't open output file %s",OFILE); -X fatal(PRG,a); -X } -X -X if ( ! cpuid ) -X fprintf(stderr,"\07%s: warning: host/cpu clash\n",PRG); -X -X read(fd,&HDR,sizeof(struct exec)); -X -X if (BADMAG(HDR)) -X { -X sprintf(a,"input file %s not in object format",IFILE); -X fatal(PRG,a); -X } -X -X if (HDR.a_cpu != A_I8086) -X { -X sprintf(a,"%s is not an 8086/8088 object file",IFILE); -X fatal(PRG,a); -X } -X -X if (HDR.a_hdrlen <= A_MINHDR) -X HDR.a_trsize = HDR.a_drsize = -X HDR.a_tbase = HDR.a_dbase = -X HDR.a_lnums = HDR.a_toffs = 0L; -X -X reloff = HDR.a_text /* Compute reloc data offset */ -X + HDR.a_data -X + (long)(HDR.a_hdrlen); -X -X relnum = -X (HDR.a_trsize + HDR.a_drsize) / sizeof(struct reloc); -X -X taboff = reloff /* Compute name table offset */ -X + HDR.a_trsize -X + HDR.a_drsize; -X -X tabnum = HDR.a_syms / sizeof(struct nlist); -X -X if (relnum > MAXSYM) -X fatal(PRG,"reloc table overflow"); -X -X if (tabnum > MAXSYM) -X fatal(PRG,"symbol table overflow"); -X -X if (relnum) /* Get reloc data */ -X if (lseek(fd,reloff,0) != reloff) -X fatal(PRG,"lseek error"); -X else -X { -X for (relptr = 0; relptr < relnum; ++relptr) -X read(fd,&relo[relptr],sizeof(struct reloc)); -X relptr--; -X } -X -X if (tabnum) /* Read in symtab */ -X if (lseek(fd,taboff,0) != taboff) -X fatal(PRG,"lseek error"); -X else -X { -X for (symptr = 0; symptr < tabnum; ++symptr) -X read(fd,&symtab[symptr],sizeof(struct nlist)); -X symptr--; -X } -X else -X fprintf(stderr,"\07%s: warning: no symbols\n",PRG); -X -X close(fd); -X -X if (freopen(IFILE,"r",stdin) == NULL) -X { -X sprintf(a,"can't reopen input file %s",IFILE); -X fatal(PRG,a); -X } -X -X distext(); -X -X disdata(); -X -X disbss(); -X -X exit(0); -X -X}/* * * * * * * * * * * END OF main() * * * * * * * * * * */ -X -X -END_OF_FILE -if test 17384 -ne `wc -c <'dismain.c'`; then - echo shar: \"'dismain.c'\" unpacked with wrong size! -fi -# end of 'dismain.c' -fi -if test -f 'disrel.c' -a "${1}" != "-c" ; then - echo shar: Will not clobber existing file \"'disrel.c'\" -else -echo shar: Extracting \"'disrel.c'\" \(742 characters\) -sed "s/^X//" >'disrel.c' <<'END_OF_FILE' -static char *copyright = -X "@(#) Copyright (C) 1987 G. M. Harding, all rights reserved"; -X -static char *sccsid = -X "@(#) disrel.c, Ver. 2.1 created 00:00:00 87/09/01"; -X -char *release = -X "release 2.1 (PC/IX)"; -X -X /* -X ** -X ** This file documents the major revisions to the 8088 sym- -X ** bolic disassembler. It also contains the release string -X ** which is output at the head of each disassembly, and the -X ** copyright string which must be incorporated in any code -X ** distribution. -X ** -X ** Permission to copy and redistribute is hereby granted, -X ** provided full source code, with all copyright notices, -X ** accompanies any redistribution. -X ** -X ** REVISION HISTORY: -X ** -X ** SEP 87: -X ** After internal shakeout, released on Usenet. -X ** -X */ -X -END_OF_FILE -if test 742 -ne `wc -c <'disrel.c'`; then - echo shar: \"'disrel.c'\" unpacked with wrong size! -fi -# end of 'disrel.c' -fi -echo shar: End of archive 1 \(of 2\). -cp /dev/null ark1isdone -MISSING="" -for I in 1 2 ; do - if test ! -f ark${I}isdone ; then - MISSING="${MISSING} ${I}" - fi -done -if test "${MISSING}" = "" ; then - echo You have unpacked both archives. - rm -f ark[1-9]isdone -else - echo You still need to unpack the following archives: - echo " " ${MISSING} -fi -## End of shell archive. -exit 0 diff --git a/part02 b/part02 deleted file mode 100644 index 34ca663..0000000 --- a/part02 +++ /dev/null @@ -1,1812 +0,0 @@ -Subject: v15i007: Symbolic disassembler for PC/IX, Part02/02 -Newsgroups: comp.sources.unix -Approved: rsalz@uunet.UU.NET - -Submitted-by: "G. M. Harding" -Posting-number: Volume 15, Issue 7 -Archive-name: dis88/part02 - -#! /bin/sh -# This is a shell archive. Remove anything before this line, then unpack -# it by saving it into a file and typing "sh file". To overwrite existing -# files, type "sh file -c". You can also feed this as standard input via -# unshar, or by typing "sh 'dishand.c' <<'END_OF_FILE' -static char *sccsid = -X "@(#) dishand.c, Ver. 2.1 created 00:00:00 87/09/01"; -X -X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -X * * -X * Copyright (C) 1987 G. M. Harding, all rights reserved * -X * * -X * Permission to copy and redistribute is hereby granted, * -X * provided full source code, with all copyright notices, * -X * accompanies any redistribution. * -X * * -X * This file contains the source code for most of the spe- * -X * cialized handler routines of the disassembler program. * -X * (The file disfp.c contains handler routines specific to * -X * the 8087 numeric co-processor.) Each handler routine * -X * interprets the opcode byte (and subsequent data bytes, * -X * if any) of a particular family of opcodes, and is re- * -X * sponsible for generating appropriate output. All of the * -X * code in this file is highly MACHINE-SPECIFIC, and would * -X * have to be rewritten for a different CPU. The handler * -X * routines are accessed only via pointers in the optab[] * -X * array, however, so machine dependencies are confined to * -X * this file, its sister file "disfp.c", and the data file * -X * "distabs.c". * -X * * -X * All of the code in this file is based on the assumption * -X * of sixteen-bit integers. * -X * * -X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -X -X#include "dis.h" /* Disassembler declarations */ -X -int segflg; /* Segment-override flag */ -X -unsigned char objbuf[OBJMAX]; /* Buffer for object code */ -X -int objptr; /* Index into objbuf[] */ -X -unsigned long PC; /* Current program counter */ -X -X /* * * * * * MISCELLANEOUS SUPPORTING ROUTINES * * * * * */ -X -X -void -objini(j) /* Object code init routine */ -X -X register int j; -X -X{ -X if ((segflg == 1) || (segflg == 2)) -X segflg *= 3; -X else -X segflg = 0; -X objptr = 0; -X objbuf[objptr++] = (unsigned char)(j); -X} -X -X -void -objout() /* Object-code output routine */ -X -X{ -X register int k; -X -X if ( ! objflg ) -X return; -X else -X { -X printf("\t|"); -X if (symptr >= 0) -X printf(" %05.5lx:",(PC + 1L - (long)(objptr))); -X for (k = 0; k < objptr; ++k) -X printf(" %02.2x",objbuf[k]); -X putchar('\n'); -X } -X} -X -X -void -badseq(j,k) /* Invalid-sequence routine */ -X -X register int j, k; -X -X{ -X printf("\t.byte\t0x%02.2x\t\t| invalid code sequence\n",j); -X printf("\t.byte\t0x%02.2x\n",k); -X} -X -X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -X * * -X * This routine is the first of several opcode-specific * -X * handlers, each of which is dedicated to a particular * -X * opcode family. A pointer to a handler routine is con- * -X * tained in the second field of each optab[] entry. The * -X * dfhand() routine is the default handler, invoked when * -X * no other handler is appropriate (generally, when an in- * -X * valid opcode is encountered). * -X * * -X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -X -void -dfhand(j) -X -X register int j; /* Pointer to optab[] entry */ -X -X{/* * * * * * * * * * START OF dfhand() * * * * * * * * * */ -X -X segflg = 0; -X -X printf("\t.byte\t0x%02.2x",j); -X -X if (optab[j].min || optab[j].max) -X putchar('\n'); -X else -X printf("\t\t| unimplemented opcode\n"); -X -X}/* * * * * * * * * * * END OF dfhand() * * * * * * * * * * */ -X -X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -X * * -X * This is the single-byte handler, invoked whenever a * -X * one-byte opcode is encountered. * -X * * -X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -X -void -sbhand(j) -X -X register int j; /* Pointer to optab[] entry */ -X -X{/* * * * * * * * * * START OF sbhand() * * * * * * * * * */ -X -X objini(j); -X -X if (j == 0x2e) /* seg cs */ -X segflg = 1; -X -X if ((j == 0x26) /* seg es */ -X || (j == 0x36) /* seg ss */ -X || (j == 0x3e)) /* seg ds */ -X segflg = 2; -X -X printf("%s\n",optab[j].text); -X -X objout(); -X -X}/* * * * * * * * * * * END OF sbhand() * * * * * * * * * * */ -X -X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -X * * -X * This is the handler for most of the processor's regular * -X * arithmetic operations. * -X * * -X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -X -void -aohand(j) -X -X register int j; /* Pointer to optab[] entry */ -X -X{/* * * * * * * * * * START OF aohand() * * * * * * * * * */ -X -X register int k; -X int m, n; -X char b[64]; -X -X objini(j); -X -X switch (j & 7) -X { -X case 0 : -X case 1 : -X case 2 : -X case 3 : -X printf("%s\t",optab[j].text); -X FETCH(k); -X printf("%s\n",mtrans(j,k,TR_STD)); -X break; -X case 4 : -X FETCH(k); -X printf("%s\tal,*0x%02.2x\n",optab[j].text,k); -X break; -X case 5 : -X FETCH(m); -X FETCH(n); -X k = (n << 8) | m; -X if (lookext((long)(k),(PC - 1),b)) -X printf("%s\tax,#%s\n",optab[j].text,b); -X else -X printf("%s\tax,#0x%04.4x\n",optab[j].text,k); -X break; -X default : -X dfhand(j); -X break; -X } -X -X objout(); -X -X}/* * * * * * * * * * * END OF aohand() * * * * * * * * * * */ -X -X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -X * * -X * This is the handler for opcodes which perform short * -X * (eight-bit) relative jumps. * -X * * -X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -X -void -sjhand(j) -X -X register int j; /* Pointer to optab[] entry */ -X -X{/* * * * * * * * * * START OF sjhand() * * * * * * * * * */ -X -X register int k; -X int m; -X -X objini(j); -X -X FETCH(m); -X -X if (m & 0x80) -X k = 0xff00; -X else -X k = 0; -X -X k |= m; -X -X printf("%s\t%s\t\t| loc %05.5lx\n",optab[j].text, -X lookup((PC + k + 1L),N_TEXT,LOOK_REL,-1L), -X (PC + k + 1L)); -X -X objout(); -X -X}/* * * * * * * * * * * END OF sjhand() * * * * * * * * * * */ -X -X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -X * * -X * This is the handler for a loosely-knit family of op- * -X * codes which perform arithmetic and logical operations, * -X * and which take immediate data. The routine's logic is * -X * rather complex, so, in an effort to avoid additional * -X * complexity, the search for external references in the * -X * relocation table has been dispensed with. Eager hackers * -X * can try their hand at coding such a search. * -X * * -X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -X -void -imhand(j) -X -X register int j; /* Pointer to optab[] entry */ -X -X{/* * * * * * * * * * START OF imhand() * * * * * * * * * */ -X -X unsigned long pc; -X register int k; -X int offset, oflag, immed, iflag, mod, opi, w, rm; -X int m, n; -X static char a[100], b[30]; -X -X objini(j); -X -X FETCH(k); -X -X pc = PC + 1; -X -X offset = 0; -X mod = (k & 0xc0) >> 6; -X opi = (k & 0x38) >> 3; -X w = j & 1; -X rm = k & 7; -X -X if ((j & 2) -X && ((opi == 1) -X || (opi == 4) -X || (opi == 6))) -X { -X badseq(j,k); -X return; -X } -X -X strcpy(a,OPFAM[opi]); -X -X if ( ! w ) -X strcat(a,"b"); -X -X if ((oflag = mod) > 2) -X oflag = 0; -X -X if ((mod == 0) && (rm == 6)) -X { -X FETCH(m); -X FETCH(n); -X offset = (n << 8) | m; -X } -X else if (oflag) -X if (oflag == 2) -X { -X FETCH(m); -X FETCH(n); -X offset = (n << 8) | m; -X } -X else -X { -X FETCH(m); -X if (m & 0x80) -X n = 0xff00; -X else -X n = 0; -X offset = n | m; -X } -X -X switch (j & 3) -X { -X case 0 : -X case 2 : -X FETCH(immed); -X iflag = 0; -X break; -X case 1 : -X FETCH(m); -X FETCH(n); -X immed = (n << 8) | m; -X iflag = 1; -X break; -X case 3 : -X FETCH(immed); -X if (immed & 0x80) -X immed &= 0xff00; -X iflag = 0; -X break; -X } -X -X strcat(a,"\t"); -X -X switch (mod) -X { -X case 0 : -X if (rm == 6) -X strcat(a, -X lookup((long)(offset),N_DATA,LOOK_ABS,pc)); -X else -X { -X sprintf(b,"(%s)",REGS0[rm]); -X strcat(a,b); -X } -X break; -X case 1 : -X case 2 : -X if (mod == 1) -X strcat(a,"*"); -X else -X strcat(a,"#"); -X sprintf(b,"%d(",offset); -X strcat(a,b); -X strcat(a,REGS1[rm]); -X strcat(a,")"); -X break; -X case 3 : -X strcat(a,REGS[(w << 3) | rm]); -X break; -X } -X -X strcat(a,","); -X if (iflag) -X strcat(a,"#"); -X else -X strcat(a,"*"); -X sprintf(b,"%d",immed); -X strcat(a,b); -X -X printf("%s\n",a); -X -X objout(); -X -X}/* * * * * * * * * * * END OF imhand() * * * * * * * * * * */ -X -X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -X * * -X * This is the handler for various "mov"-type opcodes * -X * which use the mod, reg, and r/m fields of the second * -X * code byte in a standard, straightforward way. * -X * * -X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -X -void -mvhand(j) -X -X int j; /* Pointer to optab[] entry */ -X -X{/* * * * * * * * * * START OF mvhand() * * * * * * * * * */ -X -X register int k, m = j; -X -X objini(j); -X -X FETCH(k); -X -X if ((m == 0x84) || (m == 0x85) /* Kind of kludgey */ -X || (m == 0xc4) || (m == 0xc5) -X || (m == 0x8d)) -X if (m & 0x40) -X m |= 0x03; -X else -X m |= 0x02; -X -X printf("%s\t%s\n",optab[j].text,mtrans(m,k,TR_STD)); -X -X objout(); -X -X}/* * * * * * * * * * * END OF mvhand() * * * * * * * * * * */ -X -X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -X * * -X * This is the handler for segment-register "mov" opcodes. * -X * * -X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -X -void -mshand(j) -X -X register int j; /* Pointer to optab[] entry */ -X -X{/* * * * * * * * * * START OF mshand() * * * * * * * * * */ -X -X register int k; -X -X objini(j); -X -X FETCH(k); -X -X if (k & 0x20) -X { -X badseq(j,k); -X return; -X } -X -X printf("%s\t%s\n",optab[j].text,mtrans(j,k,TR_SEG)); -X -X objout(); -X -X}/* * * * * * * * * * * END OF mshand() * * * * * * * * * * */ -X -X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -X * * -X * This is the handler for pops, other than single-byte * -X * pops. (The 8088 allows popping into any register, or * -X * directly into memory, accessed either immediately or * -X * through a register and an index.) * -X * * -X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -X -void -pohand(j) -X -X register int j; /* Pointer to optab[] entry */ -X -X{/* * * * * * * * * * START OF pohand() * * * * * * * * * */ -X -X char *a; -X register int k; -X -X objini(j); -X -X FETCH(k); -X -X if (k & 0x38) -X { -X badseq(j,k); -X return; -X } -X -X printf("%s\t",optab[j].text); -X -X a = mtrans((j & 0xfd),k,TR_STD); -X -X mtrunc(a); -X -X printf("%s\n",a); -X -X objout(); -X -X}/* * * * * * * * * * * END OF pohand() * * * * * * * * * * */ -X -X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -X * * -X * This is the handler routine for intersegment calls and * -X * jumps. Its output is never symbolic, because the host * -X * linker does not allow symbolic intersegment address * -X * references except by means of symbolic constants, and * -X * any such constants in the symbol table, even if they * -X * are of the appropriate value, may be misleading. In * -X * compiled code, intersegment references should not be * -X * encountered, and even in assembled code, they should * -X * occur infrequently. If and when they do occur, however, * -X * they will be disassembled in absolute form. * -X * * -X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -X -void -cihand(j) -X -X int j; /* Pointer to optab[] entry */ -X -X{/* * * * * * * * * * START OF cihand() * * * * * * * * * */ -X -X register int m, n; -X -X objini(j); -X -X printf("%s\t",optab[j].text); -X -X FETCH(m); -X FETCH(n); -X -X printf("#0x%04.4x,",((n << 8) | m)); -X -X FETCH(m); -X FETCH(n); -X -X printf("#0x%04.4x\n",((n << 8) | m)); -X -X objout(); -X -X}/* * * * * * * * * * * END OF cihand() * * * * * * * * * * */ -X -X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -X * * -X * This is the handler for "mov" opcodes with immediate * -X * data. * -X * * -X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -X -void -mihand(j) -X -X register int j; /* Pointer to optab[] entry */ -X -X{/* * * * * * * * * * START OF mihand() * * * * * * * * * */ -X -X register int k; -X int m, n; -X char b[64]; -X -X objini(j); -X -X printf("%s",optab[j].text); -X -X if (j & 8) -X { -X FETCH(m); -X FETCH(n); -X k = ((n << 8) | m); -X if (lookext((long)(k),(PC - 1),b)) -X printf("#%s\n",b); -X else -X printf("#%d\n",k); -X } -X else -X { -X FETCH(m); -X printf("*%d\n",m); -X } -X -X objout(); -X -X}/* * * * * * * * * * * END OF mihand() * * * * * * * * * * */ -X -X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -X * * -X * This is the handler for a family of quick-move opcodes. * -X * * -X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -X -void -mqhand(j) -X -X int j; /* Pointer to optab[] entry */ -X -X{/* * * * * * * * * * START OF mqhand() * * * * * * * * * */ -X -X unsigned long pc; -X register int m, n; -X -X objini(j); -X -X pc = PC + 1; -X -X FETCH(m); -X FETCH(n); -X -X m = (n << 8) | m; -X -X printf("%s\t",optab[j].text); -X -X if (j & 2) -X printf("%s,%s\n", -X lookup((long)(m),N_DATA,LOOK_ABS,pc), -X REGS[(j & 1) << 3]); -X else -X printf("%s,%s\n", -X REGS[(j & 1) << 3], -X lookup((long)(m),N_DATA,LOOK_ABS,pc)); -X -X objout(); -X -X}/* * * * * * * * * * * END OF mqhand() * * * * * * * * * * */ -X -X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -X * * -X * This is the handler for a family of quick-test opcodes. * -X * * -X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -X -void -tqhand(j) -X -X int j; /* Pointer to optab[] entry */ -X -X{/* * * * * * * * * * START OF tqhand() * * * * * * * * * */ -X -X register int m, n; -X int k; -X char b[64]; -X -X objini(j); -X -X printf("%s\t%s,",optab[j].text,REGS[(j & 1) << 3]); -X -X FETCH(m); -X -X if (j & 1) -X { -X FETCH(n); -X k = ((n << 8) | m); -X if (lookext((long)(k),(PC - 1),b)) -X printf("#%s\n",b); -X else -X printf("#%d\n",k); -X } -X else -X { -X if (m & 80) -X m |= 0xff00; -X printf("*%d\n",m); -X } -X -X objout(); -X -X}/* * * * * * * * * * * END OF tqhand() * * * * * * * * * * */ -X -X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -X * * -X * This is the handler for multiple-byte "return" opcodes. * -X * The 8088 allows returns to take an optional 16-bit ar- * -X * gument, which reflects the amount to be added to SP * -X * after the pop of the return address. The idea is to * -X * facilitate the use of local parameters on the stack. * -X * After some rumination, it was decided to disassemble * -X * any such arguments as absolute quantities, rather than * -X * rummaging through the symbol table for possible corre- * -X * sponding constants. * -X * * -X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -X -void -rehand(j) -X -X int j; /* Pointer to optab[] entry */ -X -X{/* * * * * * * * * * START OF rehand() * * * * * * * * * */ -X -X register int m, n; -X -X objini(j); -X -X FETCH(m); -X FETCH(n); -X -X m = (n << 8) | m; -X -X printf("%s\t#0x%04.4x\n",optab[j].text,m); -X -X objout(); -X -X}/* * * * * * * * * * * END OF rehand() * * * * * * * * * * */ -X -X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -X * * -X * This is the handler for "mov" opcodes involving memory * -X * and immediate data. * -X * * -X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -X -void -mmhand(j) -X -X register int j; /* Pointer to optab[] entry */ -X -X{/* * * * * * * * * * START OF mmhand() * * * * * * * * * */ -X -X char *a; -X register int k; -X char b[64]; -X -X objini(j); -X -X FETCH(k); -X -X if (k & 0x38) -X { -X badseq(j,k); -X return; -X } -X -X printf("%s",optab[j].text); -X -X if ( ! (j & 1) ) -X putchar('b'); -X -X a = mtrans((j & 0xfd),(k & 0xc7),TR_STD); -X -X mtrunc(a); -X -X printf("\t%s,",a); -X -X if (j & 1) -X { -X FETCH(j); -X FETCH(k); -X k = (k << 8) | j; -X if (lookext((long)(k),(PC - 1),b)) -X printf("#%s\n",b); -X else -X printf("#%d\n",k); -X } -X else -X { -X FETCH(k); -X printf("*%d\n",k); -X } -X -X objout(); -X -X}/* * * * * * * * * * * END OF mmhand() * * * * * * * * * * */ -X -X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -X * * -X * This is the handler for the 8088 family of shift and * -X * rotate instructions. * -X * * -X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -X -void -srhand(j) -X -X register int j; /* Pointer to optab[] entry */ -X -X{/* * * * * * * * * * START OF srhand() * * * * * * * * * */ -X -X char *a; -X register int k; -X -X objini(j); -X -X FETCH(k); -X -X if ((k & 0x38) == 0x30) -X { -X badseq(j,k); -X return; -X } -X -X printf("%s",OPFAM[((k & 0x38) >> 3) + 16]); -X -X if ( ! (j & 1) ) -X putchar('b'); -X -X a = mtrans((j & 0xfd),(k & 0xc7),TR_STD); -X -X mtrunc(a); -X -X printf("\t%s",a); -X -X if (j & 2) -X printf(",cl\n"); -X else -X printf(",*1\n"); -X -X objout(); -X -X}/* * * * * * * * * * * END OF srhand() * * * * * * * * * * */ -X -X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -X * * -X * This is the handler for the ASCII-adjust opcodes. * -X * * -X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -X -void -aahand(j) -X -X register int j; /* Pointer to optab[] entry */ -X -X{/* * * * * * * * * * START OF aahand() * * * * * * * * * */ -X -X register int k; -X -X objini(j); -X -X FETCH(k); -X -X if (k != 0x0a) -X { -X badseq(j,k); -X return; -X } -X -X printf("%s\n",optab[j].text); -X -X objout(); -X -X}/* * * * * * * * * * * END OF aahand() * * * * * * * * * * */ -X -X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -X * * -X * This is the handler for port I/O opcodes which specify * -X * the port address as an immediate operand. * -X * * -X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -X -void -iohand(j) -X -X register int j; /* Pointer to optab[] entry */ -X -X{/* * * * * * * * * * START OF iohand() * * * * * * * * * */ -X -X register int k; -X -X objini(j); -X -X FETCH(k); -X -X printf("%s\t0x%02.2x\n",optab[j].text,k); -X -X objout(); -X -X}/* * * * * * * * * * * END OF iohand() * * * * * * * * * * */ -X -X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -X * * -X * This is the handler for opcodes which perform long * -X * (sixteen-bit) relative jumps and calls. * -X * * -X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -X -void -ljhand(j) -X -X register int j; /* Pointer to optab[] entry */ -X -X{/* * * * * * * * * * START OF ljhand() * * * * * * * * * */ -X -X register int k; -X int m, n; -X -X objini(j); -X -X FETCH(m); -X FETCH(n); -X -X k = (n << 8) | m; -X -X printf("%s\t%s\t\t| loc %05.5lx\n",optab[j].text, -X lookup((PC + k + 1L),N_TEXT,LOOK_LNG,(PC - 1L)), -X (PC + k + 1L)); -X -X objout(); -X -X}/* * * * * * * * * * * END OF ljhand() * * * * * * * * * * */ -X -X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -X * * -X * This is the handler for a pair of oddball opcodes (0xf6 * -X * and 0xf7) which perform miscellaneous arithmetic opera- * -X * tions not dealt with elsewhere. * -X * * -X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -X -void -mahand(j) -X -X register int j; /* Pointer to optab[] entry */ -X -X{/* * * * * * * * * * START OF mahand() * * * * * * * * * */ -X -X char *a; -X register int k; -X char b[64]; -X -X objini(j); -X -X FETCH(k); -X -X a = mtrans((j & 0xfd),(k & 0xc7),TR_STD); -X -X mtrunc(a); -X -X switch (((k = objbuf[1]) & 0x38) >> 3) -X { -X case 0 : -X printf("\ttest"); -X break; -X case 1 : -X badseq(j,k); -X return; -X case 2 : -X printf("\tnot"); -X break; -X case 3 : -X printf("\tneg"); -X break; -X case 4 : -X printf("\tmul"); -X break; -X case 5 : -X printf("\timul"); -X break; -X case 6 : -X printf("\tdiv"); -X break; -X case 7 : -X printf("\tidiv"); -X break; -X } -X -X if ( ! (j & 1) ) -X putchar('b'); -X -X printf("\t%s",a); -X -X if (k & 0x38) -X putchar('\n'); -X else -X if (j & 1) -X { -X FETCH(j); -X FETCH(k); -X k = (k << 8) | j; -X if (lookext((long)(k),(PC - 1),b)) -X printf(",#%s\n",b); -X else -X printf(",#%d\n",k); -X } -X else -X { -X FETCH(k); -X printf(",*%d\n",k); -X } -X -X objout(); -X -X}/* * * * * * * * * * * END OF mahand() * * * * * * * * * * */ -X -X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -X * * -X * This is the handler for miscellaneous jump, call, push, * -X * and increment/decrement opcodes (0xfe and 0xff) which * -X * are not dealt with elsewhere. * -X * * -X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -X -void -mjhand(j) -X -X register int j; /* Pointer to optab[] entry */ -X -X{/* * * * * * * * * * START OF mjhand() * * * * * * * * * */ -X -X char *a; -X register int k; -X -X objini(j); -X -X FETCH(k); -X -X a = mtrans((j & 0xfd),(k & 0xc7),TR_STD); -X -X mtrunc(a); -X -X switch (((k = objbuf[1]) & 0x38) >> 3) -X { -X case 0 : -X printf("\tinc"); -X if ( ! (j & 1) ) -X putchar('b'); -X putchar('\t'); -X break; -X case 1 : -X printf("\tdec"); -X if ( ! (j & 1) ) -X putchar('b'); -X putchar('\t'); -X break; -X case 2 : -X if (j & 1) -X printf("\tcall\t@"); -X else -X goto BAD; -X break; -X case 3 : -X if (j & 1) -X printf("\tcalli\t@"); -X else -X goto BAD; -X break; -X case 4 : -X if (j & 1) -X printf("\tjmp\t@"); -X else -X goto BAD; -X break; -X case 5 : -X if (j & 1) -X printf("\tjmpi\t@"); -X else -X goto BAD; -X break; -X case 6 : -X if (j & 1) -X printf("\tpush\t"); -X else -X goto BAD; -X break; -X case 7 : -X BAD : -X badseq(j,k); -X return; -X } -X -X printf("%s\n",a); -X -X objout(); -X -X}/* * * * * * * * * * * END OF mjhand() * * * * * * * * * * */ -X -X -END_OF_FILE -if test 25688 -ne `wc -c <'dishand.c'`; then - echo shar: \"'dishand.c'\" unpacked with wrong size! -fi -# end of 'dishand.c' -fi -if test -f 'distabs.c' -a "${1}" != "-c" ; then - echo shar: Will not clobber existing file \"'distabs.c'\" -else -echo shar: Extracting \"'distabs.c'\" \(30238 characters\) -sed "s/^X//" >'distabs.c' <<'END_OF_FILE' -static char *sccsid = -X "@(#) distabs.c, Ver. 2.1 created 00:00:00 87/09/01"; -X -X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -X * * -X * Copyright (C) 1987 G. M. Harding, all rights reserved * -X * * -X * Permission to copy and redistribute is hereby granted, * -X * provided full source code, with all copyright notices, * -X * accompanies any redistribution. * -X * * -X * This file contains the lookup tables and other data * -X * structures for the Intel 8088 symbolic disassembler. It * -X * also contains a few global routines which facilitate * -X * access to the tables, for use primarily by the handler * -X * functions. * -X * * -X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -X -X#include "dis.h" /* Disassembler declarations */ -X -struct exec HDR; /* Used to hold header info */ -X -struct nlist symtab[MAXSYM]; /* Array of symbol table info */ -X -struct reloc relo[MAXSYM]; /* Array of relocation info */ -X -int symptr = -1, /* Index into symtab[] */ -X relptr = -1; /* Index into relo[] */ -X -char *REGS[] = /* Table of register names */ -X { -X "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh", -X "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", -X "es", "cs", "ss", "ds" -X }; -X -char *REGS0[] = /* Mode 0 register name table */ -X { -X "bx_si", "bx_di", "bp_si", "bp_di", "si", "di", "", "bx" -X }; -X -char *REGS1[] = /* Mode 1 register name table */ -X { -X "bx_si", "bx_di", "bp_si", "bp_di", "si", "di", "bp", "bx" -X }; -X -int symrank[6][6] = /* Symbol type/rank matrix */ -X { -X /* UND ABS TXT DAT BSS COM */ -X /* UND */ 5, 4, 1, 2, 3, 0, -X /* ABS */ 1, 5, 4, 3, 2, 0, -X /* TXT */ 4, 1, 5, 3, 2, 0, -X /* DAT */ 3, 1, 2, 5, 4, 0, -X /* BSS */ 3, 1, 2, 4, 5, 0, -X /* COM */ 2, 0, 1, 3, 4, 5 -X }; -X -X /* * * * * * * * * * * * OPCODE DATA * * * * * * * * * * * */ -X -char ADD[] = "\tadd", /* Mnemonics by family */ -X OR[] = "\tor", -X ADC[] = "\tadc", -X SBB[] = "\tsbb", -X AND[] = "\tand", -X SUB[] = "\tsub", -X XOR[] = "\txor", -X CMP[] = "\tcmp", -X NOT[] = "\tnot", -X NEG[] = "\tneg", -X MUL[] = "\tmul", -X DIV[] = "\tdiv", -X MOV[] = "\tmov", -X ESC[] = "\tesc", -X TEST[] = "\ttest", -X AMBIG[] = "", -X ROL[] = "\trol", -X ROR[] = "\tror", -X RCL[] = "\trcl", -X RCR[] = "\trcr", -X SAL[] = "\tsal", -X SHR[] = "\tshr", -X SHL[] = "\tshl", -X SAR[] = "\tsar"; -X -char *OPFAM[] = /* Family lookup table */ -X { -X ADD, OR, ADC, SBB, AND, SUB, XOR, CMP, -X NOT, NEG, MUL, DIV, MOV, ESC, TEST, AMBIG, -X ROL, ROR, RCL, RCR, SAL, SHR, SHL, SAR -X }; -X -struct opcode optab[] = /* Table of opcode data */ -X { -X ADD, aohand, 2, 4, /* 0x00 */ -X ADD, aohand, 2, 4, /* 0x01 */ -X ADD, aohand, 2, 4, /* 0x02 */ -X ADD, aohand, 2, 4, /* 0x03 */ -X ADD, aohand, 2, 2, /* 0x04 */ -X ADD, aohand, 3, 3, /* 0x05 */ -X "\tpush\tes", sbhand, 1, 1, /* 0x06 */ -X "\tpop\tes", sbhand, 1, 1, /* 0x07 */ -X OR, aohand, 2, 4, /* 0x08 */ -X OR, aohand, 2, 4, /* 0x09 */ -X OR, aohand, 2, 4, /* 0x0a */ -X OR, aohand, 2, 4, /* 0x0b */ -X OR, aohand, 2, 2, /* 0x0c */ -X OR, aohand, 3, 3, /* 0x0d */ -X "\tpush\tcs", sbhand, 1, 1, /* 0x0e */ -X NULL, dfhand, 0, 0, /* 0x0f */ -X ADC, aohand, 2, 4, /* 0x10 */ -X ADC, aohand, 2, 4, /* 0x11 */ -X ADC, aohand, 2, 4, /* 0x12 */ -X ADC, aohand, 2, 4, /* 0x13 */ -X ADC, aohand, 2, 2, /* 0x14 */ -X ADC, aohand, 3, 3, /* 0x15 */ -X "\tpush\tss", sbhand, 1, 1, /* 0x16 */ -X "\tpop\tss", sbhand, 1, 1, /* 0x17 */ -X SBB, aohand, 2, 4, /* 0x18 */ -X SBB, aohand, 2, 4, /* 0x19 */ -X SBB, aohand, 2, 4, /* 0x1a */ -X SBB, aohand, 2, 4, /* 0x1b */ -X SBB, aohand, 2, 2, /* 0x1c */ -X SBB, aohand, 3, 3, /* 0x1d */ -X "\tpush\tds", sbhand, 1, 1, /* 0x1e */ -X "\tpop\tds", sbhand, 1, 1, /* 0x1f */ -X AND, aohand, 2, 4, /* 0x20 */ -X AND, aohand, 2, 4, /* 0x21 */ -X AND, aohand, 2, 4, /* 0x22 */ -X AND, aohand, 2, 4, /* 0x23 */ -X AND, aohand, 2, 2, /* 0x24 */ -X AND, aohand, 3, 3, /* 0x25 */ -X "\tseg\tes", sbhand, 1, 1, /* 0x26 */ -X "\tdaa", sbhand, 1, 1, /* 0x27 */ -X SUB, aohand, 2, 4, /* 0x28 */ -X SUB, aohand, 2, 4, /* 0x29 */ -X SUB, aohand, 2, 4, /* 0x2a */ -X SUB, aohand, 2, 4, /* 0x2b */ -X SUB, aohand, 2, 2, /* 0x2c */ -X SUB, aohand, 3, 3, /* 0x2d */ -X "\tseg\tcs", sbhand, 1, 1, /* 0x2e */ -X "\tdas", sbhand, 1, 1, /* 0x2f */ -X XOR, aohand, 2, 4, /* 0x30 */ -X XOR, aohand, 2, 4, /* 0x31 */ -X XOR, aohand, 2, 4, /* 0x32 */ -X XOR, aohand, 2, 4, /* 0x33 */ -X XOR, aohand, 2, 2, /* 0x34 */ -X XOR, aohand, 3, 3, /* 0x35 */ -X "\tseg\tss", sbhand, 1, 1, /* 0x36 */ -X "\taaa", sbhand, 1, 1, /* 0x37 */ -X CMP, aohand, 2, 4, /* 0x38 */ -X CMP, aohand, 2, 4, /* 0x39 */ -X CMP, aohand, 2, 4, /* 0x3a */ -X CMP, aohand, 2, 4, /* 0x3b */ -X CMP, aohand, 2, 2, /* 0x3c */ -X CMP, aohand, 3, 3, /* 0x3d */ -X "\tseg\tds", sbhand, 1, 1, /* 0x3e */ -X "\taas", sbhand, 1, 1, /* 0x3f */ -X "\tinc\tax", sbhand, 1, 1, /* 0x40 */ -X "\tinc\tcx", sbhand, 1, 1, /* 0x41 */ -X "\tinc\tdx", sbhand, 1, 1, /* 0x42 */ -X "\tinc\tbx", sbhand, 1, 1, /* 0x43 */ -X "\tinc\tsp", sbhand, 1, 1, /* 0x44 */ -X "\tinc\tbp", sbhand, 1, 1, /* 0x45 */ -X "\tinc\tsi", sbhand, 1, 1, /* 0x46 */ -X "\tinc\tdi", sbhand, 1, 1, /* 0x47 */ -X "\tdec\tax", sbhand, 1, 1, /* 0x48 */ -X "\tdec\tcx", sbhand, 1, 1, /* 0x49 */ -X "\tdec\tdx", sbhand, 1, 1, /* 0x4a */ -X "\tdec\tbx", sbhand, 1, 1, /* 0x4b */ -X "\tdec\tsp", sbhand, 1, 1, /* 0x4c */ -X "\tdec\tbp", sbhand, 1, 1, /* 0x4d */ -X "\tdec\tsi", sbhand, 1, 1, /* 0x4e */ -X "\tdec\tdi", sbhand, 1, 1, /* 0x4f */ -X "\tpush\tax", sbhand, 1, 1, /* 0x50 */ -X "\tpush\tcx", sbhand, 1, 1, /* 0x51 */ -X "\tpush\tdx", sbhand, 1, 1, /* 0x52 */ -X "\tpush\tbx", sbhand, 1, 1, /* 0x53 */ -X "\tpush\tsp", sbhand, 1, 1, /* 0x54 */ -X "\tpush\tbp", sbhand, 1, 1, /* 0x55 */ -X "\tpush\tsi", sbhand, 1, 1, /* 0x56 */ -X "\tpush\tdi", sbhand, 1, 1, /* 0x57 */ -X "\tpop\tax", sbhand, 1, 1, /* 0x58 */ -X "\tpop\tcx", sbhand, 1, 1, /* 0x59 */ -X "\tpop\tdx", sbhand, 1, 1, /* 0x5a */ -X "\tpop\tbx", sbhand, 1, 1, /* 0x5b */ -X "\tpop\tsp", sbhand, 1, 1, /* 0x5c */ -X "\tpop\tbp", sbhand, 1, 1, /* 0x5d */ -X "\tpop\tsi", sbhand, 1, 1, /* 0x5e */ -X "\tpop\tdi", sbhand, 1, 1, /* 0x5f */ -X NULL, dfhand, 0, 0, /* 0x60 */ -X NULL, dfhand, 0, 0, /* 0x61 */ -X NULL, dfhand, 0, 0, /* 0x62 */ -X NULL, dfhand, 0, 0, /* 0x63 */ -X NULL, dfhand, 0, 0, /* 0x64 */ -X NULL, dfhand, 0, 0, /* 0x65 */ -X NULL, dfhand, 0, 0, /* 0x66 */ -X NULL, dfhand, 0, 0, /* 0x67 */ -X NULL, dfhand, 0, 0, /* 0x68 */ -X NULL, dfhand, 0, 0, /* 0x69 */ -X NULL, dfhand, 0, 0, /* 0x6a */ -X NULL, dfhand, 0, 0, /* 0x6b */ -X NULL, dfhand, 0, 0, /* 0x6c */ -X NULL, dfhand, 0, 0, /* 0x6d */ -X NULL, dfhand, 0, 0, /* 0x6e */ -X NULL, dfhand, 0, 0, /* 0x6f */ -X "\tjo", sjhand, 2, 2, /* 0x70 */ -X "\tjno", sjhand, 2, 2, /* 0x71 */ -X "\tjc", sjhand, 2, 2, /* 0x72 */ -X "\tjnc", sjhand, 2, 2, /* 0x73 */ -X "\tjz", sjhand, 2, 2, /* 0x74 */ -X "\tjnz", sjhand, 2, 2, /* 0x75 */ -X "\tjna", sjhand, 2, 2, /* 0x76 */ -X "\tja", sjhand, 2, 2, /* 0x77 */ -X "\tjs", sjhand, 2, 2, /* 0x78 */ -X "\tjns", sjhand, 2, 2, /* 0x79 */ -X "\tjp", sjhand, 2, 2, /* 0x7a */ -X "\tjnp", sjhand, 2, 2, /* 0x7b */ -X "\tjl", sjhand, 2, 2, /* 0x7c */ -X "\tjnl", sjhand, 2, 2, /* 0x7d */ -X "\tjng", sjhand, 2, 2, /* 0x7e */ -X "\tjg", sjhand, 2, 2, /* 0x7f */ -X AMBIG, imhand, 3, 5, /* 0x80 */ -X AMBIG, imhand, 4, 6, /* 0x81 */ -X AMBIG, imhand, 3, 5, /* 0x82 */ -X AMBIG, imhand, 3, 5, /* 0x83 */ -X TEST, mvhand, 2, 4, /* 0x84 */ -X TEST, mvhand, 2, 4, /* 0x85 */ -X "\txchg", mvhand, 2, 4, /* 0x86 */ -X "\txchg", mvhand, 2, 4, /* 0x87 */ -X MOV, mvhand, 2, 4, /* 0x88 */ -X MOV, mvhand, 2, 4, /* 0x89 */ -X MOV, mvhand, 2, 4, /* 0x8a */ -X MOV, mvhand, 2, 4, /* 0x8b */ -X MOV, mshand, 2, 4, /* 0x8c */ -X "\tlea", mvhand, 2, 4, /* 0x8d */ -X MOV, mshand, 2, 4, /* 0x8e */ -X "\tpop", pohand, 2, 4, /* 0x8f */ -X "\tnop", sbhand, 1, 1, /* 0x90 */ -X "\txchg\tax,cx", sbhand, 1, 1, /* 0x91 */ -X "\txchg\tax,dx", sbhand, 1, 1, /* 0x92 */ -X "\txchg\tax,bx", sbhand, 1, 1, /* 0x93 */ -X "\txchg\tax,sp", sbhand, 1, 1, /* 0x94 */ -X "\txchg\tax,bp", sbhand, 1, 1, /* 0x95 */ -X "\txchg\tax,si", sbhand, 1, 1, /* 0x96 */ -X "\txchg\tax,di", sbhand, 1, 1, /* 0x97 */ -X "\tcbw", sbhand, 1, 1, /* 0x98 */ -X "\tcwd", sbhand, 1, 1, /* 0x99 */ -X "\tcalli", cihand, 5, 5, /* 0x9a */ -X "\twait", sbhand, 1, 1, /* 0x9b */ -X "\tpushf", sbhand, 1, 1, /* 0x9c */ -X "\tpopf", sbhand, 1, 1, /* 0x9d */ -X "\tsahf", sbhand, 1, 1, /* 0x9e */ -X "\tlahf", sbhand, 1, 1, /* 0x9f */ -X MOV, mqhand, 3, 3, /* 0xa0 */ -X MOV, mqhand, 3, 3, /* 0xa1 */ -X MOV, mqhand, 3, 3, /* 0xa2 */ -X MOV, mqhand, 3, 3, /* 0xa3 */ -X "\tmovb", sbhand, 1, 1, /* 0xa4 */ -X "\tmovw", sbhand, 1, 1, /* 0xa5 */ -X "\tcmpb", sbhand, 1, 1, /* 0xa6 */ -X "\tcmpw", sbhand, 1, 1, /* 0xa7 */ -X TEST, tqhand, 2, 2, /* 0xa8 */ -X TEST, tqhand, 3, 3, /* 0xa9 */ -X "\tstob", sbhand, 1, 1, /* 0xaa */ -X "\tstow", sbhand, 1, 1, /* 0xab */ -X "\tlodb", sbhand, 1, 1, /* 0xac */ -X "\tlodw", sbhand, 1, 1, /* 0xad */ -X "\tscab", sbhand, 1, 1, /* 0xae */ -X "\tscaw", sbhand, 1, 1, /* 0xaf */ -X "\tmov\tal,", mihand, 2, 2, /* 0xb0 */ -X "\tmov\tcl,", mihand, 2, 2, /* 0xb1 */ -X "\tmov\tdl,", mihand, 2, 2, /* 0xb2 */ -X "\tmov\tbl,", mihand, 2, 2, /* 0xb3 */ -X "\tmov\tah,", mihand, 2, 2, /* 0xb4 */ -X "\tmov\tch,", mihand, 2, 2, /* 0xb5 */ -X "\tmov\tdh,", mihand, 2, 2, /* 0xb6 */ -X "\tmov\tbh,", mihand, 2, 2, /* 0xb7 */ -X "\tmov\tax,", mihand, 3, 3, /* 0xb8 */ -X "\tmov\tcx,", mihand, 3, 3, /* 0xb9 */ -X "\tmov\tdx,", mihand, 3, 3, /* 0xba */ -X "\tmov\tbx,", mihand, 3, 3, /* 0xbb */ -X "\tmov\tsp,", mihand, 3, 3, /* 0xbc */ -X "\tmov\tbp,", mihand, 3, 3, /* 0xbd */ -X "\tmov\tsi,", mihand, 3, 3, /* 0xbe */ -X "\tmov\tdi,", mihand, 3, 3, /* 0xbf */ -X NULL, dfhand, 0, 0, /* 0xc0 */ -X NULL, dfhand, 0, 0, /* 0xc1 */ -X "\tret", rehand, 3, 3, /* 0xc2 */ -X "\tret", sbhand, 1, 1, /* 0xc3 */ -X "\tles", mvhand, 2, 4, /* 0xc4 */ -X "\tlds", mvhand, 2, 4, /* 0xc5 */ -X MOV, mmhand, 3, 5, /* 0xc6 */ -X MOV, mmhand, 4, 6, /* 0xc7 */ -X NULL, dfhand, 0, 0, /* 0xc8 */ -X NULL, dfhand, 0, 0, /* 0xc9 */ -X "\treti", rehand, 3, 3, /* 0xca */ -X "\treti", sbhand, 1, 1, /* 0xcb */ -X "\tint", sbhand, 1, 1, /* 0xcc */ -X "\tint", inhand, 2, 2, /* 0xcd */ -X "\tinto", sbhand, 1, 1, /* 0xce */ -X "\tiret", sbhand, 1, 1, /* 0xcf */ -X AMBIG, srhand, 2, 4, /* 0xd0 */ -X AMBIG, srhand, 2, 4, /* 0xd1 */ -X AMBIG, srhand, 2, 4, /* 0xd2 */ -X AMBIG, srhand, 2, 4, /* 0xd3 */ -X "\taam", aahand, 2, 2, /* 0xd4 */ -X "\taad", aahand, 2, 2, /* 0xd5 */ -X NULL, dfhand, 0, 0, /* 0xd6 */ -X "\txlat", sbhand, 1, 1, /* 0xd7 */ -X ESC, eshand, 2, 2, /* 0xd8 */ -X ESC, eshand, 2, 2, /* 0xd9 */ -X ESC, eshand, 2, 2, /* 0xda */ -X ESC, eshand, 2, 2, /* 0xdb */ -X ESC, eshand, 2, 2, /* 0xdc */ -X ESC, eshand, 2, 2, /* 0xdd */ -X ESC, eshand, 2, 2, /* 0xde */ -X ESC, eshand, 2, 2, /* 0xdf */ -X "\tloopne", sjhand, 2, 2, /* 0xe0 */ -X "\tloope", sjhand, 2, 2, /* 0xe1 */ -X "\tloop", sjhand, 2, 2, /* 0xe2 */ -X "\tjcxz", sjhand, 2, 2, /* 0xe3 */ -X "\tin", iohand, 2, 2, /* 0xe4 */ -X "\tinw", iohand, 2, 2, /* 0xe5 */ -X "\tout", iohand, 2, 2, /* 0xe6 */ -X "\toutw", iohand, 2, 2, /* 0xe7 */ -X "\tcall", ljhand, 3, 3, /* 0xe8 */ -X "\tjmp", ljhand, 3, 3, /* 0xe9 */ -X "\tjmpi", cihand, 5, 5, /* 0xea */ -X "\tj", sjhand, 2, 2, /* 0xeb */ -X "\tin", sbhand, 1, 1, /* 0xec */ -X "\tinw", sbhand, 1, 1, /* 0xed */ -X "\tout", sbhand, 1, 1, /* 0xee */ -X "\toutw", sbhand, 1, 1, /* 0xef */ -X "\tlock", sbhand, 1, 1, /* 0xf0 */ -X NULL, dfhand, 0, 0, /* 0xf1 */ -X "\trepnz", sbhand, 1, 1, /* 0xf2 */ -X "\trepz", sbhand, 1, 1, /* 0xf3 */ -X "\thlt", sbhand, 1, 1, /* 0xf4 */ -X "\tcmc", sbhand, 1, 1, /* 0xf5 */ -X AMBIG, mahand, 2, 5, /* 0xf6 */ -X AMBIG, mahand, 2, 6, /* 0xf7 */ -X "\tclc", sbhand, 1, 1, /* 0xf8 */ -X "\tstc", sbhand, 1, 1, /* 0xf9 */ -X "\tcli", sbhand, 1, 1, /* 0xfa */ -X "\tsti", sbhand, 1, 1, /* 0xfb */ -X "\tcld", sbhand, 1, 1, /* 0xfc */ -X "\tstd", sbhand, 1, 1, /* 0xfd */ -X AMBIG, mjhand, 2, 4, /* 0xfe */ -X AMBIG, mjhand, 2, 4 /* 0xff */ -X }; -X -X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -X * * -X * This simple routine returns the name field of a symbol * -X * table entry as a printable string. * -X * * -X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -X -char * -getnam(k) -X -X register int k; -X -X{/* * * * * * * * * * START OF getnam() * * * * * * * * * */ -X -X register int j; -X static char a[9]; -X -X for (j = 0; j < 8; ++j) -X if ( ! symtab[k].n_name[j] ) -X break; -X else -X a[j] = symtab[k].n_name[j]; -X -X a[j] = '\0'; -X -X return (a); -X -X}/* * * * * * * * * * * END OF getnam() * * * * * * * * * * */ -X -X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -X * * -X * This function is responsible for mucking through the * -X * relocation table in search of externally referenced * -X * symbols to be output as operands. It accepts two long * -X * arguments: the code-segment location at which an extern * -X * reference is expected, and the offset value which is * -X * embedded in the object code and used at link time to * -X * bias the external value. In the most typical case, the * -X * function will be called by lookup(), which always makes * -X * a check for external names before searching the symbol * -X * table proper. However, it may also be called directly * -X * by any function (such as the move-immediate handler) * -X * which wants to make an independent check for externals. * -X * The caller is expected to supply, as the third argument * -X * to the function, a pointer to a character buffer large * -X * enough to hold any possible output string. Lookext() * -X * will fill this buffer and return a logical TRUE if it * -X * finds an extern reference; otherwise, it will return a * -X * logical FALSE, leaving the buffer undisturbed. * -X * * -X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -X -int -lookext(off,loc,buf) -X -X long off, loc; -X char *buf; -X -X{/* * * * * * * * * * START OF lookext() * * * * * * * * * */ -X -X register int k; -X char c[16]; -X -X if ((loc != -1L) && (relptr >= 0)) -X for (k = 0; k <= relptr; ++k) -X if ((relo[k].r_vaddr == loc) -X && (relo[k].r_symndx < S_BSS)) -X { -X strcpy(buf,getnam(relo[k].r_symndx)); -X if (off) -X { -X if (off < 0) -X sprintf(c,"%ld",off); -X else -X sprintf(c,"+%ld",off); -X strcat(buf,c); -X } -X return (1); -X } -X -X return (0); -X -X}/* * * * * * * * * * END OF lookext() * * * * * * * * * */ -X -X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -X * * -X * This function finds an entry in the symbol table by * -X * value. Its input is a (long) machine address, and its * -X * output is a pointer to a string containing the corre- * -X * sponding symbolic name. The function first searches the * -X * relocation table for a possible external reference; if * -X * none is found, a linear search of the symbol table is * -X * undertaken. If no matching symbol has been found at the * -X * end of these searches, the function returns a pointer * -X * to a string containing the ASCII equivalent of the ad- * -X * dress which was to be located, so that, regardless of * -X * the success of the search, the function's return value * -X * is suitable for use as a memory-reference operand. The * -X * caller specifies the type of symbol to be found (text, * -X * data, bss, undefined, absolute, or common) by means of * -X * the function's second parameter. The third parameter * -X * specifies the format to be used in the event of a nu- * -X * meric output: zero for absolute format, one for short * -X * relative format, two for long relative format. The * -X * fourth parameter is the address which would appear in * -X * the relocation table for the reference in question, or * -X * -1 if the relocation table is not to be searched. The * -X * function attempts to apply a certain amount of intelli- * -X * gence in its selection of symbols, so it is possible * -X * that, in the absence of a type match, a symbol of the * -X * correct value but different type will be returned. * -X * * -X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -X -char * -lookup(addr,type,kind,ext) -X -X long addr; /* Machine address to be located */ -X -X int type, /* Type of symbol to be matched */ -X kind; /* Addressing output mode to use */ -X -X long ext; /* Value for extern ref, if any */ -X -X{/* * * * * * * * * * START OF lookup() * * * * * * * * * */ -X -X register int j, k; -X static char b[64]; -X -X struct -X { -X int i; -X int t; -X } -X best; -X -X if (lookext(addr,ext,b)) -X return (b); -X -X if (segflg) -X if (segflg & 1) -X type = N_TEXT; -X else -X type = N_DATA; -X -X for (k = 0, best.i = -1; k <= symptr; ++k) -X if (symtab[k].n_value == addr) -X if ((j = symtab[k].n_sclass & N_SECT) == type) -X { -X best.t = j; -X best.i = k; -X break; -X } -X else if (segflg || (HDR.a_flags & A_SEP)) -X continue; -X else if (best.i < 0) -X best.t = j, best.i = k; -X else if (symrank[type][j] > symrank[type][best.t]) -X best.t = j, best.i = k; -X -X if (best.i >= 0) -X return (getnam(best.i)); -X -X if (kind == LOOK_ABS) -X sprintf(b,"0x%05.5x",addr); -X else -X { -X long x = addr - (PC - kind); -X if (x < 0) -X sprintf(b,".%ld",x); -X else -X sprintf(b,".+%ld",x); -X } -X -X return (b); -X -X}/* * * * * * * * * * * END OF lookup() * * * * * * * * * * */ -X -X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -X * * -X * This function translates an 8088 addressing mode byte * -X * to an equivalent assembler string, returning a pointer * -X * thereto. If necessary, it performs successive inputs * -X * of bytes from the object file in order to obtain offset * -X * data, adjusting PC accordingly. (The addressing mode * -X * byte appears in several 8088 opcodes; it is used to * -X * specify source and destination operand locations.) The * -X * third argument to the function is zero if the standard * -X * registers are to be used, or eight if the segment reg- * -X * isters are to be used; these constants are defined sym- * -X * bolically in dis.h. NOTE: The mtrans() function must * -X * NEVER be called except immediately after fetching the * -X * mode byte. If any additional object bytes are fetched * -X * after the fetch of the mode byte, mtrans() will not * -X * produce correct output! * -X * * -X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -X -char * -mtrans(c,m,type) -X -X register int c; /* Primary instruction byte */ -X register int m; /* Addressing mode byte */ -X -X int type; /* Type code: standard or seg */ -X -X{/* * * * * * * * * * START OF mtrans() * * * * * * * * * */ -X -X unsigned long pc; -X int offset, oflag, dir, w, mod, reg, rm; -X static char a[100]; -X static char b[30]; -X -X offset = 0; -X dir = c & 2; -X w = c & 1; -X mod = (m & 0xc0) >> 6; -X reg = (m & 0x38) >> 3; -X rm = m & 7; -X pc = PC + 1; -X -X if (type) -X w = 1; -X -X if ((oflag = mod) > 2) -X oflag = 0; -X -X if (oflag) -X { -X int j, k; -X if (oflag == 2) -X { -X FETCH(j); -X FETCH(k); -X offset = (k << 8) | j; -X } -X else -X { -X FETCH(j); -X if (j & 0x80) -X k = 0xff00; -X else -X k = 0; -X offset = k | j; -X } -X } -X -X if (dir) -X { -X strcpy(a,REGS[type + ((w << 3) | reg)]); -X strcat(a,","); -X switch (mod) -X { -X case 0 : -X if (rm == 6) -X { -X int j, k; -X FETCH(j); -X FETCH(k); -X offset = (k << 8) | j; -X strcat(a, -X lookup((long)(offset),N_DATA,LOOK_ABS,pc)); -X } -X else -X { -X sprintf(b,"(%s)",REGS0[rm]); -X strcat(a,b); -X } -X break; -X case 1 : -X case 2 : -X if (mod == 1) -X strcat(a,"*"); -X else -X strcat(a,"#"); -X sprintf(b,"%d(",offset); -X strcat(a,b); -X strcat(a,REGS1[rm]); -X strcat(a,")"); -X break; -X case 3 : -X strcat(a,REGS[(w << 3) | rm]); -X break; -X } -X } -X else -X { -X switch (mod) -X { -X case 0 : -X if (rm == 6) -X { -X int j, k; -X FETCH(j); -X FETCH(k); -X offset = (k << 8) | j; -X strcpy(a, -X lookup((long)(offset),N_DATA,LOOK_ABS,pc)); -X } -X else -X { -X sprintf(b,"(%s)",REGS0[rm]); -X strcpy(a,b); -X } -X break; -X case 1 : -X case 2 : -X if (mod == 1) -X strcpy(a,"*"); -X else -X strcpy(a,"#"); -X sprintf(b,"%d(",offset); -X strcat(a,b); -X strcat(a,REGS1[rm]); -X strcat(a,")"); -X break; -X case 3 : -X strcpy(a,REGS[(w << 3) | rm]); -X break; -X } -X strcat(a,","); -X strcat(a,REGS[type + ((w << 3) | reg)]); -X } -X -X return (a); -X -X}/* * * * * * * * * * * END OF mtrans() * * * * * * * * * * */ -X -X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -X * * -X * This simple routine truncates a string returned by the * -X * mtrans() function, removing its source operand. This is * -X * useful in handlers which ignore the "reg" field of the * -X * mode byte. * -X * * -X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -X -void -mtrunc(a) -X -X register char *a; /* Ptr. to string to truncate */ -X -X{/* * * * * * * * * * START OF mtrunc() * * * * * * * * * */ -X -X register int k; -X -X for (k = strlen(a) - 1; k >= 0; --k) -X if (a[k] == ',') -X { -X a[k] = '\0'; -X break; -X } -X -X}/* * * * * * * * * * * END OF mtrunc() * * * * * * * * * * */ -X -X -END_OF_FILE -if test 30238 -ne `wc -c <'distabs.c'`; then - echo shar: \"'distabs.c'\" unpacked with wrong size! -fi -# end of 'distabs.c' -fi -echo shar: End of archive 2 \(of 2\). -cp /dev/null ark2isdone -MISSING="" -for I in 1 2 ; do - if test ! -f ark${I}isdone ; then - MISSING="${MISSING} ${I}" - fi -done -if test "${MISSING}" = "" ; then - echo You have unpacked both archives. - rm -f ark[1-9]isdone -else - echo You still need to unpack the following archives: - echo " " ${MISSING} -fi -## End of shell archive. -exit 0 -- cgit v1.2.1