ast@cs.vu.nl (Andy Tanenbaum) (10/06/88)
: This is a shar archive. Extract with sh, not csh.
: This archive ends with exit, so do not worry about trailing junk.
: --------------------------- cut here --------------------------
PATH=/bin:/usr/bin:/usr/ucb
echo Extracting 'dis.h'
sed 's/^X//' > 'dis.h' << '+ END-OF-FILE ''dis.h'
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 <stdio.h> /* System standard I/O definitions */
X
X/* fcntl.h not used in MINIX */
X/* #include <fcntl.h> /* System file-control definitions */
X
X#include <a.out.h> /* 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
Xextern struct nlist /* Array to hold the symbol table */
X symtab[MAXSYM];
X
Xextern struct reloc /* Array to hold relocation table */
X relo[MAXSYM];
X
Xextern int symptr; /* Index into the symtab[] array */
X
Xextern int relptr; /* Index into the relo[] array */
X
Xstruct 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
Xextern 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
Xextern 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
Xextern void eshand(), /* Bus-escape opcode handler */
X fphand(), /* Floating-point handler */
X inhand(); /* Interrupt-opcode handler */
X
Xextern char *REGS[]; /* Table of register names */
X
Xextern char *REGS0[]; /* Mode 0 register name table */
X
Xextern 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
Xextern int symrank[6][6]; /* Symbol type/rank matrix */
X
Xextern unsigned long PC; /* Current program counter */
X
Xextern int segflg; /* Flag: segment override in effect */
X
Xextern int objflg; /* Flag: output object as a comment */
X
X#define OBJMAX 8 /* Size of the object code buffer */
X
Xextern unsigned char /* Internal buffer for object code */
X objbuf[OBJMAX];
X
Xextern void objini(), /* Object-buffer init routine */
X objout(); /* Object-code output routine */
X
Xextern int objptr; /* Index into the objbuf[] array */
X
Xextern void badseq(); /* Bad-code-sequence function */
X
Xextern char *getnam(); /* Symbol-name string function */
X
Xextern char *lookup(); /* Symbol-table lookup function */
X
Xextern int lookext(); /* Extern-definition lookup routine */
X
Xextern char *mtrans(); /* Interpreter for the mode byte */
X
Xextern void mtrunc(); /* Mode string truncator function */
X
Xextern 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
Xextern char *OPFAM[]; /* Indexed mnemonic family table */
X
Xextern 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
Xextern int close(); /* System file-close primitive */
Xextern int fprintf(); /* Library file-output function */
Xextern long lseek(); /* System file-position primitive */
Xextern int open(); /* System file-open primitive */
Xextern int printf(); /* Library output-format function */
Xextern int read(); /* System file-read primitive */
Xextern int sprintf(); /* Library string-output function */
Xextern char *strcat(); /* Library string-join function */
Xextern char *strcpy(); /* Library string-copy function */
Xextern int strlen(); /* Library string-length function */
X
X /* * * * * * * * * * * END OF dis.h * * * * * * * * * * */
X
X
+ END-OF-FILE dis.h
chmod 'u=rw,g=r,o=r' 'dis.h'
set `wc -c 'dis.h'`
count=$1
case $count in
7600) :;;
*) echo 'Bad character count in ''dis.h' >&2
echo 'Count should be 7600' >&2
esac
echo Extracting 'disfp.c'
sed 's/^X//' > 'disfp.c' << '+ END-OF-FILE ''disfp.c'
Xstatic 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
Xvoid
Xeshand(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
Xvoid
Xfphand(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
Xvoid
Xinhand(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 disfp.c
chmod 'u=rw,g=r,o=r' 'disfp.c'
set `wc -c 'disfp.c'`
count=$1
case $count in
5589) :;;
*) echo 'Bad character count in ''disfp.c' >&2
echo 'Count should be 5589' >&2
esac
echo Extracting 'dishand.c'
sed 's/^X//' > 'dishand.c' << '+ END-OF-FILE ''dishand.c'
Xstatic 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
Xint segflg; /* Segment-override flag */
X
Xunsigned char objbuf[OBJMAX]; /* Buffer for object code */
X
Xint objptr; /* Index into objbuf[] */
X
Xunsigned long PC; /* Current program counter */
X
X /* * * * * * MISCELLANEOUS SUPPORTING ROUTINES * * * * * */
X
X
Xvoid
Xobjini(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
Xvoid
Xobjout() /* 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
Xvoid
Xbadseq(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
Xvoid
Xdfhand(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
Xvoid
Xsbhand(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
Xvoid
Xaohand(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
Xvoid
Xsjhand(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
Xvoid
Ximhand(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
Xvoid
Xmvhand(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
Xvoid
Xmshand(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
Xvoid
Xpohand(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
Xvoid
Xcihand(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
Xvoid
Xmihand(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
Xvoid
Xmqhand(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
Xvoid
Xtqhand(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
Xvoid
Xrehand(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
Xvoid
Xmmhand(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
Xvoid
Xsrhand(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
Xvoid
Xaahand(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
Xvoid
Xiohand(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
Xvoid
Xljhand(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
Xvoid
Xmahand(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
Xvoid
Xmjhand(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 dishand.c
chmod 'u=rw,g=r,o=r' 'dishand.c'
set `wc -c 'dishand.c'`
count=$1
case $count in
25688) :;;
*) echo 'Bad character count in ''dishand.c' >&2
echo 'Count should be 25688' >&2
esac
echo Extracting 'dismain.c'
sed 's/^X//' > 'dismain.c' << '+ END-OF-FILE ''dismain.c'
Xstatic 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
Xextern char *release; /* Contains release string */
X
Xstatic char *IFILE = NULL; /* Points to input file name */
X
Xstatic char *OFILE = NULL; /* Points to output file name */
X
Xstatic char *PRG; /* Name of invoking program */
X
Xstatic unsigned long zcount; /* Consecutive "0" byte count */
X
Xint objflg = 0; /* Flag: output object bytes */
X
X#define unix 1
X#define i8086 1
X#define ibmpc 1
X
X#if unix && i8086 && ibmpc /* Set the CPU identifier */
Xstatic int cpuid = 1;
X#else
Xstatic int cpuid = 0;
X#endif
X
X /* * * * * * * MISCELLANEOUS UTILITY FUNCTIONS * * * * * * */
X
Xstatic void
Xusage(s)
X register char *s;
X{
X fprintf(stderr,"Usage: %s [-o] ifile [ofile]\n",s);
X exit(-1);
X}
X
Xstatic void
Xfatal(s,t)
X register char *s, *t;
X{
X fprintf(stderr,"\07%s: %s\n",s,t);
X exit(-1);
X}
X
Xstatic void
Xzdump(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
Xstatic char *
Xinvoker(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
Xstatic int
Xobjdump(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
Xstatic char *
Xgetlab(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
Xstatic void
Xprolog()
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
Xstatic void
Xdistext()
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
Xstatic void
Xdisdata()
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
Xstatic void
Xdisbss()
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
Xvoid
Xmain(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,0)) < 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 = 0L;
X HDR.a_tbase = HDR.a_dbase = 0L;
X/* AST emergency patch
X HDR.a_lnums = HDR.a_toffs = 0L;
X*/
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 dismain.c
chmod 'u=rw,g=r,o=r' 'dismain.c'
set `wc -c 'dismain.c'`
count=$1
case $count in
17458) :;;
*) echo 'Bad character count in ''dismain.c' >&2
echo 'Count should be 17458' >&2
esac
exit 0