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