[comp.os.minix] Disassembler for MINIX, part 2 of 2

ast@cs.vu.nl (Andy Tanenbaum) (06/11/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 'distabs.c'
sed 's/^X//' > 'distabs.c' << '+ END-OF-FILE ''distabs.c'
Xstatic char *sccsid =
X   "@(#) distabs.c, Ver. 2.1 created 00:00:00 87/09/01";
X
X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
X  *                                                         *
X  *  Copyright (C) 1987 G. M. Harding, all rights reserved  *
X  *                                                         *
X  * Permission to copy and  redistribute is hereby granted, *
X  * provided full source code,  with all copyright notices, *
X  * accompanies any redistribution.                         *
X  *                                                         *
X  * This file  contains  the  lookup  tables and other data *
X  * structures for the Intel 8088 symbolic disassembler. It *
X  * also contains a few global  routines  which  facilitate *
X  * access to the tables,  for use primarily by the handler *
X  * functions.                                              *
X  *                                                         *
X  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
X
X#include "dis.h"              /* Disassembler declarations  */
X
Xstruct exec HDR;              /* Used to hold header info   */
X
Xstruct nlist symtab[MAXSYM];  /* Array of symbol table info */
X
Xstruct reloc relo[MAXSYM];    /* Array of relocation info   */
X
Xint symptr = -1,              /* Index into symtab[]        */
X    relptr = -1;              /* Index into relo[]          */
X
Xchar *REGS[] =                /* Table of register names    */
X   {
X   "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh",
X   "ax", "cx", "dx", "bx", "sp", "bp", "si", "di",
X   "es", "cs", "ss", "ds"
X   };
X
Xchar *REGS0[] =               /* Mode 0 register name table */
X   {
X   "bx_si", "bx_di", "bp_si", "bp_di", "si", "di", "", "bx"
X   };
X
Xchar *REGS1[] =               /* Mode 1 register name table */
X   {
X   "bx_si", "bx_di", "bp_si", "bp_di", "si", "di", "bp", "bx"
X   };
X
Xint symrank[6][6] =           /* Symbol type/rank matrix    */
X   {
X              /* UND  ABS  TXT  DAT  BSS  COM */
X   /* UND */      5,   4,   1,   2,   3,   0,
X   /* ABS */      1,   5,   4,   3,   2,   0,
X   /* TXT */      4,   1,   5,   3,   2,   0,
X   /* DAT */      3,   1,   2,   5,   4,   0,
X   /* BSS */      3,   1,   2,   4,   5,   0,
X   /* COM */      2,   0,   1,   3,   4,   5
X   };
X
X /* * * * * * * * * * * * OPCODE DATA * * * * * * * * * * * */
X
Xchar ADD[]   = "\tadd",             /* Mnemonics by family  */
X     OR[]    = "\tor",
X     ADC[]   = "\tadc",
X     SBB[]   = "\tsbb",
X     AND[]   = "\tand",
X     SUB[]   = "\tsub",
X     XOR[]   = "\txor",
X     CMP[]   = "\tcmp",
X     NOT[]   = "\tnot",
X     NEG[]   = "\tneg",
X     MUL[]   = "\tmul",
X     DIV[]   = "\tdiv",
X     MOV[]   = "\tmov",
X     ESC[]   = "\tesc",
X     TEST[]  = "\ttest",
X     AMBIG[] = "",
X     ROL[]   = "\trol",
X     ROR[]   = "\tror",
X     RCL[]   = "\trcl",
X     RCR[]   = "\trcr",
X     SAL[]   = "\tsal",
X     SHR[]   = "\tshr",
X     SHL[]   = "\tshl",
X     SAR[]   = "\tsar";
X
Xchar *OPFAM[] =                     /* Family lookup table  */
X   {
X   ADD, OR, ADC, SBB, AND, SUB, XOR, CMP,
X   NOT, NEG, MUL, DIV, MOV, ESC, TEST, AMBIG,
X   ROL, ROR, RCL, RCR, SAL, SHR, SHL, SAR
X   };
X
Xstruct opcode optab[] =             /* Table of opcode data */
X   {
X   ADD,              aohand,  2,    4,             /* 0x00  */
X   ADD,              aohand,  2,    4,             /* 0x01  */
X   ADD,              aohand,  2,    4,             /* 0x02  */
X   ADD,              aohand,  2,    4,             /* 0x03  */
X   ADD,              aohand,  2,    2,             /* 0x04  */
X   ADD,              aohand,  3,    3,             /* 0x05  */
X   "\tpush\tes",     sbhand,  1,    1,             /* 0x06  */
X   "\tpop\tes",      sbhand,  1,    1,             /* 0x07  */
X   OR,               aohand,  2,    4,             /* 0x08  */
X   OR,               aohand,  2,    4,             /* 0x09  */
X   OR,               aohand,  2,    4,             /* 0x0a  */
X   OR,               aohand,  2,    4,             /* 0x0b  */
X   OR,               aohand,  2,    2,             /* 0x0c  */
X   OR,               aohand,  3,    3,             /* 0x0d  */
X   "\tpush\tcs",     sbhand,  1,    1,             /* 0x0e  */
X   NULL,             dfhand,  0,    0,             /* 0x0f  */
X   ADC,              aohand,  2,    4,             /* 0x10  */
X   ADC,              aohand,  2,    4,             /* 0x11  */
X   ADC,              aohand,  2,    4,             /* 0x12  */
X   ADC,              aohand,  2,    4,             /* 0x13  */
X   ADC,              aohand,  2,    2,             /* 0x14  */
X   ADC,              aohand,  3,    3,             /* 0x15  */
X   "\tpush\tss",     sbhand,  1,    1,             /* 0x16  */
X   "\tpop\tss",      sbhand,  1,    1,             /* 0x17  */
X   SBB,              aohand,  2,    4,             /* 0x18  */
X   SBB,              aohand,  2,    4,             /* 0x19  */
X   SBB,              aohand,  2,    4,             /* 0x1a  */
X   SBB,              aohand,  2,    4,             /* 0x1b  */
X   SBB,              aohand,  2,    2,             /* 0x1c  */
X   SBB,              aohand,  3,    3,             /* 0x1d  */
X   "\tpush\tds",     sbhand,  1,    1,             /* 0x1e  */
X   "\tpop\tds",      sbhand,  1,    1,             /* 0x1f  */
X   AND,              aohand,  2,    4,             /* 0x20  */
X   AND,              aohand,  2,    4,             /* 0x21  */
X   AND,              aohand,  2,    4,             /* 0x22  */
X   AND,              aohand,  2,    4,             /* 0x23  */
X   AND,              aohand,  2,    2,             /* 0x24  */
X   AND,              aohand,  3,    3,             /* 0x25  */
X   "\tseg\tes",      sbhand,  1,    1,             /* 0x26  */
X   "\tdaa",          sbhand,  1,    1,             /* 0x27  */
X   SUB,              aohand,  2,    4,             /* 0x28  */
X   SUB,              aohand,  2,    4,             /* 0x29  */
X   SUB,              aohand,  2,    4,             /* 0x2a  */
X   SUB,              aohand,  2,    4,             /* 0x2b  */
X   SUB,              aohand,  2,    2,             /* 0x2c  */
X   SUB,              aohand,  3,    3,             /* 0x2d  */
X   "\tseg\tcs",      sbhand,  1,    1,             /* 0x2e  */
X   "\tdas",          sbhand,  1,    1,             /* 0x2f  */
X   XOR,              aohand,  2,    4,             /* 0x30  */
X   XOR,              aohand,  2,    4,             /* 0x31  */
X   XOR,              aohand,  2,    4,             /* 0x32  */
X   XOR,              aohand,  2,    4,             /* 0x33  */
X   XOR,              aohand,  2,    2,             /* 0x34  */
X   XOR,              aohand,  3,    3,             /* 0x35  */
X   "\tseg\tss",      sbhand,  1,    1,             /* 0x36  */
X   "\taaa",          sbhand,  1,    1,             /* 0x37  */
X   CMP,              aohand,  2,    4,             /* 0x38  */
X   CMP,              aohand,  2,    4,             /* 0x39  */
X   CMP,              aohand,  2,    4,             /* 0x3a  */
X   CMP,              aohand,  2,    4,             /* 0x3b  */
X   CMP,              aohand,  2,    2,             /* 0x3c  */
X   CMP,              aohand,  3,    3,             /* 0x3d  */
X   "\tseg\tds",      sbhand,  1,    1,             /* 0x3e  */
X   "\taas",          sbhand,  1,    1,             /* 0x3f  */
X   "\tinc\tax",      sbhand,  1,    1,             /* 0x40  */
X   "\tinc\tcx",      sbhand,  1,    1,             /* 0x41  */
X   "\tinc\tdx",      sbhand,  1,    1,             /* 0x42  */
X   "\tinc\tbx",      sbhand,  1,    1,             /* 0x43  */
X   "\tinc\tsp",      sbhand,  1,    1,             /* 0x44  */
X   "\tinc\tbp",      sbhand,  1,    1,             /* 0x45  */
X   "\tinc\tsi",      sbhand,  1,    1,             /* 0x46  */
X   "\tinc\tdi",      sbhand,  1,    1,             /* 0x47  */
X   "\tdec\tax",      sbhand,  1,    1,             /* 0x48  */
X   "\tdec\tcx",      sbhand,  1,    1,             /* 0x49  */
X   "\tdec\tdx",      sbhand,  1,    1,             /* 0x4a  */
X   "\tdec\tbx",      sbhand,  1,    1,             /* 0x4b  */
X   "\tdec\tsp",      sbhand,  1,    1,             /* 0x4c  */
X   "\tdec\tbp",      sbhand,  1,    1,             /* 0x4d  */
X   "\tdec\tsi",      sbhand,  1,    1,             /* 0x4e  */
X   "\tdec\tdi",      sbhand,  1,    1,             /* 0x4f  */
X   "\tpush\tax",     sbhand,  1,    1,             /* 0x50  */
X   "\tpush\tcx",     sbhand,  1,    1,             /* 0x51  */
X   "\tpush\tdx",     sbhand,  1,    1,             /* 0x52  */
X   "\tpush\tbx",     sbhand,  1,    1,             /* 0x53  */
X   "\tpush\tsp",     sbhand,  1,    1,             /* 0x54  */
X   "\tpush\tbp",     sbhand,  1,    1,             /* 0x55  */
X   "\tpush\tsi",     sbhand,  1,    1,             /* 0x56  */
X   "\tpush\tdi",     sbhand,  1,    1,             /* 0x57  */
X   "\tpop\tax",      sbhand,  1,    1,             /* 0x58  */
X   "\tpop\tcx",      sbhand,  1,    1,             /* 0x59  */
X   "\tpop\tdx",      sbhand,  1,    1,             /* 0x5a  */
X   "\tpop\tbx",      sbhand,  1,    1,             /* 0x5b  */
X   "\tpop\tsp",      sbhand,  1,    1,             /* 0x5c  */
X   "\tpop\tbp",      sbhand,  1,    1,             /* 0x5d  */
X   "\tpop\tsi",      sbhand,  1,    1,             /* 0x5e  */
X   "\tpop\tdi",      sbhand,  1,    1,             /* 0x5f  */
X   NULL,             dfhand,  0,    0,             /* 0x60  */
X   NULL,             dfhand,  0,    0,             /* 0x61  */
X   NULL,             dfhand,  0,    0,             /* 0x62  */
X   NULL,             dfhand,  0,    0,             /* 0x63  */
X   NULL,             dfhand,  0,    0,             /* 0x64  */
X   NULL,             dfhand,  0,    0,             /* 0x65  */
X   NULL,             dfhand,  0,    0,             /* 0x66  */
X   NULL,             dfhand,  0,    0,             /* 0x67  */
X   NULL,             dfhand,  0,    0,             /* 0x68  */
X   NULL,             dfhand,  0,    0,             /* 0x69  */
X   NULL,             dfhand,  0,    0,             /* 0x6a  */
X   NULL,             dfhand,  0,    0,             /* 0x6b  */
X   NULL,             dfhand,  0,    0,             /* 0x6c  */
X   NULL,             dfhand,  0,    0,             /* 0x6d  */
X   NULL,             dfhand,  0,    0,             /* 0x6e  */
X   NULL,             dfhand,  0,    0,             /* 0x6f  */
X   "\tjo",           sjhand,  2,    2,             /* 0x70  */
X   "\tjno",          sjhand,  2,    2,             /* 0x71  */
X   "\tjc",           sjhand,  2,    2,             /* 0x72  */
X   "\tjnc",          sjhand,  2,    2,             /* 0x73  */
X   "\tjz",           sjhand,  2,    2,             /* 0x74  */
X   "\tjnz",          sjhand,  2,    2,             /* 0x75  */
X   "\tjna",          sjhand,  2,    2,             /* 0x76  */
X   "\tja",           sjhand,  2,    2,             /* 0x77  */
X   "\tjs",           sjhand,  2,    2,             /* 0x78  */
X   "\tjns",          sjhand,  2,    2,             /* 0x79  */
X   "\tjp",           sjhand,  2,    2,             /* 0x7a  */
X   "\tjnp",          sjhand,  2,    2,             /* 0x7b  */
X   "\tjl",           sjhand,  2,    2,             /* 0x7c  */
X   "\tjnl",          sjhand,  2,    2,             /* 0x7d  */
X   "\tjng",          sjhand,  2,    2,             /* 0x7e  */
X   "\tjg",           sjhand,  2,    2,             /* 0x7f  */
X   AMBIG,            imhand,  3,    5,             /* 0x80  */
X   AMBIG,            imhand,  4,    6,             /* 0x81  */
X   AMBIG,            imhand,  3,    5,             /* 0x82  */
X   AMBIG,            imhand,  3,    5,             /* 0x83  */
X   TEST,             mvhand,  2,    4,             /* 0x84  */
X   TEST,             mvhand,  2,    4,             /* 0x85  */
X   "\txchg",         mvhand,  2,    4,             /* 0x86  */
X   "\txchg",         mvhand,  2,    4,             /* 0x87  */
X   MOV,              mvhand,  2,    4,             /* 0x88  */
X   MOV,              mvhand,  2,    4,             /* 0x89  */
X   MOV,              mvhand,  2,    4,             /* 0x8a  */
X   MOV,              mvhand,  2,    4,             /* 0x8b  */
X   MOV,              mshand,  2,    4,             /* 0x8c  */
X   "\tlea",          mvhand,  2,    4,             /* 0x8d  */
X   MOV,              mshand,  2,    4,             /* 0x8e  */
X   "\tpop",          pohand,  2,    4,             /* 0x8f  */
X   "\tnop",          sbhand,  1,    1,             /* 0x90  */
X   "\txchg\tax,cx",  sbhand,  1,    1,             /* 0x91  */
X   "\txchg\tax,dx",  sbhand,  1,    1,             /* 0x92  */
X   "\txchg\tax,bx",  sbhand,  1,    1,             /* 0x93  */
X   "\txchg\tax,sp",  sbhand,  1,    1,             /* 0x94  */
X   "\txchg\tax,bp",  sbhand,  1,    1,             /* 0x95  */
X   "\txchg\tax,si",  sbhand,  1,    1,             /* 0x96  */
X   "\txchg\tax,di",  sbhand,  1,    1,             /* 0x97  */
X   "\tcbw",          sbhand,  1,    1,             /* 0x98  */
X   "\tcwd",          sbhand,  1,    1,             /* 0x99  */
X   "\tcalli",        cihand,  5,    5,             /* 0x9a  */
X   "\twait",         sbhand,  1,    1,             /* 0x9b  */
X   "\tpushf",        sbhand,  1,    1,             /* 0x9c  */
X   "\tpopf",         sbhand,  1,    1,             /* 0x9d  */
X   "\tsahf",         sbhand,  1,    1,             /* 0x9e  */
X   "\tlahf",         sbhand,  1,    1,             /* 0x9f  */
X   MOV,              mqhand,  3,    3,             /* 0xa0  */
X   MOV,              mqhand,  3,    3,             /* 0xa1  */
X   MOV,              mqhand,  3,    3,             /* 0xa2  */
X   MOV,              mqhand,  3,    3,             /* 0xa3  */
X   "\tmovb",         sbhand,  1,    1,             /* 0xa4  */
X   "\tmovw",         sbhand,  1,    1,             /* 0xa5  */
X   "\tcmpb",         sbhand,  1,    1,             /* 0xa6  */
X   "\tcmpw",         sbhand,  1,    1,             /* 0xa7  */
X   TEST,             tqhand,  2,    2,             /* 0xa8  */
X   TEST,             tqhand,  3,    3,             /* 0xa9  */
X   "\tstob",         sbhand,  1,    1,             /* 0xaa  */
X   "\tstow",         sbhand,  1,    1,             /* 0xab  */
X   "\tlodb",         sbhand,  1,    1,             /* 0xac  */
X   "\tlodw",         sbhand,  1,    1,             /* 0xad  */
X   "\tscab",         sbhand,  1,    1,             /* 0xae  */
X   "\tscaw",         sbhand,  1,    1,             /* 0xaf  */
X   "\tmov\tal,",     mihand,  2,    2,             /* 0xb0  */
X   "\tmov\tcl,",     mihand,  2,    2,             /* 0xb1  */
X   "\tmov\tdl,",     mihand,  2,    2,             /* 0xb2  */
X   "\tmov\tbl,",     mihand,  2,    2,             /* 0xb3  */
X   "\tmov\tah,",     mihand,  2,    2,             /* 0xb4  */
X   "\tmov\tch,",     mihand,  2,    2,             /* 0xb5  */
X   "\tmov\tdh,",     mihand,  2,    2,             /* 0xb6  */
X   "\tmov\tbh,",     mihand,  2,    2,             /* 0xb7  */
X   "\tmov\tax,",     mihand,  3,    3,             /* 0xb8  */
X   "\tmov\tcx,",     mihand,  3,    3,             /* 0xb9  */
X   "\tmov\tdx,",     mihand,  3,    3,             /* 0xba  */
X   "\tmov\tbx,",     mihand,  3,    3,             /* 0xbb  */
X   "\tmov\tsp,",     mihand,  3,    3,             /* 0xbc  */
X   "\tmov\tbp,",     mihand,  3,    3,             /* 0xbd  */
X   "\tmov\tsi,",     mihand,  3,    3,             /* 0xbe  */
X   "\tmov\tdi,",     mihand,  3,    3,             /* 0xbf  */
X   NULL,             dfhand,  0,    0,             /* 0xc0  */
X   NULL,             dfhand,  0,    0,             /* 0xc1  */
X   "\tret",          rehand,  3,    3,             /* 0xc2  */
X   "\tret",          sbhand,  1,    1,             /* 0xc3  */
X   "\tles",          mvhand,  2,    4,             /* 0xc4  */
X   "\tlds",          mvhand,  2,    4,             /* 0xc5  */
X   MOV,              mmhand,  3,    5,             /* 0xc6  */
X   MOV,              mmhand,  4,    6,             /* 0xc7  */
X   NULL,             dfhand,  0,    0,             /* 0xc8  */
X   NULL,             dfhand,  0,    0,             /* 0xc9  */
X   "\treti",         rehand,  3,    3,             /* 0xca  */
X   "\treti",         sbhand,  1,    1,             /* 0xcb  */
X   "\tint",          sbhand,  1,    1,             /* 0xcc  */
X   "\tint",          inhand,  2,    2,             /* 0xcd  */
X   "\tinto",         sbhand,  1,    1,             /* 0xce  */
X   "\tiret",         sbhand,  1,    1,             /* 0xcf  */
X   AMBIG,            srhand,  2,    4,             /* 0xd0  */
X   AMBIG,            srhand,  2,    4,             /* 0xd1  */
X   AMBIG,            srhand,  2,    4,             /* 0xd2  */
X   AMBIG,            srhand,  2,    4,             /* 0xd3  */
X   "\taam",          aahand,  2,    2,             /* 0xd4  */
X   "\taad",          aahand,  2,    2,             /* 0xd5  */
X   NULL,             dfhand,  0,    0,             /* 0xd6  */
X   "\txlat",         sbhand,  1,    1,             /* 0xd7  */
X   ESC,              eshand,  2,    2,             /* 0xd8  */
X   ESC,              eshand,  2,    2,             /* 0xd9  */
X   ESC,              eshand,  2,    2,             /* 0xda  */
X   ESC,              eshand,  2,    2,             /* 0xdb  */
X   ESC,              eshand,  2,    2,             /* 0xdc  */
X   ESC,              eshand,  2,    2,             /* 0xdd  */
X   ESC,              eshand,  2,    2,             /* 0xde  */
X   ESC,              eshand,  2,    2,             /* 0xdf  */
X   "\tloopne",       sjhand,  2,    2,             /* 0xe0  */
X   "\tloope",        sjhand,  2,    2,             /* 0xe1  */
X   "\tloop",         sjhand,  2,    2,             /* 0xe2  */
X   "\tjcxz",         sjhand,  2,    2,             /* 0xe3  */
X   "\tin",           iohand,  2,    2,             /* 0xe4  */
X   "\tinw",          iohand,  2,    2,             /* 0xe5  */
X   "\tout",          iohand,  2,    2,             /* 0xe6  */
X   "\toutw",         iohand,  2,    2,             /* 0xe7  */
X   "\tcall",         ljhand,  3,    3,             /* 0xe8  */
X   "\tjmp",          ljhand,  3,    3,             /* 0xe9  */
X   "\tjmpi",         cihand,  5,    5,             /* 0xea  */
X   "\tj",            sjhand,  2,    2,             /* 0xeb  */
X   "\tin",           sbhand,  1,    1,             /* 0xec  */
X   "\tinw",          sbhand,  1,    1,             /* 0xed  */
X   "\tout",          sbhand,  1,    1,             /* 0xee  */
X   "\toutw",         sbhand,  1,    1,             /* 0xef  */
X   "\tlock",         sbhand,  1,    1,             /* 0xf0  */
X   NULL,             dfhand,  0,    0,             /* 0xf1  */
X   "\trepnz",        sbhand,  1,    1,             /* 0xf2  */
X   "\trepz",         sbhand,  1,    1,             /* 0xf3  */
X   "\thlt",          sbhand,  1,    1,             /* 0xf4  */
X   "\tcmc",          sbhand,  1,    1,             /* 0xf5  */
X   AMBIG,            mahand,  2,    5,             /* 0xf6  */
X   AMBIG,            mahand,  2,    6,             /* 0xf7  */
X   "\tclc",          sbhand,  1,    1,             /* 0xf8  */
X   "\tstc",          sbhand,  1,    1,             /* 0xf9  */
X   "\tcli",          sbhand,  1,    1,             /* 0xfa  */
X   "\tsti",          sbhand,  1,    1,             /* 0xfb  */
X   "\tcld",          sbhand,  1,    1,             /* 0xfc  */
X   "\tstd",          sbhand,  1,    1,             /* 0xfd  */
X   AMBIG,            mjhand,  2,    4,             /* 0xfe  */
X   AMBIG,            mjhand,  2,    4              /* 0xff  */
X   };
X
X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
X  *                                                         *
X  * This simple routine  returns the name field of a symbol *
X  * table entry as a printable string.                      *
X  *                                                         *
X  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
X
Xchar *
Xgetnam(k)
X
X   register int k;
X
X{/* * * * * * * * * *  START OF getnam()  * * * * * * * * * */
X
X   register int j;
X   static char a[9];
X
X   for (j = 0; j < 8; ++j)
X      if ( ! symtab[k].n_name[j] )
X         break;
X      else
X         a[j] = symtab[k].n_name[j];
X
X   a[j] = '\0';
X
X   return (a);
X
X}/* * * * * * * * * * * END OF getnam() * * * * * * * * * * */
X
X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
X  *                                                         *
X  * This function is  responsible  for mucking  through the *
X  * relocation  table in  search of  externally  referenced *
X  * symbols to be output as  operands.  It accepts two long *
X  * arguments: the code-segment location at which an extern *
X  * reference  is  expected,  and the offset value which is *
X  * embedded  in the  object  code and used at link time to *
X  * bias the external value.  In the most typical case, the *
X  * function will be called by lookup(), which always makes *
X  * a check for external names before  searching the symbol *
X  * table proper.  However,  it may also be called directly *
X  * by any function  (such as the  move-immediate  handler) *
X  * which wants to make an independent check for externals. *
X  * The caller is expected to supply, as the third argument *
X  * to the function,  a pointer to a character buffer large *
X  * enough to hold any possible  output  string.  Lookext() *
X  * will fill this  buffer and return a logical  TRUE if it *
X  * finds an extern reference;  otherwise, it will return a *
X  * logical FALSE, leaving the buffer undisturbed.          *
X  *                                                         *
X  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
X
Xint
Xlookext(off,loc,buf)
X
X   long off, loc;
X   char *buf;
X
X{/* * * * * * * * * * START OF  lookext() * * * * * * * * * */
X
X   register int k;
X   char c[16];
X
X   if ((loc != -1L) && (relptr >= 0))
X      for (k = 0; k <= relptr; ++k)
X         if ((relo[k].r_vaddr == loc)
X          && (relo[k].r_symndx < S_BSS))
X            {
X            strcpy(buf,getnam(relo[k].r_symndx));
X            if (off)
X               {
X               if (off < 0)
X                  sprintf(c,"%ld",off);
X               else
X                  sprintf(c,"+%ld",off);
X               strcat(buf,c);
X               }
X            return (1);
X            }
X
X   return (0);
X
X}/* * * * * * * * * *  END OF  lookext()  * * * * * * * * * */
X
X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
X  *                                                         *
X  * This  function  finds an entry in the  symbol  table by *
X  * value.  Its input is a (long) machine address,  and its *
X  * output is a pointer to a string  containing  the corre- *
X  * sponding symbolic name. The function first searches the *
X  * relocation table for a possible external reference;  if *
X  * none is found,  a linear  search of the symbol table is *
X  * undertaken. If no matching symbol has been found at the *
X  * end of these searches,  the function  returns a pointer *
X  * to a string  containing the ASCII equivalent of the ad- *
X  * dress which was to be located,  so that,  regardless of *
X  * the success of the search,  the function's return value *
X  * is suitable for use as a memory-reference operand.  The *
X  * caller specifies the type of symbol to be found  (text, *
X  * data, bss, undefined,  absolute, or common) by means of *
X  * the function's  second  parameter.  The third parameter *
X  * specifies  the  format to be used in the event of a nu- *
X  * meric output:  zero for absolute format,  one for short *
X  * relative  format,  two for long  relative  format.  The *
X  * fourth  parameter is the address  which would appear in *
X  * the relocation table for the reference in question,  or *
X  * -1 if the relocation  table is not to be searched.  The *
X  * function attempts to apply a certain amount of intelli- *
X  * gence in its  selection  of symbols,  so it is possible *
X  * that,  in the absence of a type match,  a symbol of the *
X  * correct value but different type will be returned.      *
X  *                                                         *
X  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
X
Xchar *
Xlookup(addr,type,kind,ext)
X
X   long addr;              /* Machine address to be located */
X
X   int type,               /* Type of symbol to be matched  */
X       kind;               /* Addressing output mode to use */
X
X   long ext;               /* Value for extern ref, if any  */
X
X{/* * * * * * * * * *  START OF lookup()  * * * * * * * * * */
X
X   register int j, k;
X   static char b[64];
X
X   struct
X      {
X      int   i;
X      int   t;
X      }
X   best;
X
X   if (lookext(addr,ext,b))
X      return (b);
X
X   if (segflg)
X      if (segflg & 1)
X         type = N_TEXT;
X      else
X         type = N_DATA;
X
X   for (k = 0, best.i = -1; k <= symptr; ++k)
X      if (symtab[k].n_value == addr)
X         if ((j = symtab[k].n_sclass & N_SECT) == type)
X            {
X            best.t = j;
X            best.i = k;
X            break;
X            }
X         else if (segflg || (HDR.a_flags & A_SEP))
X            continue;
X         else if (best.i < 0)
X            best.t = j, best.i = k;
X         else if (symrank[type][j] > symrank[type][best.t])
X            best.t = j, best.i = k;
X
X   if (best.i >= 0)
X      return (getnam(best.i));
X
X   if (kind == LOOK_ABS)
X      sprintf(b,"0x%05.5x",addr);
X   else
X      {
X      long x = addr - (PC - kind);
X      if (x < 0)
X         sprintf(b,".%ld",x);
X      else
X         sprintf(b,".+%ld",x);
X      }
X
X   return (b);
X
X}/* * * * * * * * * * * END OF lookup() * * * * * * * * * * */
X
X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
X  *                                                         *
X  * This function  translates an 8088  addressing mode byte *
X  * to an equivalent assembler string,  returning a pointer *
X  * thereto.  If necessary,  it performs  successive inputs *
X  * of bytes from the object file in order to obtain offset *
X  * data,  adjusting PC  accordingly.  (The addressing mode *
X  * byte  appears in several  8088  opcodes;  it is used to *
X  * specify source and destination operand locations.)  The *
X  * third  argument to the function is zero if the standard *
X  * registers are to be used,  or eight if the segment reg- *
X  * isters are to be used; these constants are defined sym- *
X  * bolically in dis.h.  NOTE:  The mtrans()  function must *
X  * NEVER be called except  immediately  after fetching the *
X  * mode byte.  If any additional  object bytes are fetched *
X  * after  the fetch of the mode  byte,  mtrans()  will not *
X  * produce correct output!                                 *
X  *                                                         *
X  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
X
Xchar *
Xmtrans(c,m,type)
X
X   register int c;            /* Primary instruction byte   */
X   register int m;            /* Addressing mode byte       */
X
X   int type;                  /* Type code: standard or seg */
X
X{/* * * * * * * * * *  START OF mtrans()  * * * * * * * * * */
X
X   unsigned long pc;
X   int offset, oflag, dir, w, mod, reg, rm;
X   static char a[100];
X   static char b[30];
X
X   offset = 0;
X   dir = c & 2;
X   w = c & 1;
X   mod = (m & 0xc0) >> 6;
X   reg = (m & 0x38) >> 3;
X   rm = m & 7;
X   pc = PC + 1;
X
X   if (type)
X      w = 1;
X
X   if ((oflag = mod) > 2)
X      oflag = 0;
X
X   if (oflag)
X      {
X      int j, k;
X      if (oflag == 2)
X         {
X         FETCH(j);
X         FETCH(k);
X         offset = (k << 8) | j;
X         }
X      else
X         {
X         FETCH(j);
X         if (j & 0x80)
X            k = 0xff00;
X         else
X            k = 0;
X         offset = k | j;
X         }
X      }
X
X   if (dir)
X      {
X      strcpy(a,REGS[type + ((w << 3) | reg)]);
X      strcat(a,",");
X      switch (mod)
X         {
X         case 0 :
X            if (rm == 6)
X               {
X               int j, k;
X               FETCH(j);
X               FETCH(k);
X               offset = (k << 8) | j;
X               strcat(a,
X                lookup((long)(offset),N_DATA,LOOK_ABS,pc));
X               }
X            else
X               {
X               sprintf(b,"(%s)",REGS0[rm]);
X               strcat(a,b);
X               }
X            break;
X         case 1 :
X         case 2 :
X            if (mod == 1)
X               strcat(a,"*");
X            else
X               strcat(a,"#");
X            sprintf(b,"%d(",offset);
X            strcat(a,b);
X            strcat(a,REGS1[rm]);
X            strcat(a,")");
X            break;
X         case 3 :
X            strcat(a,REGS[(w << 3) | rm]);
X            break;
X         }
X      }
X   else
X      {
X      switch (mod)
X         {
X         case 0 :
X            if (rm == 6)
X               {
X               int j, k;
X               FETCH(j);
X               FETCH(k);
X               offset = (k << 8) | j;
X               strcpy(a,
X                lookup((long)(offset),N_DATA,LOOK_ABS,pc));
X               }
X            else
X               {
X               sprintf(b,"(%s)",REGS0[rm]);
X               strcpy(a,b);
X               }
X            break;
X         case 1 :
X         case 2 :
X            if (mod == 1)
X               strcpy(a,"*");
X            else
X               strcpy(a,"#");
X            sprintf(b,"%d(",offset);
X            strcat(a,b);
X            strcat(a,REGS1[rm]);
X            strcat(a,")");
X            break;
X         case 3 :
X            strcpy(a,REGS[(w << 3) | rm]);
X            break;
X         }
X      strcat(a,",");
X      strcat(a,REGS[type + ((w << 3) | reg)]);
X      }
X
X   return (a);
X
X}/* * * * * * * * * * * END OF mtrans() * * * * * * * * * * */
X
X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
X  *                                                         *
X  * This simple routine  truncates a string returned by the *
X  * mtrans() function, removing its source operand. This is *
X  * useful in handlers which ignore the "reg"  field of the *
X  * mode byte.                                              *
X  *                                                         *
X  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
X
Xvoid
Xmtrunc(a)
X
X   register char *a;          /* Ptr. to string to truncate */
X
X{/* * * * * * * * * *  START OF mtrunc()  * * * * * * * * * */
X
X   register int k;
X
X   for (k = strlen(a) - 1; k >= 0; --k)
X      if (a[k] == ',')
X         {
X         a[k] = '\0';
X         break;
X         }
X
X}/* * * * * * * * * * * END OF mtrunc() * * * * * * * * * * */
X
X
+ END-OF-FILE distabs.c
chmod 'u=rw,g=r,o=r' 'distabs.c'
set `wc -c 'distabs.c'`
count=$1
case $count in
30238)	:;;
*)	echo 'Bad character count in ''distabs.c' >&2
		echo 'Count should be 30238' >&2
esac
echo Extracting 'README'
sed 's/^X//' > 'README' << '+ END-OF-FILE ''README'
X                                     dis88
X                                  Beta Release
X                                    87/09/01
X                                      ---
X                                 G. M. HARDING
X                                    POB 4142
X                           Santa Clara CA  95054-0142
X				gm@uts.amdahl.com
X
X
X             "Dis88" is a symbolic disassembler for the Intel 8088 CPU,
X        designed to run under the PC/IX  operating  system on an IBM XT
X        or fully-compatible clone.  Its output is in the format of, and
X        is completely compatible with, the PC/IX assembler,  "as".  The
X        program is copyrighted by its author, but may be copied and re-
X        distributed freely provided that complete source code, with all
X        copyright notices, accompanies any distribution. This provision
X        also applies to any  modifications you may make.  You are urged
X        to comment such changes,  giving,  as a miminum,  your name and
X        complete address.
X
X             This release of the program is a beta release, which means
X        that it has been  extensively,  but not  exhaustively,  tested.
X        User comments, recommendations, and bug fixes are welcome.  The
X        principal features of the current release are:
X
X             (a)  The ability to  disassemble  any file in PC/IX object
X        format, making full use of symbol and relocation information if
X        it is present,  regardless of whether the file is executable or
X        linkable,  and regardless of whether it has continuous or split
X        I/D space;
X
X             (b)  Automatic generation of synthetic labels when no sym-
X        bol table is available; and
X
X             (c)  Optional  output of address and object-code  informa-
X        tion as assembler comment text.
X
X             Limitations of the current release are:
X
X             (a)  Numeric co-processor  (i.e., 8087)  mnemonics are not
X        supported.  Instructions  for the co-processor are disassembled
X        as CPU escape  sequences,  or as  interrupts,  depending on how
X        they were assembled in the first place. This limitation will be
X        addressed in a future release.
X
X             (b)  Symbolic  references  within the object  file's  data
X        segment are not supported. Thus, for example, if a data segment
X        location is initialized to point to a text segment address,  no
X        reference to a text segment symbol will be detected. This limi-
X        tation is likely to remain in future  releases,  because object
X        code does not, in most cases, contain sufficient information to
X        allow meaningful interpretation of pure data.  (Note,  however,
X        that  symbolic  references  to the data segment from within the
X        text segment are always supported.)
X
X             As a final caveat,  be aware that the PC/IX assembler does
X        not recognize the  "esc"  mnemonic,  even though it refers to a
X        completely  valid CPU operation  which is documented in all the
X        Intel literature. Thus, the corresponding opcodes (0xd8 through
X        0xdf) are disassembled as .byte directives. For reference, how-
X        ever,  the syntactically-correct "esc" instruction is output as
X        a comment.
X
X             To build the disassembler program, transfer all the source
X        files,  together with the Makefile,  to a suitable  (preferably
X        empty) PC/IX directory. Then, simply type "make".
X
X             To use dis88,  place it in a  directory  which  appears in
X        your $PATH list.  It may then be invoked by name from  whatever
X        directory you happen to be in.  As a minimum,  the program must
X        be invoked with one command-line argument:  the name of the ob-
X        ject file to be disassembled.  (Dis88 will complain if the file
X        specified is not an object file.)  Optionally,  you may specify
X        an output file; stdout is the default.  One command-line switch
X        is available:  "-o",  which makes the program display addresses
X        and object code along with its mnemonic disassembly.
X
X             The "-o" option is useful primarily for verifying the cor-
X        rectness of the program's output. In particular, it may be used
X        to check the accuracy of local  relative  jump  opcodes.  These
X        jumps often  target  local  labels,  which are lost at assembly
X        time;  thus,  the disassembly may contain cryptic  instructions
X        like "jnz .+39".  As a user convenience,  all relative jump and
X        call  opcodes are output with a comment  which  identifies  the
X        physical target address.
X
X             By convention, the release level of the program as a whole
X        is the SID of the file disrel.c, and this SID string appears in
X        each disassembly.  Release 2.1 of the program is the first beta
X        release to be distributed on Usenet.
X
+ END-OF-FILE README
chmod 'u=rw,g=r,o=r' 'README'
set `wc -c 'README'`
count=$1
case $count in
4920)	:;;
*)	echo 'Bad character count in ''README' >&2
		echo 'Count should be 4920' >&2
esac
echo Extracting 'dis88.1'
sed 's/^X//' > 'dis88.1' << '+ END-OF-FILE ''dis88.1'
X.TH dis88 1 LOCAL
X.SH "NAME"
Xdis88 \- 8088 symbolic disassembler
X.SH "SYNOPSIS"
X\fBdis88\fP [ -o ] ifile [ ofile ]
X.SH "DESCRIPTION"
XDis88 reads ifile, which must be in PC/IX a.out format.
XIt interprets the binary opcodes and data locations, and
Xwrites corresponding assembler source code to stdout, or
Xto ofile if specified.  The program's output is in the
Xformat of, and fully compatible with, the PC/IX assembler,
Xas(1).  If a symbol table is present in ifile, labels and
Xreferences will be symbolic in the output.  If the input
Xfile lacks a symbol table, the fact will be noted, and the
Xdisassembly will proceed, with the disassembler generating
Xsynthetic labels as needed.  If the input file has split
XI/D space, or if it is executable, the disassembler will
Xmake all necessary adjustments in address-reference calculations.
X.PP
XIf the "-o" option appears, object code will be included
Xin comments during disassembly of the text segment.  This
Xfeature is used primarily for debugging the disassembler
Xitself, but may provide information of passing interest
Xto users.
X.PP
XThe program always outputs the current machine address
Xbefore disassembling an opcode.  If a symbol table is
Xpresent, this address is output as an assembler comment;
Xotherwise, it is incorporated into the synthetic label
Xwhich is generated internally.  Since relative jumps,
Xespecially short ones, may target unlabelled locations,
Xthe program always outputs the physical target address
Xas a comment, to assist the user in following the code.
X.PP
XThe text segment of an object file is always padded to
Xan even machine address.  In addition, if the file has
Xsplit I/D space, the text segment will be padded to a
Xparagraph boundary (i.e., an address divisible by 16).
XAs a result of this padding, the disassembler may produce
Xa few spurious, but harmless, instructions at the
Xend of the text segment.
X.PP
XDisassembly of the data segment is a difficult matter.
XThe information to which initialized data refers cannot
Xbe inferred from context, except in the special case
Xof an external data or address reference, which will be
Xreflected in the relocation table.  Internal data and
Xaddress references will already be resolved in the object file,
Xand cannot be recreated.  Therefore, the data
Xsegment is disassembled as a byte stream, with long
Xstretches of null data represented by an appropriate
X".zerow" pseudo-op.  This limitation notwithstanding,
Xlabels (as opposed to symbolic references) are always
Xoutput at appropriate points within the data segment.
X.PP
XIf disassembly of the data segment is difficult, disassembly of the
Xbss segment is quite easy, because uninitialized data is all
Xzero by definition.  No data
Xis output in the bss segment, but symbolic labels are
Xoutput as appropriate.
X.PP
XFor each opcode which takes an operand, a particular
Xsymbol type (text, data, or bss) is appropriate.  This
Xtidy correspondence is complicated somewhat, however,
Xby the existence of assembler symbolic constants and
Xsegment override opcodes.  Therefore, the disassembler's
Xsymbol lookup routine attempts to apply a certain amount
Xof intelligence when it is asked to find a symbol.  If
Xit cannot match on a symbol of the preferred type, it
Xmay return a symbol of some other type, depending on
Xpreassigned (and somewhat arbitrary) rankings within
Xeach type.  Finally, if all else fails, it returns a
Xstring containing the address sought as a hex constant;
Xthis behavior allows calling routines to use the output
Xof the lookup function regardless of the success of its
Xsearch.
X.PP
XIt is worth noting, at this point, that the symbol lookup
Xroutine operates linearly, and has not been optimized in
Xany way.  Execution time is thus likely to increase
Xgeometrically with input file size.  The disassembler is
Xinternally limited to 1500 symbol table entries and 1500
Xrelocation table entries; while these limits are generous
X(/unix, itself, has fewer than 800 symbols), they are not
Xguaranteed to be adequate in all cases.  If the symbol
Xtable or the relocation table overflows, the disassembly
Xaborts.
X.PP
XFinally, users should be aware of a bug in the assembler,
Xwhich causes it not to parse the "esc" mnemonic, even
Xthough "esc" is a completely legitimate opcode which is
Xdocumented in all the Intel literature.  To accommodate
Xthis deficiency, the disassembler translates opcodes of
Xthe "esc" family to .byte directives, but notes the
Xcorrect mnemonic in a comment for reference.
X.PP
XIn all cases, it should be possible to submit the output
Xof the disassembler program to the assembler, and assemble
Xit without error.  In most cases, the resulting object
Xcode will be identical to the original; in any event, it
Xwill be functionally equivalent.
X.SH "SEE ALSO"
Xadb(1), as(1), cc(1), ld(1).
X.br
X"Assembler Reference Manual" in the PC/IX Programmer's
XGuide.
X.SH "DIAGNOSTICS"
X"can't access input file" if the input file cannot be
Xfound, opened, or read.
X.sp
X"can't open output file" if the output file cannot be
Xcreated.
X.sp
X"warning: host/cpu clash" if the program is run on a
Xmachine with a different CPU.
X.sp
X"input file not in object format" if the magic number
Xdoes not correspond to that of a PC/IX object file.
X.sp
X"not an 8086/8088 object file" if the CPU ID of the
Xfile header is incorrect.
X.sp
X"reloc table overflow" if there are more than 1500
Xentries in the relocation table.
X.sp
X"symbol table overflow" if there are more than 1500
Xentries in the symbol table.
X.sp
X"lseek error" if the input file is corrupted (should
Xnever happen).
X.sp
X"warning: no symbols" if the symbol table is missing.
X.sp
X"can't reopen input file" if the input file is removed
Xor altered during program execution (should never happen).
X.SH "BUGS"
XNumeric co-processor (i.e., 8087) mnemonics are not currently supported.
XInstructions for the co-processor are
Xdisassembled as CPU escape sequences, or as interrupts,
Xdepending on how they were assembled in the first place.
X.sp
XDespite the program's best efforts, a symbol retrieved
Xfrom the symbol table may sometimes be different from
Xthe symbol used in the original assembly.
X.sp
XThe disassembler's internal tables are of fixed size,
Xand the program aborts if they overflow.
+ END-OF-FILE dis88.1
chmod 'u=rw,g=r,o=r' 'dis88.1'
set `wc -c 'dis88.1'`
count=$1
case $count in
6174)	:;;
*)	echo 'Bad character count in ''dis88.1' >&2
		echo 'Count should be 6174' >&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 'disrel.c'
sed 's/^X//' > 'disrel.c' << '+ END-OF-FILE ''disrel.c'
Xstatic char *copyright =
X   "@(#) Copyright (C) 1987 G. M. Harding, all rights reserved";
X
Xstatic char *sccsid =
X   "@(#) disrel.c, Ver. 2.1 created 00:00:00 87/09/01";
X
Xchar *release =
X   "release 2.1 (PC/IX)";
X
X /*
X **
X ** This file documents the major revisions to the 8088 sym-
X ** bolic disassembler. It also contains the release string
X ** which is output at the head of each disassembly, and the
X ** copyright string which must be incorporated in any code
X ** distribution.
X **
X ** Permission to copy and redistribute is hereby granted,
X ** provided full source code, with all copyright notices,
X ** accompanies any redistribution.
X **
X ** REVISION HISTORY:
X **
X ** SEP 87:
X **    After internal shakeout, released on Usenet.
X **
X */
X
+ END-OF-FILE disrel.c
chmod 'u=rw,g=r,o=r' 'disrel.c'
set `wc -c 'disrel.c'`
count=$1
case $count in
742)	:;;
*)	echo 'Bad character count in ''disrel.c' >&2
		echo 'Count should be 742' >&2
esac
exit 0