summaryrefslogtreecommitdiff
path: root/dis88
diff options
context:
space:
mode:
authorRobert de Bath <rdebath@poboxes.com>1996-03-24 17:45:55 +0100
committerLubomir Rintel <lkundrak@v3.sk>2013-10-23 23:29:43 +0200
commitfe22c37817ce338fbbc90b239320248c270957fa (patch)
treed9550410c4a20bdd382fcc58d2d3d7c5e04e5245 /dis88
parenta7aba15e8efffb1c5d3097656f1a93955a64f01f (diff)
parent42192453ea219b80d0bf9f41e51e36d3d4d0740b (diff)
downloaddev86-fe22c37817ce338fbbc90b239320248c270957fa.tar.gz
Import Dev86-0.0.4.tar.gzv0.0.4
Diffstat (limited to 'dis88')
-rw-r--r--dis88/Makefile51
-rw-r--r--dis88/README90
l---------dis88/a.out.h1
-rw-r--r--dis88/ansi.h58
-rw-r--r--dis88/dis.h170
-rw-r--r--dis88/dis88.1147
-rw-r--r--dis88/disfp.c157
-rw-r--r--dis88/dishand.c1049
-rw-r--r--dis88/dismain.c650
-rw-r--r--dis88/disrel.c30
-rw-r--r--dis88/distabs.c708
-rw-r--r--dis88/old_a.out.h117
12 files changed, 3228 insertions, 0 deletions
diff --git a/dis88/Makefile b/dis88/Makefile
new file mode 100644
index 0000000..692326f
--- /dev/null
+++ b/dis88/Makefile
@@ -0,0 +1,51 @@
+# Makefile for dis
+
+# @(#) 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.
+
+CC=bcc
+CFLAGS=-O
+LDFLAGS=
+
+OBJ = disrel.o dismain.o distabs.o dishand.o disfp.o
+
+all: dis88
+
+dis88: $(OBJ)
+ $(CC) $(LDFLAGS) -o dis88 $(OBJ)
+
+install: /usr/bin/dis88
+
+/usr/bin/dis88: dis88
+ install -cs -o bin dis88 $@
+
+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
+
+
+clean:
+ rm -f *.bak *.o core dis88
diff --git a/dis88/README b/dis88/README
new file mode 100644
index 0000000..efc5ad9
--- /dev/null
+++ b/dis88/README
@@ -0,0 +1,90 @@
+ 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/dis88/a.out.h b/dis88/a.out.h
new file mode 120000
index 0000000..ccbf4b5
--- /dev/null
+++ b/dis88/a.out.h
@@ -0,0 +1 @@
+../libc/include/a.out.h \ No newline at end of file
diff --git a/dis88/ansi.h b/dis88/ansi.h
new file mode 100644
index 0000000..825b4a6
--- /dev/null
+++ b/dis88/ansi.h
@@ -0,0 +1,58 @@
+/* The <ansi.h> header attempts to decide whether the compiler has enough
+ * conformance to Standard C for Minix to take advantage of. If so, the
+ * symbol _ANSI is defined (as 31415). Otherwise _ANSI is not defined
+ * here, but it may be defined by applications that want to bend the rules.
+ * The magic number in the definition is to inhibit unnecessary bending
+ * of the rules. (For consistency with the new '#ifdef _ANSI" tests in
+ * the headers, _ANSI should really be defined as nothing, but that would
+ * break many library routines that use "#if _ANSI".)
+
+ * If _ANSI ends up being defined, a macro
+ *
+ * _PROTOTYPE(function, params)
+ *
+ * is defined. This macro expands in different ways, generating either
+ * ANSI Standard C prototypes or old-style K&R (Kernighan & Ritchie)
+ * prototypes, as needed. Finally, some programs use _CONST, _VOIDSTAR etc
+ * in such a way that they are portable over both ANSI and K&R compilers.
+ * The appropriate macros are defined here.
+ */
+
+#ifndef _ANSI_H
+#define _ANSI_H
+
+#if __STDC__ == 1
+#define _ANSI 31459 /* compiler claims full ANSI conformance */
+#endif
+
+#ifdef __GNUC__
+#define _ANSI 31459 /* gcc conforms enough even in non-ANSI mode */
+#endif
+
+#ifdef _ANSI
+
+/* Keep everything for ANSI prototypes. */
+#define _PROTOTYPE(function, params) function params
+#define _ARGS(params) params
+
+#define _VOIDSTAR void *
+#define _VOID void
+#define _CONST const
+#define _VOLATILE volatile
+#define _SIZET size_t
+
+#else
+
+/* Throw away the parameters for K&R prototypes. */
+#define _PROTOTYPE(function, params) function()
+#define _ARGS(params) ()
+
+#define _VOIDSTAR void *
+#define _VOID void
+#define _CONST
+#define _VOLATILE
+#define _SIZET int
+
+#endif /* _ANSI */
+
+#endif /* ANSI_H */
diff --git a/dis88/dis.h b/dis88/dis.h
new file mode 100644
index 0000000..7815e06
--- /dev/null
+++ b/dis88/dis.h
@@ -0,0 +1,170 @@
+ /*
+ ** @(#) 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 <sys/types.h>
+#include <fcntl.h> /* System file-control definitions */
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h> /* System standard I/O definitions */
+#include "a.out.h" /* Object file format definitions */
+#include "ansi.h"
+
+#define MAXSYM 800 /* 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];
+
+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 int objptr; /* Index into the objbuf[] array */
+
+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 */
+static int _F_;
+#define FETCH(p) (p)=_F_ = Fetch(); if(_F_<0) {printf("???\n"); return; }
+
+
+/* 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/dis88.1 b/dis88/dis88.1
new file mode 100644
index 0000000..c991ad7
--- /dev/null
+++ b/dis88/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/dis88/disfp.c b/dis88/disfp.c
new file mode 100644
index 0000000..c6dc0da
--- /dev/null
+++ b/dis88/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/dis88/dishand.c b/dis88/dishand.c
new file mode 100644
index 0000000..5983972
--- /dev/null
+++ b/dis88/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[80];
+
+ 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[80];
+
+ 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[80];
+
+ 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[80];
+
+ 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[80];
+
+ 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/dis88/dismain.c b/dis88/dismain.c
new file mode 100644
index 0000000..f9ec6c5
--- /dev/null
+++ b/dis88/dismain.c
@@ -0,0 +1,650 @@
+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 */
+
+#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,"Usage: %s [-o] ifile [ofile]\n",s);
+ exit(-1);
+}
+
+static void
+fatal(s,t)
+ register char *s, *t;
+{
+ fprintf(stderr,"%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;
+{
+ 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[48], c[32];
+
+ 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;
+
+ fflush(stdout);
+
+ 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');
+ fflush(stdout);
+
+ 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');
+ fflush(stdout);
+
+ 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');
+ fflush(stdout);
+
+}/* * * * * * * * * * * 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);
+ fflush(stdout);
+
+ 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);
+ fflush(stdout);
+ }
+
+}/* * * * * * * * * * END OF distext() * * * * * * * * * */
+
+Fetch()
+{
+ int p;
+ ++PC;
+ if( symptr>=0 && getlab(N_TEXT) != NULL ) { --PC; return -1; }
+
+/* #define FETCH(p) ++PC; p = getchar() & 0xff; objbuf[objptr++] = p */
+ p = getchar() & 0xff;
+ objbuf[objptr++] = p;
+ return p;
+}
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * *
+ * 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,0)) < 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,"%s: warning: host/cpu clash\n",PRG);
+
+ read(fd, (char *) &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 = 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
+ + (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, (char *) &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, (char *) &symtab[symptr],sizeof(struct nlist));
+ symptr--;
+ }
+ else
+ fprintf(stderr,"%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/dis88/disrel.c b/dis88/disrel.c
new file mode 100644
index 0000000..37f3221
--- /dev/null
+++ b/dis88/disrel.c
@@ -0,0 +1,30 @@
+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 (MINIX)";
+
+ /*
+ **
+ ** 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.
+ **
+ ** JUN 88:
+ ** Ported to MINIX
+ */
+
diff --git a/dis88/distabs.c b/dis88/distabs.c
new file mode 100644
index 0000000..283fe42
--- /dev/null
+++ b/dis88/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[sizeof(symtab->n_name)+1];
+
+ for (j = 0; j < sizeof(symtab[k].n_name); ++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[32];
+
+ 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[80];
+
+ 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/dis88/old_a.out.h b/dis88/old_a.out.h
new file mode 100644
index 0000000..1a36dfb
--- /dev/null
+++ b/dis88/old_a.out.h
@@ -0,0 +1,117 @@
+/* The <a.out> header file describes the format of executable files. */
+
+#ifndef _AOUT_H
+#define _AOUT_H
+
+struct exec { /* a.out header */
+ unsigned char a_magic[2]; /* magic number */
+ unsigned char a_flags; /* flags, see below */
+ unsigned char a_cpu; /* cpu id */
+ unsigned char a_hdrlen; /* length of header */
+ unsigned char a_unused; /* reserved for future use */
+ unsigned short a_version; /* version stamp (not used at present) */
+ long a_text; /* size of text segement in bytes */
+ long a_data; /* size of data segment in bytes */
+ long a_bss; /* size of bss segment in bytes */
+ long a_entry; /* entry point */
+ long a_total; /* total memory allocated */
+ long a_syms; /* size of symbol table */
+
+ /* SHORT FORM ENDS HERE */
+ long a_trsize; /* text relocation size */
+ long a_drsize; /* data relocation size */
+ long a_tbase; /* text relocation base */
+ long a_dbase; /* data relocation base */
+};
+
+#define A_MAGIC0 (unsigned char) 0x01
+#define A_MAGIC1 (unsigned char) 0x03
+#define BADMAG(X) ((X).a_magic[0] != A_MAGIC0 ||(X).a_magic[1] != A_MAGIC1)
+
+/* CPU Id of TARGET machine (byte order coded in low order two bits) */
+#define A_NONE 0x00 /* unknown */
+#define A_I8086 0x04 /* intel i8086/8088 */
+#define A_M68K 0x0B /* motorola m68000 */
+#define A_NS16K 0x0C /* national semiconductor 16032 */
+#define A_I80386 0x10 /* intel i80386 */
+#define A_SPARC 0x17 /* Sun SPARC */
+
+#define A_BLR(cputype) ((cputype&0x01)!=0) /* TRUE if bytes left-to-right */
+#define A_WLR(cputype) ((cputype&0x02)!=0) /* TRUE if words left-to-right */
+
+/* Flags. */
+#define A_UZP 0x01 /* unmapped zero page (pages) */
+#define A_PAL 0x02 /* page aligned executable */
+#define A_NSYM 0x04 /* new style symbol table */
+#define A_EXEC 0x10 /* executable */
+#define A_SEP 0x20 /* separate I/D */
+#define A_PURE 0x40 /* pure text */ /* not used */
+#define A_TOVLY 0x80 /* text overlay */ /* not used */
+
+/* Offsets of various things. */
+#define A_MINHDR 32
+#define A_TEXTPOS(X) ((long)(X).a_hdrlen)
+#define A_DATAPOS(X) (A_TEXTPOS(X) + (X).a_text)
+#define A_HASRELS(X) ((X).a_hdrlen > (unsigned char) A_MINHDR)
+#define A_HASEXT(X) ((X).a_hdrlen > (unsigned char) (A_MINHDR + 8))
+#define A_HASLNS(X) ((X).a_hdrlen > (unsigned char) (A_MINHDR + 16))
+#define A_HASTOFF(X) ((X).a_hdrlen > (unsigned char) (A_MINHDR + 24))
+#define A_TRELPOS(X) (A_DATAPOS(X) + (X).a_data)
+#define A_DRELPOS(X) (A_TRELPOS(X) + (X).a_trsize)
+#define A_SYMPOS(X) (A_TRELPOS(X) + (A_HASRELS(X) ? \
+ ((X).a_trsize + (X).a_drsize) : 0))
+
+struct reloc {
+ long r_vaddr; /* virtual address of reference */
+ unsigned short r_symndx; /* internal segnum or extern symbol num */
+ unsigned short r_type; /* relocation type */
+};
+
+/* r_tyep values: */
+#define R_ABBS 0
+#define R_RELLBYTE 2
+#define R_PCRBYTE 3
+#define R_RELWORD 4
+#define R_PCRWORD 5
+#define R_RELLONG 6
+#define R_PCRLONG 7
+#define R_REL3BYTE 8
+#define R_KBRANCHE 9
+
+/* r_symndx for internal segments */
+#define S_ABS ((unsigned short)-1)
+#define S_TEXT ((unsigned short)-2)
+#define S_DATA ((unsigned short)-3)
+#define S_BSS ((unsigned short)-4)
+
+struct nlist { /* symbol table entry */
+ char n_name[8]; /* symbol name */
+ long n_value; /* value */
+ unsigned char n_sclass; /* storage class */
+ unsigned char n_numaux; /* number of auxiliary entries (not used) */
+ unsigned short n_type; /* language base and derived type (not used) */
+};
+
+/* Low bits of storage class (section). */
+#define N_SECT 07 /* section mask */
+#define N_UNDF 00 /* undefined */
+#define N_ABS 01 /* absolute */
+#define N_TEXT 02 /* text */
+#define N_DATA 03 /* data */
+#define N_BSS 04 /* bss */
+#define N_COMM 05 /* (common) */
+
+/* High bits of storage class. */
+#define N_CLASS 0370 /* storage class mask */
+#define C_NULL
+#define C_EXT 0020 /* external symbol */
+#define C_STAT 0030 /* static */
+
+/* Function prototypes. */
+#ifndef _ANSI_H
+#include "ansi.h"
+#endif
+
+_PROTOTYPE( int nlist, (char *_file, struct nlist *_nl) );
+
+#endif /* _AOUT_H */