diff options
author | Robert de Bath <rdebath@poboxes.com> | 1996-03-24 17:45:55 +0100 |
---|---|---|
committer | Lubomir Rintel <lkundrak@v3.sk> | 2013-10-23 23:29:43 +0200 |
commit | fe22c37817ce338fbbc90b239320248c270957fa (patch) | |
tree | d9550410c4a20bdd382fcc58d2d3d7c5e04e5245 /dis88 | |
parent | a7aba15e8efffb1c5d3097656f1a93955a64f01f (diff) | |
parent | 42192453ea219b80d0bf9f41e51e36d3d4d0740b (diff) | |
download | dev86-fe22c37817ce338fbbc90b239320248c270957fa.tar.gz |
Import Dev86-0.0.4.tar.gzv0.0.4
Diffstat (limited to 'dis88')
-rw-r--r-- | dis88/Makefile | 51 | ||||
-rw-r--r-- | dis88/README | 90 | ||||
l--------- | dis88/a.out.h | 1 | ||||
-rw-r--r-- | dis88/ansi.h | 58 | ||||
-rw-r--r-- | dis88/dis.h | 170 | ||||
-rw-r--r-- | dis88/dis88.1 | 147 | ||||
-rw-r--r-- | dis88/disfp.c | 157 | ||||
-rw-r--r-- | dis88/dishand.c | 1049 | ||||
-rw-r--r-- | dis88/dismain.c | 650 | ||||
-rw-r--r-- | dis88/disrel.c | 30 | ||||
-rw-r--r-- | dis88/distabs.c | 708 | ||||
-rw-r--r-- | dis88/old_a.out.h | 117 |
12 files changed, 3228 insertions, 0 deletions
diff --git a/dis88/Makefile b/dis88/Makefile new file mode 100644 index 0000000..692326f --- /dev/null +++ b/dis88/Makefile @@ -0,0 +1,51 @@ +# Makefile for dis + +# @(#) Makefile, Ver. 2.1 created 00:00:00 87/09/01 +# Makefile for 8088 symbolic disassembler + +# Copyright (C) 1987 G. M. Harding, all rights reserved. +# Permission to copy and redistribute is hereby granted, +# provided full source code, with all copyright notices, +# accompanies any redistribution. + +# This Makefile automates the process of compiling and linking +# a symbolic object-file disassembler program for the Intel +# 8088 CPU. Relatively machine-independent code is contained in +# the file dismain.c; lookup tables and handler routines, which +# are by their nature machine-specific, are contained in two +# files named distabs.c and dishand.c, respectively. (A third +# machine-specific file, disfp.c, contains handler routines for +# floating-point coprocessor opcodes.) A header file, dis.h, +# attempts to mediate between the machine-specific and machine- +# independent portions of the code. An attempt has been made to +# isolate machine dependencies and to deal with them in fairly +# straightforward ways. Thus, it should be possible to target a +# different CPU by rewriting the handler routines and changing +# the initialization data in the lookup tables. It should not +# be necessary to alter the formats of the tables. + +CC=bcc +CFLAGS=-O +LDFLAGS= + +OBJ = disrel.o dismain.o distabs.o dishand.o disfp.o + +all: dis88 + +dis88: $(OBJ) + $(CC) $(LDFLAGS) -o dis88 $(OBJ) + +install: /usr/bin/dis88 + +/usr/bin/dis88: dis88 + install -cs -o bin dis88 $@ + +disrel.o: disrel.c +dismain.o: dismain.c dis.h +distabs.o: distabs.c dis.h +dishand.o: dishand.c dis.h +disfp.o: disfp.c dis.h + + +clean: + rm -f *.bak *.o core dis88 diff --git a/dis88/README b/dis88/README new file mode 100644 index 0000000..efc5ad9 --- /dev/null +++ b/dis88/README @@ -0,0 +1,90 @@ + dis88 + Beta Release + 87/09/01 + --- + G. M. HARDING + POB 4142 + Santa Clara CA 95054-0142 + + + "Dis88" is a symbolic disassembler for the Intel 8088 CPU, + designed to run under the PC/IX operating system on an IBM XT + or fully-compatible clone. Its output is in the format of, and + is completely compatible with, the PC/IX assembler, "as". The + program is copyrighted by its author, but may be copied and re- + distributed freely provided that complete source code, with all + copyright notices, accompanies any distribution. This provision + also applies to any modifications you may make. You are urged + to comment such changes, giving, as a miminum, your name and + complete address. + + This release of the program is a beta release, which means + that it has been extensively, but not exhaustively, tested. + User comments, recommendations, and bug fixes are welcome. The + principal features of the current release are: + + (a) The ability to disassemble any file in PC/IX object + format, making full use of symbol and relocation information if + it is present, regardless of whether the file is executable or + linkable, and regardless of whether it has continuous or split + I/D space; + + (b) Automatic generation of synthetic labels when no sym- + bol table is available; and + + (c) Optional output of address and object-code informa- + tion as assembler comment text. + + Limitations of the current release are: + + (a) Numeric co-processor (i.e., 8087) mnemonics are not + supported. Instructions for the co-processor are disassembled + as CPU escape sequences, or as interrupts, depending on how + they were assembled in the first place. This limitation will be + addressed in a future release. + + (b) Symbolic references within the object file's data + segment are not supported. Thus, for example, if a data segment + location is initialized to point to a text segment address, no + reference to a text segment symbol will be detected. This limi- + tation is likely to remain in future releases, because object + code does not, in most cases, contain sufficient information to + allow meaningful interpretation of pure data. (Note, however, + that symbolic references to the data segment from within the + text segment are always supported.) + + As a final caveat, be aware that the PC/IX assembler does + not recognize the "esc" mnemonic, even though it refers to a + completely valid CPU operation which is documented in all the + Intel literature. Thus, the corresponding opcodes (0xd8 through + 0xdf) are disassembled as .byte directives. For reference, how- + ever, the syntactically-correct "esc" instruction is output as + a comment. + + To build the disassembler program, transfer all the source + files, together with the Makefile, to a suitable (preferably + empty) PC/IX directory. Then, simply type "make". + + To use dis88, place it in a directory which appears in + your $PATH list. It may then be invoked by name from whatever + directory you happen to be in. As a minimum, the program must + be invoked with one command-line argument: the name of the ob- + ject file to be disassembled. (Dis88 will complain if the file + specified is not an object file.) Optionally, you may specify + an output file; stdout is the default. One command-line switch + is available: "-o", which makes the program display addresses + and object code along with its mnemonic disassembly. + + The "-o" option is useful primarily for verifying the cor- + rectness of the program's output. In particular, it may be used + to check the accuracy of local relative jump opcodes. These + jumps often target local labels, which are lost at assembly + time; thus, the disassembly may contain cryptic instructions + like "jnz .+39". As a user convenience, all relative jump and + call opcodes are output with a comment which identifies the + physical target address. + + By convention, the release level of the program as a whole + is the SID of the file disrel.c, and this SID string appears in + each disassembly. Release 2.1 of the program is the first beta + release to be distributed on Usenet. diff --git a/dis88/a.out.h b/dis88/a.out.h new file mode 120000 index 0000000..ccbf4b5 --- /dev/null +++ b/dis88/a.out.h @@ -0,0 +1 @@ +../libc/include/a.out.h
\ No newline at end of file diff --git a/dis88/ansi.h b/dis88/ansi.h new file mode 100644 index 0000000..825b4a6 --- /dev/null +++ b/dis88/ansi.h @@ -0,0 +1,58 @@ +/* The <ansi.h> header attempts to decide whether the compiler has enough + * conformance to Standard C for Minix to take advantage of. If so, the + * symbol _ANSI is defined (as 31415). Otherwise _ANSI is not defined + * here, but it may be defined by applications that want to bend the rules. + * The magic number in the definition is to inhibit unnecessary bending + * of the rules. (For consistency with the new '#ifdef _ANSI" tests in + * the headers, _ANSI should really be defined as nothing, but that would + * break many library routines that use "#if _ANSI".) + + * If _ANSI ends up being defined, a macro + * + * _PROTOTYPE(function, params) + * + * is defined. This macro expands in different ways, generating either + * ANSI Standard C prototypes or old-style K&R (Kernighan & Ritchie) + * prototypes, as needed. Finally, some programs use _CONST, _VOIDSTAR etc + * in such a way that they are portable over both ANSI and K&R compilers. + * The appropriate macros are defined here. + */ + +#ifndef _ANSI_H +#define _ANSI_H + +#if __STDC__ == 1 +#define _ANSI 31459 /* compiler claims full ANSI conformance */ +#endif + +#ifdef __GNUC__ +#define _ANSI 31459 /* gcc conforms enough even in non-ANSI mode */ +#endif + +#ifdef _ANSI + +/* Keep everything for ANSI prototypes. */ +#define _PROTOTYPE(function, params) function params +#define _ARGS(params) params + +#define _VOIDSTAR void * +#define _VOID void +#define _CONST const +#define _VOLATILE volatile +#define _SIZET size_t + +#else + +/* Throw away the parameters for K&R prototypes. */ +#define _PROTOTYPE(function, params) function() +#define _ARGS(params) () + +#define _VOIDSTAR void * +#define _VOID void +#define _CONST +#define _VOLATILE +#define _SIZET int + +#endif /* _ANSI */ + +#endif /* ANSI_H */ diff --git a/dis88/dis.h b/dis88/dis.h new file mode 100644 index 0000000..7815e06 --- /dev/null +++ b/dis88/dis.h @@ -0,0 +1,170 @@ + /* + ** @(#) dis.h, Ver. 2.1 created 00:00:00 87/09/01 + */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 1987 G. M. Harding, all rights reserved * + * * + * Permission to copy and redistribute is hereby granted, * + * provided full source code, with all copyright notices, * + * accompanies any redistribution. * + * * + * This file contains declarations and definitions used by * + * the 8088 disassembler program. The program was designed * + * for execution on a machine of its own type (i.e., it is * + * not designed as a cross-disassembler); consequently, A * + * SIXTEEN-BIT INTEGER SIZE HAS BEEN ASSUMED. This assump- * + * tion is not particularly important, however, except in * + * the machine-specific portions of the code (i.e., the * + * handler routines and the optab[] array). It should be * + * possible to override this assumption, for execution on * + * 32-bit machines, by use of a pre-processor directive * + * (see below); however, this has not been tested. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include <sys/types.h> +#include <fcntl.h> /* System file-control definitions */ +#include <unistd.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> /* System standard I/O definitions */ +#include "a.out.h" /* Object file format definitions */ +#include "ansi.h" + +#define MAXSYM 800 /* Maximum entries in symbol table */ + +extern struct nlist /* Array to hold the symbol table */ + symtab[MAXSYM]; + +extern struct reloc /* Array to hold relocation table */ + relo[MAXSYM]; + +extern int symptr; /* Index into the symtab[] array */ +extern int relptr; /* Index into the relo[] array */ + +struct opcode /* Format for opcode data records */ +{ + char *text; /* Pointer to mnemonic text */ + void (*func)(); /* Pointer to handler routine */ + unsigned min; /* Minimum # of object bytes */ + unsigned max; /* Maximum # of object bytes */ +}; + +extern struct opcode /* Array to hold the opcode table */ + optab[256]; + +extern char *REGS[]; /* Table of register names */ +extern char *REGS0[]; /* Mode 0 register name table */ +extern char *REGS1[]; /* Mode 1 register name table */ + +#define AL REGS[0] /* CPU register manifests */ +#define CL REGS[1] +#define DL REGS[2] +#define BL REGS[3] +#define AH REGS[4] +#define CH REGS[5] +#define DH REGS[6] +#define BH REGS[7] +#define AX REGS[8] +#define CX REGS[9] +#define DX REGS[10] +#define BX REGS[11] +#define SP REGS[12] +#define BP REGS[13] +#define SI REGS[14] +#define DI REGS[15] +#define ES REGS[16] +#define CS REGS[17] +#define SS REGS[18] +#define DS REGS[19] +#define BX_SI REGS0[0] +#define BX_DI REGS0[1] +#define BP_SI REGS0[2] +#define BP_DI REGS0[3] + +extern int symrank[6][6]; /* Symbol type/rank matrix */ +extern unsigned long PC; /* Current program counter */ +extern int segflg; /* Flag: segment override in effect */ +extern int objflg; /* Flag: output object as a comment */ + +#define OBJMAX 8 /* Size of the object code buffer */ + +extern unsigned char /* Internal buffer for object code */ + objbuf[OBJMAX]; + +extern int objptr; /* Index into the objbuf[] array */ + +extern char ADD[], /* Opcode family mnemonic strings */ + OR[], + ADC[], + SBB[], + AND[], + SUB[], + XOR[], + CMP[], + NOT[], + NEG[], + MUL[], + DIV[], + MOV[], + ESC[], + TEST[], + AMBIG[]; + +extern char *OPFAM[]; /* Indexed mnemonic family table */ +extern struct exec HDR; /* Holds the object file's header */ + +#define LOOK_ABS 0 /* Arguments to lookup() function */ +#define LOOK_REL 1 +#define LOOK_LNG 2 + +#define TR_STD 0 /* Arguments to mtrans() function */ +#define TR_SEG 8 + + /* Macro for byte input primitive */ +/* #define FETCH(p) ++PC; p = getchar() & 0xff; objbuf[objptr++] = p */ +static int _F_; +#define FETCH(p) (p)=_F_ = Fetch(); if(_F_<0) {printf("???\n"); return; } + + +/* disfp.c */ +_PROTOTYPE(void eshand, (int j )); +_PROTOTYPE(void fphand, (int j )); +_PROTOTYPE(void inhand, (int j )); + +/* dishand.c */ +_PROTOTYPE(void objini, (int j )); +_PROTOTYPE(void objout, (void)); +_PROTOTYPE(void badseq, (int j, int k )); +_PROTOTYPE(void dfhand, (int j )); +_PROTOTYPE(void sbhand, (int j )); +_PROTOTYPE(void aohand, (int j )); +_PROTOTYPE(void sjhand, (int j )); +_PROTOTYPE(void imhand, (int j )); +_PROTOTYPE(void mvhand, (int j )); +_PROTOTYPE(void mshand, (int j )); +_PROTOTYPE(void pohand, (int j )); +_PROTOTYPE(void cihand, (int j )); +_PROTOTYPE(void mihand, (int j )); +_PROTOTYPE(void mqhand, (int j )); +_PROTOTYPE(void tqhand, (int j )); +_PROTOTYPE(void rehand, (int j )); +_PROTOTYPE(void mmhand, (int j )); +_PROTOTYPE(void srhand, (int j )); +_PROTOTYPE(void aahand, (int j )); +_PROTOTYPE(void iohand, (int j )); +_PROTOTYPE(void ljhand, (int j )); +_PROTOTYPE(void mahand, (int j )); +_PROTOTYPE(void mjhand, (int j )); + +/* dismain.c */ +_PROTOTYPE(void main, (int argc, char **argv )); + +/* distabs.c */ +_PROTOTYPE(char *getnam, (int k )); +_PROTOTYPE(int lookext, (long off, long loc, char *buf )); +_PROTOTYPE(char *lookup, (long addr, int type, int kind, long ext )); +_PROTOTYPE(char *mtrans, (int c, int m, int type )); +_PROTOTYPE(void mtrunc, (char *a )); diff --git a/dis88/dis88.1 b/dis88/dis88.1 new file mode 100644 index 0000000..c991ad7 --- /dev/null +++ b/dis88/dis88.1 @@ -0,0 +1,147 @@ +.TH dis88 1 LOCAL +.SH "NAME" +dis88 \- 8088 symbolic disassembler +.SH "SYNOPSIS" +\fBdis88\fP [ -o ] ifile [ ofile ] +.SH "DESCRIPTION" +Dis88 reads ifile, which must be in PC/IX a.out format. +It interprets the binary opcodes and data locations, and +writes corresponding assembler source code to stdout, or +to ofile if specified. The program's output is in the +format of, and fully compatible with, the PC/IX assembler, +as(1). If a symbol table is present in ifile, labels and +references will be symbolic in the output. If the input +file lacks a symbol table, the fact will be noted, and the +disassembly will proceed, with the disassembler generating +synthetic labels as needed. If the input file has split +I/D space, or if it is executable, the disassembler will +make all necessary adjustments in address-reference calculations. +.PP +If the "-o" option appears, object code will be included +in comments during disassembly of the text segment. This +feature is used primarily for debugging the disassembler +itself, but may provide information of passing interest +to users. +.PP +The program always outputs the current machine address +before disassembling an opcode. If a symbol table is +present, this address is output as an assembler comment; +otherwise, it is incorporated into the synthetic label +which is generated internally. Since relative jumps, +especially short ones, may target unlabelled locations, +the program always outputs the physical target address +as a comment, to assist the user in following the code. +.PP +The text segment of an object file is always padded to +an even machine address. In addition, if the file has +split I/D space, the text segment will be padded to a +paragraph boundary (i.e., an address divisible by 16). +As a result of this padding, the disassembler may produce +a few spurious, but harmless, instructions at the +end of the text segment. +.PP +Disassembly of the data segment is a difficult matter. +The information to which initialized data refers cannot +be inferred from context, except in the special case +of an external data or address reference, which will be +reflected in the relocation table. Internal data and +address references will already be resolved in the object file, +and cannot be recreated. Therefore, the data +segment is disassembled as a byte stream, with long +stretches of null data represented by an appropriate +".zerow" pseudo-op. This limitation notwithstanding, +labels (as opposed to symbolic references) are always +output at appropriate points within the data segment. +.PP +If disassembly of the data segment is difficult, disassembly of the +bss segment is quite easy, because uninitialized data is all +zero by definition. No data +is output in the bss segment, but symbolic labels are +output as appropriate. +.PP +For each opcode which takes an operand, a particular +symbol type (text, data, or bss) is appropriate. This +tidy correspondence is complicated somewhat, however, +by the existence of assembler symbolic constants and +segment override opcodes. Therefore, the disassembler's +symbol lookup routine attempts to apply a certain amount +of intelligence when it is asked to find a symbol. If +it cannot match on a symbol of the preferred type, it +may return a symbol of some other type, depending on +preassigned (and somewhat arbitrary) rankings within +each type. Finally, if all else fails, it returns a +string containing the address sought as a hex constant; +this behavior allows calling routines to use the output +of the lookup function regardless of the success of its +search. +.PP +It is worth noting, at this point, that the symbol lookup +routine operates linearly, and has not been optimized in +any way. Execution time is thus likely to increase +geometrically with input file size. The disassembler is +internally limited to 1500 symbol table entries and 1500 +relocation table entries; while these limits are generous +(/unix, itself, has fewer than 800 symbols), they are not +guaranteed to be adequate in all cases. If the symbol +table or the relocation table overflows, the disassembly +aborts. +.PP +Finally, users should be aware of a bug in the assembler, +which causes it not to parse the "esc" mnemonic, even +though "esc" is a completely legitimate opcode which is +documented in all the Intel literature. To accommodate +this deficiency, the disassembler translates opcodes of +the "esc" family to .byte directives, but notes the +correct mnemonic in a comment for reference. +.PP +In all cases, it should be possible to submit the output +of the disassembler program to the assembler, and assemble +it without error. In most cases, the resulting object +code will be identical to the original; in any event, it +will be functionally equivalent. +.SH "SEE ALSO" +adb(1), as(1), cc(1), ld(1). +.br +"Assembler Reference Manual" in the PC/IX Programmer's +Guide. +.SH "DIAGNOSTICS" +"can't access input file" if the input file cannot be +found, opened, or read. +.sp +"can't open output file" if the output file cannot be +created. +.sp +"warning: host/cpu clash" if the program is run on a +machine with a different CPU. +.sp +"input file not in object format" if the magic number +does not correspond to that of a PC/IX object file. +.sp +"not an 8086/8088 object file" if the CPU ID of the +file header is incorrect. +.sp +"reloc table overflow" if there are more than 1500 +entries in the relocation table. +.sp +"symbol table overflow" if there are more than 1500 +entries in the symbol table. +.sp +"lseek error" if the input file is corrupted (should +never happen). +.sp +"warning: no symbols" if the symbol table is missing. +.sp +"can't reopen input file" if the input file is removed +or altered during program execution (should never happen). +.SH "BUGS" +Numeric co-processor (i.e., 8087) mnemonics are not currently supported. +Instructions for the co-processor are +disassembled as CPU escape sequences, or as interrupts, +depending on how they were assembled in the first place. +.sp +Despite the program's best efforts, a symbol retrieved +from the symbol table may sometimes be different from +the symbol used in the original assembly. +.sp +The disassembler's internal tables are of fixed size, +and the program aborts if they overflow. diff --git a/dis88/disfp.c b/dis88/disfp.c new file mode 100644 index 0000000..c6dc0da --- /dev/null +++ b/dis88/disfp.c @@ -0,0 +1,157 @@ +static char *sccsid = + "@(#) disfp.c, Ver. 2.1 created 00:00:00 87/09/01"; + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 1987 G. M. Harding, all rights reserved * + * * + * Permission to copy and redistribute is hereby granted, * + * provided full source code, with all copyright notices, * + * accompanies any redistribution. * + * * + * This file contains handler routines for the numeric op- * + * codes of the 8087 co-processor, as well as a few other * + * opcodes which are related to 8087 emulation. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "dis.h" /* Disassembler declarations */ + +#define FPINT0 0xd8 /* Floating-point interrupts */ +#define FPINT1 0xd9 +#define FPINT2 0xda +#define FPINT3 0xdb +#define FPINT4 0xdc +#define FPINT5 0xdd +#define FPINT6 0xde +#define FPINT7 0xdf + + /* Test for floating opcodes */ +#define ISFLOP(x) \ + (((x) >= FPINT0) && ((x) <= FPINT7)) + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the handler for the escape family of opcodes. * + * These opcodes place the contents of a specified memory * + * location on the system bus, for access by a peripheral * + * or by a co-processor such as the 8087. (The 8087 NDP is * + * accessed only via bus escapes.) Due to a bug in the * + * PC/IX assembler, the "esc" mnemonic is not recognized; * + * consequently, escape opcodes are disassembled as .byte * + * directives, with the appropriate mnemonic and operand * + * included as a comment. FOR NOW, those escape sequences * + * corresponding to 8087 opcodes are treated as simple * + * escapes. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +eshand(j) + + register int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF eshand() * * * * * * * * * */ + + register char *a; + register int k; + + objini(j); + + FETCH(k); + + a = mtrans((j & 0xfd),(k & 0xc7),TR_STD); + + mtrunc(a); + + printf("\t.byte\t0x%02.2x\t\t| esc\t%s\n",j,a); + + for (k = 1; k < objptr; ++k) + printf("\t.byte\t0x%02.2x\n",objbuf[k]); + +}/* * * * * * * * * * * END OF eshand() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the handler routine for floating-point opcodes. * + * Since PC/IX must accommodate systems with and without * + * 8087 co-processors, it allows floating-point operations * + * to be initiated in either of two ways: by a software * + * interrput whose type is in the range 0xd8 through 0xdf, * + * or by a CPU escape sequence, which is invoked by an op- * + * code in the same range. In either case, the subsequent * + * byte determines the actual numeric operation to be per- * + * formed. However, depending on the method of access, * + * either one or two code bytes will precede that byte, * + * and the fphand() routine has no way of knowing whether * + * it was invoked by interrupt or by an escape sequence. * + * Therefore, unlike all of the other handler routines ex- * + * cept dfhand(), fphand() does not initialize the object * + * buffer, leaving that chore to the caller. * + * * + * FOR NOW, fphand() does not disassemble floating-point * + * opcodes to floating mnemonics, but simply outputs the * + * object code as .byte directives. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +fphand(j) + + register int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF fphand() * * * * * * * * * */ + + register int k; + + segflg = 0; + + FETCH(k); + + printf("\t.byte\t0x%02.2x\t\t| 8087 code sequence\n", + objbuf[0]); + + for (k = 1; k < objptr; ++k) + printf("\t.byte\t0x%02.2x\n",objbuf[k]); + +/* objout(); FOR NOW */ + +}/* * * * * * * * * * * END OF fphand() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the handler for variable software interrupt * + * opcodes. It is included in this file because PC/IX im- * + * plements its software floating-point emulation by means * + * of interrupts. Any interrupt in the range 0xd8 through * + * 0xdf is an NDP-emulation interrupt, and is specially * + * handled by the assembler. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +inhand(j) + + register int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF inhand() * * * * * * * * * */ + + register int k; + + objini(j); + + FETCH(k); + + if (ISFLOP(k)) + { + fphand(k); + return; + } + + printf("%s\t%d\n",optab[j].text,k); + + objout(); + +}/* * * * * * * * * * * END OF inhand() * * * * * * * * * * */ + + diff --git a/dis88/dishand.c b/dis88/dishand.c new file mode 100644 index 0000000..5983972 --- /dev/null +++ b/dis88/dishand.c @@ -0,0 +1,1049 @@ +static char *sccsid = + "@(#) dishand.c, Ver. 2.1 created 00:00:00 87/09/01"; + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 1987 G. M. Harding, all rights reserved * + * * + * Permission to copy and redistribute is hereby granted, * + * provided full source code, with all copyright notices, * + * accompanies any redistribution. * + * * + * This file contains the source code for most of the spe- * + * cialized handler routines of the disassembler program. * + * (The file disfp.c contains handler routines specific to * + * the 8087 numeric co-processor.) Each handler routine * + * interprets the opcode byte (and subsequent data bytes, * + * if any) of a particular family of opcodes, and is re- * + * sponsible for generating appropriate output. All of the * + * code in this file is highly MACHINE-SPECIFIC, and would * + * have to be rewritten for a different CPU. The handler * + * routines are accessed only via pointers in the optab[] * + * array, however, so machine dependencies are confined to * + * this file, its sister file "disfp.c", and the data file * + * "distabs.c". * + * * + * All of the code in this file is based on the assumption * + * of sixteen-bit integers. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "dis.h" /* Disassembler declarations */ + +int segflg; /* Segment-override flag */ + +unsigned char objbuf[OBJMAX]; /* Buffer for object code */ + +int objptr; /* Index into objbuf[] */ + +unsigned long PC; /* Current program counter */ + + /* * * * * * MISCELLANEOUS SUPPORTING ROUTINES * * * * * */ + + +void +objini(j) /* Object code init routine */ + + register int j; + +{ + if ((segflg == 1) || (segflg == 2)) + segflg *= 3; + else + segflg = 0; + objptr = 0; + objbuf[objptr++] = (unsigned char)(j); +} + + +void +objout() /* Object-code output routine */ + +{ + register int k; + + if ( ! objflg ) + return; + else + { + printf("\t|"); + if (symptr >= 0) + printf(" %05.5lx:",(PC + 1L - (long)(objptr))); + for (k = 0; k < objptr; ++k) + printf(" %02.2x",objbuf[k]); + putchar('\n'); + } +} + + +void +badseq(j,k) /* Invalid-sequence routine */ + + register int j, k; + +{ + printf("\t.byte\t0x%02.2x\t\t| invalid code sequence\n",j); + printf("\t.byte\t0x%02.2x\n",k); +} + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This routine is the first of several opcode-specific * + * handlers, each of which is dedicated to a particular * + * opcode family. A pointer to a handler routine is con- * + * tained in the second field of each optab[] entry. The * + * dfhand() routine is the default handler, invoked when * + * no other handler is appropriate (generally, when an in- * + * valid opcode is encountered). * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +dfhand(j) + + register int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF dfhand() * * * * * * * * * */ + + segflg = 0; + + printf("\t.byte\t0x%02.2x",j); + + if (optab[j].min || optab[j].max) + putchar('\n'); + else + printf("\t\t| unimplemented opcode\n"); + +}/* * * * * * * * * * * END OF dfhand() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the single-byte handler, invoked whenever a * + * one-byte opcode is encountered. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +sbhand(j) + + register int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF sbhand() * * * * * * * * * */ + + objini(j); + + if (j == 0x2e) /* seg cs */ + segflg = 1; + + if ((j == 0x26) /* seg es */ + || (j == 0x36) /* seg ss */ + || (j == 0x3e)) /* seg ds */ + segflg = 2; + + printf("%s\n",optab[j].text); + + objout(); + +}/* * * * * * * * * * * END OF sbhand() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the handler for most of the processor's regular * + * arithmetic operations. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +aohand(j) + + register int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF aohand() * * * * * * * * * */ + + register int k; + int m, n; + char b[80]; + + objini(j); + + switch (j & 7) + { + case 0 : + case 1 : + case 2 : + case 3 : + printf("%s\t",optab[j].text); + FETCH(k); + printf("%s\n",mtrans(j,k,TR_STD)); + break; + case 4 : + FETCH(k); + printf("%s\tal,*0x%02.2x\n",optab[j].text,k); + break; + case 5 : + FETCH(m); + FETCH(n); + k = (n << 8) | m; + if (lookext((long)(k),(PC - 1),b)) + printf("%s\tax,#%s\n",optab[j].text,b); + else + printf("%s\tax,#0x%04.4x\n",optab[j].text,k); + break; + default : + dfhand(j); + break; + } + + objout(); + +}/* * * * * * * * * * * END OF aohand() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the handler for opcodes which perform short * + * (eight-bit) relative jumps. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +sjhand(j) + + register int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF sjhand() * * * * * * * * * */ + + register int k; + int m; + + objini(j); + + FETCH(m); + + if (m & 0x80) + k = 0xff00; + else + k = 0; + + k |= m; + + printf("%s\t%s\t\t| loc %05.5lx\n",optab[j].text, + lookup((PC + k + 1L),N_TEXT,LOOK_REL,-1L), + (PC + k + 1L)); + + objout(); + +}/* * * * * * * * * * * END OF sjhand() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the handler for a loosely-knit family of op- * + * codes which perform arithmetic and logical operations, * + * and which take immediate data. The routine's logic is * + * rather complex, so, in an effort to avoid additional * + * complexity, the search for external references in the * + * relocation table has been dispensed with. Eager hackers * + * can try their hand at coding such a search. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +imhand(j) + + register int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF imhand() * * * * * * * * * */ + + unsigned long pc; + register int k; + int offset, oflag, immed, iflag, mod, opi, w, rm; + int m, n; + static char a[100], b[30]; + + objini(j); + + FETCH(k); + + pc = PC + 1; + + offset = 0; + mod = (k & 0xc0) >> 6; + opi = (k & 0x38) >> 3; + w = j & 1; + rm = k & 7; + + if ((j & 2) + && ((opi == 1) + || (opi == 4) + || (opi == 6))) + { + badseq(j,k); + return; + } + + strcpy(a,OPFAM[opi]); + + if ( ! w ) + strcat(a,"b"); + + if ((oflag = mod) > 2) + oflag = 0; + + if ((mod == 0) && (rm == 6)) + { + FETCH(m); + FETCH(n); + offset = (n << 8) | m; + } + else if (oflag) + if (oflag == 2) + { + FETCH(m); + FETCH(n); + offset = (n << 8) | m; + } + else + { + FETCH(m); + if (m & 0x80) + n = 0xff00; + else + n = 0; + offset = n | m; + } + + switch (j & 3) + { + case 0 : + case 2 : + FETCH(immed); + iflag = 0; + break; + case 1 : + FETCH(m); + FETCH(n); + immed = (n << 8) | m; + iflag = 1; + break; + case 3 : + FETCH(immed); + if (immed & 0x80) + immed &= 0xff00; + iflag = 0; + break; + } + + strcat(a,"\t"); + + switch (mod) + { + case 0 : + if (rm == 6) + strcat(a, + lookup((long)(offset),N_DATA,LOOK_ABS,pc)); + else + { + sprintf(b,"(%s)",REGS0[rm]); + strcat(a,b); + } + break; + case 1 : + case 2 : + if (mod == 1) + strcat(a,"*"); + else + strcat(a,"#"); + sprintf(b,"%d(",offset); + strcat(a,b); + strcat(a,REGS1[rm]); + strcat(a,")"); + break; + case 3 : + strcat(a,REGS[(w << 3) | rm]); + break; + } + + strcat(a,","); + if (iflag) + strcat(a,"#"); + else + strcat(a,"*"); + sprintf(b,"%d",immed); + strcat(a,b); + + printf("%s\n",a); + + objout(); + +}/* * * * * * * * * * * END OF imhand() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the handler for various "mov"-type opcodes * + * which use the mod, reg, and r/m fields of the second * + * code byte in a standard, straightforward way. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +mvhand(j) + + int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF mvhand() * * * * * * * * * */ + + register int k, m = j; + + objini(j); + + FETCH(k); + + if ((m == 0x84) || (m == 0x85) /* Kind of kludgey */ + || (m == 0xc4) || (m == 0xc5) + || (m == 0x8d)) + if (m & 0x40) + m |= 0x03; + else + m |= 0x02; + + printf("%s\t%s\n",optab[j].text,mtrans(m,k,TR_STD)); + + objout(); + +}/* * * * * * * * * * * END OF mvhand() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the handler for segment-register "mov" opcodes. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +mshand(j) + + register int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF mshand() * * * * * * * * * */ + + register int k; + + objini(j); + + FETCH(k); + + if (k & 0x20) + { + badseq(j,k); + return; + } + + printf("%s\t%s\n",optab[j].text,mtrans(j,k,TR_SEG)); + + objout(); + +}/* * * * * * * * * * * END OF mshand() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the handler for pops, other than single-byte * + * pops. (The 8088 allows popping into any register, or * + * directly into memory, accessed either immediately or * + * through a register and an index.) * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +pohand(j) + + register int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF pohand() * * * * * * * * * */ + + char *a; + register int k; + + objini(j); + + FETCH(k); + + if (k & 0x38) + { + badseq(j,k); + return; + } + + printf("%s\t",optab[j].text); + + a = mtrans((j & 0xfd),k,TR_STD); + + mtrunc(a); + + printf("%s\n",a); + + objout(); + +}/* * * * * * * * * * * END OF pohand() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the handler routine for intersegment calls and * + * jumps. Its output is never symbolic, because the host * + * linker does not allow symbolic intersegment address * + * references except by means of symbolic constants, and * + * any such constants in the symbol table, even if they * + * are of the appropriate value, may be misleading. In * + * compiled code, intersegment references should not be * + * encountered, and even in assembled code, they should * + * occur infrequently. If and when they do occur, however, * + * they will be disassembled in absolute form. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +cihand(j) + + int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF cihand() * * * * * * * * * */ + + register int m, n; + + objini(j); + + printf("%s\t",optab[j].text); + + FETCH(m); + FETCH(n); + + printf("#0x%04.4x,",((n << 8) | m)); + + FETCH(m); + FETCH(n); + + printf("#0x%04.4x\n",((n << 8) | m)); + + objout(); + +}/* * * * * * * * * * * END OF cihand() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the handler for "mov" opcodes with immediate * + * data. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +mihand(j) + + register int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF mihand() * * * * * * * * * */ + + register int k; + int m, n; + char b[80]; + + objini(j); + + printf("%s",optab[j].text); + + if (j & 8) + { + FETCH(m); + FETCH(n); + k = ((n << 8) | m); + if (lookext((long)(k),(PC - 1),b)) + printf("#%s\n",b); + else + printf("#%d\n",k); + } + else + { + FETCH(m); + printf("*%d\n",m); + } + + objout(); + +}/* * * * * * * * * * * END OF mihand() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the handler for a family of quick-move opcodes. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +mqhand(j) + + int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF mqhand() * * * * * * * * * */ + + unsigned long pc; + register int m, n; + + objini(j); + + pc = PC + 1; + + FETCH(m); + FETCH(n); + + m = (n << 8) | m; + + printf("%s\t",optab[j].text); + + if (j & 2) + printf("%s,%s\n", + lookup((long)(m),N_DATA,LOOK_ABS,pc), + REGS[(j & 1) << 3]); + else + printf("%s,%s\n", + REGS[(j & 1) << 3], + lookup((long)(m),N_DATA,LOOK_ABS,pc)); + + objout(); + +}/* * * * * * * * * * * END OF mqhand() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the handler for a family of quick-test opcodes. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +tqhand(j) + + int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF tqhand() * * * * * * * * * */ + + register int m, n; + int k; + char b[80]; + + objini(j); + + printf("%s\t%s,",optab[j].text,REGS[(j & 1) << 3]); + + FETCH(m); + + if (j & 1) + { + FETCH(n); + k = ((n << 8) | m); + if (lookext((long)(k),(PC - 1),b)) + printf("#%s\n",b); + else + printf("#%d\n",k); + } + else + { + if (m & 80) + m |= 0xff00; + printf("*%d\n",m); + } + + objout(); + +}/* * * * * * * * * * * END OF tqhand() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the handler for multiple-byte "return" opcodes. * + * The 8088 allows returns to take an optional 16-bit ar- * + * gument, which reflects the amount to be added to SP * + * after the pop of the return address. The idea is to * + * facilitate the use of local parameters on the stack. * + * After some rumination, it was decided to disassemble * + * any such arguments as absolute quantities, rather than * + * rummaging through the symbol table for possible corre- * + * sponding constants. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +rehand(j) + + int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF rehand() * * * * * * * * * */ + + register int m, n; + + objini(j); + + FETCH(m); + FETCH(n); + + m = (n << 8) | m; + + printf("%s\t#0x%04.4x\n",optab[j].text,m); + + objout(); + +}/* * * * * * * * * * * END OF rehand() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the handler for "mov" opcodes involving memory * + * and immediate data. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +mmhand(j) + + register int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF mmhand() * * * * * * * * * */ + + char *a; + register int k; + char b[80]; + + objini(j); + + FETCH(k); + + if (k & 0x38) + { + badseq(j,k); + return; + } + + printf("%s",optab[j].text); + + if ( ! (j & 1) ) + putchar('b'); + + a = mtrans((j & 0xfd),(k & 0xc7),TR_STD); + + mtrunc(a); + + printf("\t%s,",a); + + if (j & 1) + { + FETCH(j); + FETCH(k); + k = (k << 8) | j; + if (lookext((long)(k),(PC - 1),b)) + printf("#%s\n",b); + else + printf("#%d\n",k); + } + else + { + FETCH(k); + printf("*%d\n",k); + } + + objout(); + +}/* * * * * * * * * * * END OF mmhand() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the handler for the 8088 family of shift and * + * rotate instructions. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +srhand(j) + + register int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF srhand() * * * * * * * * * */ + + char *a; + register int k; + + objini(j); + + FETCH(k); + + if ((k & 0x38) == 0x30) + { + badseq(j,k); + return; + } + + printf("%s",OPFAM[((k & 0x38) >> 3) + 16]); + + if ( ! (j & 1) ) + putchar('b'); + + a = mtrans((j & 0xfd),(k & 0xc7),TR_STD); + + mtrunc(a); + + printf("\t%s",a); + + if (j & 2) + printf(",cl\n"); + else + printf(",*1\n"); + + objout(); + +}/* * * * * * * * * * * END OF srhand() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the handler for the ASCII-adjust opcodes. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +aahand(j) + + register int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF aahand() * * * * * * * * * */ + + register int k; + + objini(j); + + FETCH(k); + + if (k != 0x0a) + { + badseq(j,k); + return; + } + + printf("%s\n",optab[j].text); + + objout(); + +}/* * * * * * * * * * * END OF aahand() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the handler for port I/O opcodes which specify * + * the port address as an immediate operand. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +iohand(j) + + register int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF iohand() * * * * * * * * * */ + + register int k; + + objini(j); + + FETCH(k); + + printf("%s\t0x%02.2x\n",optab[j].text,k); + + objout(); + +}/* * * * * * * * * * * END OF iohand() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the handler for opcodes which perform long * + * (sixteen-bit) relative jumps and calls. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +ljhand(j) + + register int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF ljhand() * * * * * * * * * */ + + register int k; + int m, n; + + objini(j); + + FETCH(m); + FETCH(n); + + k = (n << 8) | m; + + printf("%s\t%s\t\t| loc %05.5lx\n",optab[j].text, + lookup((PC + k + 1L),N_TEXT,LOOK_LNG,(PC - 1L)), + (PC + k + 1L)); + + objout(); + +}/* * * * * * * * * * * END OF ljhand() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the handler for a pair of oddball opcodes (0xf6 * + * and 0xf7) which perform miscellaneous arithmetic opera- * + * tions not dealt with elsewhere. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +mahand(j) + + register int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF mahand() * * * * * * * * * */ + + char *a; + register int k; + char b[80]; + + objini(j); + + FETCH(k); + + a = mtrans((j & 0xfd),(k & 0xc7),TR_STD); + + mtrunc(a); + + switch (((k = objbuf[1]) & 0x38) >> 3) + { + case 0 : + printf("\ttest"); + break; + case 1 : + badseq(j,k); + return; + case 2 : + printf("\tnot"); + break; + case 3 : + printf("\tneg"); + break; + case 4 : + printf("\tmul"); + break; + case 5 : + printf("\timul"); + break; + case 6 : + printf("\tdiv"); + break; + case 7 : + printf("\tidiv"); + break; + } + + if ( ! (j & 1) ) + putchar('b'); + + printf("\t%s",a); + + if (k & 0x38) + putchar('\n'); + else + if (j & 1) + { + FETCH(j); + FETCH(k); + k = (k << 8) | j; + if (lookext((long)(k),(PC - 1),b)) + printf(",#%s\n",b); + else + printf(",#%d\n",k); + } + else + { + FETCH(k); + printf(",*%d\n",k); + } + + objout(); + +}/* * * * * * * * * * * END OF mahand() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the handler for miscellaneous jump, call, push, * + * and increment/decrement opcodes (0xfe and 0xff) which * + * are not dealt with elsewhere. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +mjhand(j) + + register int j; /* Pointer to optab[] entry */ + +{/* * * * * * * * * * START OF mjhand() * * * * * * * * * */ + + char *a; + register int k; + + objini(j); + + FETCH(k); + + a = mtrans((j & 0xfd),(k & 0xc7),TR_STD); + + mtrunc(a); + + switch (((k = objbuf[1]) & 0x38) >> 3) + { + case 0 : + printf("\tinc"); + if ( ! (j & 1) ) + putchar('b'); + putchar('\t'); + break; + case 1 : + printf("\tdec"); + if ( ! (j & 1) ) + putchar('b'); + putchar('\t'); + break; + case 2 : + if (j & 1) + printf("\tcall\t@"); + else + goto BAD; + break; + case 3 : + if (j & 1) + printf("\tcalli\t@"); + else + goto BAD; + break; + case 4 : + if (j & 1) + printf("\tjmp\t@"); + else + goto BAD; + break; + case 5 : + if (j & 1) + printf("\tjmpi\t@"); + else + goto BAD; + break; + case 6 : + if (j & 1) + printf("\tpush\t"); + else + goto BAD; + break; + case 7 : + BAD : + badseq(j,k); + return; + } + + printf("%s\n",a); + + objout(); + +}/* * * * * * * * * * * END OF mjhand() * * * * * * * * * * */ + + diff --git a/dis88/dismain.c b/dis88/dismain.c new file mode 100644 index 0000000..f9ec6c5 --- /dev/null +++ b/dis88/dismain.c @@ -0,0 +1,650 @@ +static char *sccsid = "@(#) dismain.c, Ver. 2.1 created 00:00:00 87/09/01"; + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 1987 G. M. Harding, all rights reserved * + * * + * Permission to copy and redistribute is hereby granted, * + * provided full source code, with all copyright notices, * + * accompanies any redistribution. * + * * + * This file contains the source code for the machine- * + * independent portions of a disassembler program to run * + * in a Unix (System III) environment. It expects, as its * + * input, a file in standard a.out format, optionally con- * + * taining symbol table information. If a symbol table is * + * present, it will be used in the disassembly; otherwise, * + * all address references will be literal (absolute). * + * * + * The disassembler program was originally written for an * + * Intel 8088 CPU. However, all details of the actual CPU * + * architecture are hidden in three machine-specific files * + * named distabs.c, dishand.c, and disfp.c (the latter * + * file is specific to the 8087 numeric co-processor). The * + * code in this file is generic, and should require mini- * + * mal revision if a different CPU is to be targeted. If a * + * different version of Unix is to be targeted, changes to * + * this file may be necessary, and if a completely differ- * + * ent OS is to be targeted, all bets are off. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "dis.h" /* Disassembler declarations */ + +extern char *release; /* Contains release string */ +static char *IFILE = NULL; /* Points to input file name */ +static char *OFILE = NULL; /* Points to output file name */ +static char *PRG; /* Name of invoking program */ +static unsigned long zcount; /* Consecutive "0" byte count */ +int objflg = 0; /* Flag: output object bytes */ + +#define unix 1 +#define i8086 1 +#define ibmpc 1 + +#if unix && i8086 && ibmpc /* Set the CPU identifier */ +static int cpuid = 1; +#else +static int cpuid = 0; +#endif + +_PROTOTYPE(static void usage, (char *s )); +_PROTOTYPE(static void fatal, (char *s, char *t )); +_PROTOTYPE(static void zdump, (unsigned long beg )); +_PROTOTYPE(static void prolog, (void)); +_PROTOTYPE(static void distext, (void)); +_PROTOTYPE(static void disdata, (void)); +_PROTOTYPE(static void disbss, (void)); + +_PROTOTYPE(static char *invoker, (char *s)); +_PROTOTYPE(static int objdump, (char *c)); +_PROTOTYPE(static char *getlab, (int type)); +_PROTOTYPE(static void prolog, (void)); + + /* * * * * * * MISCELLANEOUS UTILITY FUNCTIONS * * * * * * */ + +static void +usage(s) + register char *s; +{ + fprintf(stderr,"Usage: %s [-o] ifile [ofile]\n",s); + exit(-1); +} + +static void +fatal(s,t) + register char *s, *t; +{ + fprintf(stderr,"%s: %s\n",s,t); + exit(-1); +} + +static void +zdump(beg) + unsigned long beg; +{ + beg = PC - beg; + if (beg > 1L) + printf("\t.zerow\t%ld\n",(beg >> 1)); + if (beg & 1L) + printf("\t.byte\t0\n"); +} + +static char * +invoker(s) + register char *s; +{ + register int k; + + k = strlen(s); + + while (k--) + if (s[k] == '/') + { + s += k; + ++s; + break; + } + + return (s); +} + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This rather tricky routine supports the disdata() func- * + * tion. Its job is to output the code for a sequence of * + * data bytes whenever the object buffer is full, or when * + * a symbolic label is to be output. However, it must also * + * keep track of consecutive zero words so that lengthy * + * stretches of null data can be compressed by the use of * + * an appropriate assembler pseudo-op. It does this by * + * setting and testing a file-wide flag which counts suc- * + * cessive full buffers of null data. The function returns * + * a logical TRUE value if it outputs anything, logical * + * FALSE otherwise. (This enables disdata() to determine * + * whether to output a new synthetic label when there is * + * no symbol table.) * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +static int +objdump(c) + + register char *c; + +{/* * * * * * * * * * START OF objdump() * * * * * * * * * */ + + register int k; + int retval = 0; + + if (objptr == OBJMAX) + { + for (k = 0; k < OBJMAX; ++k) + if (objbuf[k]) + break; + if (k == OBJMAX) + { + zcount += k; + objptr = 0; + if (c == NULL) + return (retval); + } + } + + if (zcount) + { + printf("\t.zerow\t%ld\n",(zcount >> 1)); + ++retval; + zcount = 0L; + } + + if (objptr) + { + printf("\t.byte\t"); + ++retval; + } + else + return (retval); + + for (k = 0; k < objptr; ++k) + { + printf("0x%02.2x",objbuf[k]); + if (k < (objptr - 1)) + putchar(','); + else + putchar('\n'); + } + + objptr = 0; + + return (retval); + +}/* * * * * * * * * * END OF objdump() * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This routine, called at the beginning of the input * + * cycle for each object byte, and before any interpreta- * + * tion is attempted, searches the symbol table for any * + * symbolic name with a value corresponding to the cur- * + * rent PC and a type corresponding to the segment type * + * (i.e., text, data, or bss) specified by the function's * + * argument. If any such name is found, a pointer to it is * + * returned; otherwise, a NULL pointer is returned. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +static char * +getlab(type) +register int type; +{/* * * * * * * * * * START OF getlab() * * * * * * * * * */ + + register int k; + static char b[48], c[32]; + + if (symptr < 0) + if ((type == N_TEXT) + || ((type == N_DATA) && ( ! objptr ) && ( ! zcount ))) + { + if (type == N_TEXT) + sprintf(b,"T%05.5lx:",PC); + else + sprintf(b,"D%05.5lx:",PC); + return (b); + } + else + return (NULL); + + for (k = 0; k <= symptr; ++k) + if ((symtab[k].n_value == PC) + && ((symtab[k].n_sclass & N_SECT) == type)) + { + sprintf(b,"%s:\n",getnam(k)); + if (objflg && (type != N_TEXT)) + sprintf(c,"| %05.5lx\n",PC); + strcat(b,c); + return (b); + } + + return (NULL); + +}/* * * * * * * * * * * END OF getlab() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This routine performs a preliminary scan of the symbol * + * table, before disassembly begins, and outputs declara- * + * tions of globals and constants. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +static void +prolog() + +{/* * * * * * * * * * START OF prolog() * * * * * * * * * */ + + register int j, flag; + + fflush(stdout); + + if (symptr < 0) + return; + + for (j = flag = 0; j <= symptr; ++j) + if ((symtab[j].n_sclass & N_CLASS) == C_EXT) + if (((symtab[j].n_sclass & N_SECT) > N_UNDF) + && ((symtab[j].n_sclass & N_SECT) < N_COMM)) + { + char *c = getnam(j); + printf("\t.globl\t%s",c); + if (++flag == 1) + { + putchar('\t'); + if (strlen(c) < 8) + putchar('\t'); + printf("| Internal global\n"); + } + else + putchar('\n'); + } + else + if (symtab[j].n_value) + { + char *c = getnam(j); + printf("\t.comm\t%s,0x%08.8lx",c, + symtab[j].n_value); + if (++flag == 1) + printf("\t| Internal global\n"); + else + putchar('\n'); + } + + if (flag) + putchar('\n'); + fflush(stdout); + + for (j = flag = 0; j <= relptr; ++j) + if (relo[j].r_symndx < S_BSS) + { + char *c = getnam(relo[j].r_symndx); + ++flag; + printf("\t.globl\t%s",c); + putchar('\t'); + if (strlen(c) < 8) + putchar('\t'); + printf("| Undef: %05.5lx\n",relo[j].r_vaddr); + } + + if (flag) + putchar('\n'); + fflush(stdout); + + for (j = flag = 0; j <= symptr; ++j) + if ((symtab[j].n_sclass & N_SECT) == N_ABS) + { + char *c = getnam(j); + printf("%s=0x%08.8lx",c,symtab[j].n_value); + if (++flag == 1) + { + printf("\t\t"); + if (strlen(c) < 5) + putchar('\t'); + printf("| Literal\n"); + } + else + putchar('\n'); + } + + if (flag) + putchar('\n'); + fflush(stdout); + +}/* * * * * * * * * * * END OF prolog() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This function is responsible for disassembly of the * + * object file's text segment. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +static void +distext() + +{/* * * * * * * * * * START OF distext() * * * * * * * * * */ + + char *c; + register int j; + register void (*f)(); + + for (j = 0; j < (int)(HDR.a_hdrlen); ++j) + getchar(); + + printf("| %s, %s\n\n",PRG,release); + + printf("| @("); + + printf("#)\tDisassembly of %s",IFILE); + + if (symptr < 0) + printf(" (no symbols)\n\n"); + else + printf("\n\n"); + + if (HDR.a_flags & A_EXEC) + printf("| File is executable\n\n"); + + if (HDR.a_flags & A_SEP) + { + printf("| File has split I/D space, and may have\n"); + printf("| extraneous instructions in text segment\n\n"); + } + + prolog(); + + printf("\t.text\t\t\t| loc = %05.5lx, size = %05.5lx\n\n", + PC,HDR.a_text); + fflush(stdout); + + segflg = 0; + + for (PC = 0L; PC < HDR.a_text; ++PC) + { + j = getchar() & 0xff; + if ((j == 0) && ((PC + 1L) == HDR.a_text)) + { + ++PC; + break; + } + if ((c = getlab(N_TEXT)) != NULL) + printf("%s",c); + f = optab[j].func; + (*f)(j); + fflush(stdout); + } + +}/* * * * * * * * * * END OF distext() * * * * * * * * * */ + +Fetch() +{ + int p; + ++PC; + if( symptr>=0 && getlab(N_TEXT) != NULL ) { --PC; return -1; } + +/* #define FETCH(p) ++PC; p = getchar() & 0xff; objbuf[objptr++] = p */ + p = getchar() & 0xff; + objbuf[objptr++] = p; + return p; +} + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This function handles the object file's data segment. * + * There is no good way to disassemble a data segment, be- * + * cause it is impossible to tell, from the object code * + * alone, what each data byte refers to. If it refers to * + * an external symbol, the reference can be resolved from * + * the relocation table, if there is one. However, if it * + * refers to a static symbol, it cannot be distinguished * + * from numeric, character, or other pointer data. In some * + * cases, one might make a semi-educated guess as to the * + * nature of the data, but such guesses are inherently * + * haphazard, and they are bound to be wrong a good por- * + * tion of the time. Consequently, the data segment is * + * disassembled as a byte stream, which will satisfy no * + * one but which, at least, will never mislead anyone. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +static void +disdata() + +{/* * * * * * * * * * START OF disdata() * * * * * * * * * */ + + register char *c; + register int j; + unsigned long end; + + putchar('\n'); + + if (HDR.a_flags & A_SEP) + { + PC = 0L; + end = HDR.a_data; + } + else + end = HDR.a_text + HDR.a_data; + + printf("\t.data\t\t\t| loc = %05.5lx, size = %05.5lx\n\n", + PC,HDR.a_data); + + segflg = 0; + + for (objptr = 0, zcount = 0L; PC < end; ++PC) + { + if ((c = getlab(N_DATA)) != NULL) + { + objdump(c); + printf("%s",c); + } + if (objptr >= OBJMAX) + if (objdump(NULL) && (symptr < 0)) + printf("D%05.5lx:",PC); + j = getchar() & 0xff; + objbuf[objptr++] = j; + } + + objdump(""); + +}/* * * * * * * * * * END OF disdata() * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This function handles the object file's bss segment. * + * Disassembly of the bss segment is easy, because every- * + * thing in it is zero by definition. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +static void disbss() + +{/* * * * * * * * * * START OF disbss() * * * * * * * * * */ + + register int j; + register char *c; + unsigned long beg, end; + + putchar('\n'); + + if (HDR.a_flags & A_SEP) + end = HDR.a_data + HDR.a_bss; + else + end = HDR.a_text + HDR.a_data + HDR.a_bss; + + printf("\t.bss\t\t\t| loc = %05.5lx, size = %05.5lx\n\n", + PC,HDR.a_bss); + + segflg = 0; + + for (beg = PC; PC < end; ++PC) + if ((c = getlab(N_BSS)) != NULL) + { + if (PC > beg) + { + zdump(beg); + beg = PC; + } + printf("%s",c); + } + + if (PC > beg) + zdump(beg); + +}/* * * * * * * * * * * END OF disbss() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This is the program entry point. The command line is * + * searched for an input file name, which must be present. * + * An optional output file name is also permitted; if none * + * is found, standard output is the default. One command- * + * line option is available: "-o", which causes the pro- * + * gram to include object code in comments along with its * + * mnemonic output. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +main(argc,argv) + + int argc; /* Command-line args from OS */ + register char **argv; + +{/* * * * * * * * * * * START OF main() * * * * * * * * * * */ + + char a[1024]; + register int fd; + long taboff, tabnum; + long reloff, relnum; + + PRG = invoker(*argv); + + while (*++argv != NULL) /* Process command-line args */ + if (**argv == '-') + switch (*++*argv) + { + case 'o' : + if (*++*argv) + usage(PRG); + else + ++objflg; + break; + default : + usage(PRG); + } + else + if (IFILE == NULL) + IFILE = *argv; + else if (OFILE == NULL) + OFILE = *argv; + else + usage(PRG); + + if (IFILE == NULL) + usage(PRG); + else + if ((fd = open(IFILE,0)) < 0) + { + sprintf(a,"can't access input file %s",IFILE); + fatal(PRG,a); + } + + if (OFILE != NULL) + if (freopen(OFILE,"w",stdout) == NULL) + { + sprintf(a,"can't open output file %s",OFILE); + fatal(PRG,a); + } + + if ( ! cpuid ) + fprintf(stderr,"%s: warning: host/cpu clash\n",PRG); + + read(fd, (char *) &HDR,sizeof(struct exec)); + + if (BADMAG(HDR)) + { + sprintf(a,"input file %s not in object format",IFILE); + fatal(PRG,a); + } + + if (HDR.a_cpu != A_I8086) + { + sprintf(a,"%s is not an 8086/8088 object file",IFILE); + fatal(PRG,a); + } + + if (HDR.a_hdrlen <= A_MINHDR) + HDR.a_trsize = HDR.a_drsize = 0L; + HDR.a_tbase = HDR.a_dbase = 0L; +/* AST emergency patch + HDR.a_lnums = HDR.a_toffs = 0L; +*/ + + reloff = HDR.a_text /* Compute reloc data offset */ + + HDR.a_data + + (long)(HDR.a_hdrlen); + + relnum = + (HDR.a_trsize + HDR.a_drsize) / sizeof(struct reloc); + + taboff = reloff /* Compute name table offset */ + + HDR.a_trsize + + HDR.a_drsize; + + tabnum = HDR.a_syms / sizeof(struct nlist); + + if (relnum > MAXSYM) + fatal(PRG,"reloc table overflow"); + + if (tabnum > MAXSYM) + fatal(PRG,"symbol table overflow"); + + if (relnum) /* Get reloc data */ + if (lseek(fd,reloff,0) != reloff) + fatal(PRG,"lseek error"); + else + { + for (relptr = 0; relptr < relnum; ++relptr) + read(fd, (char *) &relo[relptr],sizeof(struct reloc)); + relptr--; + } + + if (tabnum) /* Read in symtab */ + if (lseek(fd,taboff,0) != taboff) + fatal(PRG,"lseek error"); + else + { + for (symptr = 0; symptr < tabnum; ++symptr) + read(fd, (char *) &symtab[symptr],sizeof(struct nlist)); + symptr--; + } + else + fprintf(stderr,"%s: warning: no symbols\n",PRG); + + close(fd); + + if (freopen(IFILE,"r",stdin) == NULL) + { + sprintf(a,"can't reopen input file %s",IFILE); + fatal(PRG,a); + } + + distext(); + + disdata(); + + disbss(); + + exit(0); + +}/* * * * * * * * * * * END OF main() * * * * * * * * * * */ diff --git a/dis88/disrel.c b/dis88/disrel.c new file mode 100644 index 0000000..37f3221 --- /dev/null +++ b/dis88/disrel.c @@ -0,0 +1,30 @@ +static char *copyright = + "@(#) Copyright (C) 1987 G. M. Harding, all rights reserved"; + +static char *sccsid = + "@(#) disrel.c, Ver. 2.1 created 00:00:00 87/09/01"; + +char *release = + "release 2.1 (MINIX)"; + + /* + ** + ** This file documents the major revisions to the 8088 sym- + ** bolic disassembler. It also contains the release string + ** which is output at the head of each disassembly, and the + ** copyright string which must be incorporated in any code + ** distribution. + ** + ** Permission to copy and redistribute is hereby granted, + ** provided full source code, with all copyright notices, + ** accompanies any redistribution. + ** + ** REVISION HISTORY: + ** + ** SEP 87: + ** After internal shakeout, released on Usenet. + ** + ** JUN 88: + ** Ported to MINIX + */ + diff --git a/dis88/distabs.c b/dis88/distabs.c new file mode 100644 index 0000000..283fe42 --- /dev/null +++ b/dis88/distabs.c @@ -0,0 +1,708 @@ +static char *sccsid = + "@(#) distabs.c, Ver. 2.1 created 00:00:00 87/09/01"; + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 1987 G. M. Harding, all rights reserved * + * * + * Permission to copy and redistribute is hereby granted, * + * provided full source code, with all copyright notices, * + * accompanies any redistribution. * + * * + * This file contains the lookup tables and other data * + * structures for the Intel 8088 symbolic disassembler. It * + * also contains a few global routines which facilitate * + * access to the tables, for use primarily by the handler * + * functions. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "dis.h" /* Disassembler declarations */ + +struct exec HDR; /* Used to hold header info */ + +struct nlist symtab[MAXSYM]; /* Array of symbol table info */ + +struct reloc relo[MAXSYM]; /* Array of relocation info */ + +int symptr = -1, /* Index into symtab[] */ + relptr = -1; /* Index into relo[] */ + +char *REGS[] = /* Table of register names */ + { + "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh", + "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", + "es", "cs", "ss", "ds" + }; + +char *REGS0[] = /* Mode 0 register name table */ + { + "bx_si", "bx_di", "bp_si", "bp_di", "si", "di", "", "bx" + }; + +char *REGS1[] = /* Mode 1 register name table */ + { + "bx_si", "bx_di", "bp_si", "bp_di", "si", "di", "bp", "bx" + }; + +int symrank[6][6] = /* Symbol type/rank matrix */ + { + /* UND ABS TXT DAT BSS COM */ + /* UND */ 5, 4, 1, 2, 3, 0, + /* ABS */ 1, 5, 4, 3, 2, 0, + /* TXT */ 4, 1, 5, 3, 2, 0, + /* DAT */ 3, 1, 2, 5, 4, 0, + /* BSS */ 3, 1, 2, 4, 5, 0, + /* COM */ 2, 0, 1, 3, 4, 5 + }; + + /* * * * * * * * * * * * OPCODE DATA * * * * * * * * * * * */ + +char ADD[] = "\tadd", /* Mnemonics by family */ + OR[] = "\tor", + ADC[] = "\tadc", + SBB[] = "\tsbb", + AND[] = "\tand", + SUB[] = "\tsub", + XOR[] = "\txor", + CMP[] = "\tcmp", + NOT[] = "\tnot", + NEG[] = "\tneg", + MUL[] = "\tmul", + DIV[] = "\tdiv", + MOV[] = "\tmov", + ESC[] = "\tesc", + TEST[] = "\ttest", + AMBIG[] = "", + ROL[] = "\trol", + ROR[] = "\tror", + RCL[] = "\trcl", + RCR[] = "\trcr", + SAL[] = "\tsal", + SHR[] = "\tshr", + SHL[] = "\tshl", + SAR[] = "\tsar"; + +char *OPFAM[] = /* Family lookup table */ + { + ADD, OR, ADC, SBB, AND, SUB, XOR, CMP, + NOT, NEG, MUL, DIV, MOV, ESC, TEST, AMBIG, + ROL, ROR, RCL, RCR, SAL, SHR, SHL, SAR + }; + +struct opcode optab[] = /* Table of opcode data */ + { + ADD, aohand, 2, 4, /* 0x00 */ + ADD, aohand, 2, 4, /* 0x01 */ + ADD, aohand, 2, 4, /* 0x02 */ + ADD, aohand, 2, 4, /* 0x03 */ + ADD, aohand, 2, 2, /* 0x04 */ + ADD, aohand, 3, 3, /* 0x05 */ + "\tpush\tes", sbhand, 1, 1, /* 0x06 */ + "\tpop\tes", sbhand, 1, 1, /* 0x07 */ + OR, aohand, 2, 4, /* 0x08 */ + OR, aohand, 2, 4, /* 0x09 */ + OR, aohand, 2, 4, /* 0x0a */ + OR, aohand, 2, 4, /* 0x0b */ + OR, aohand, 2, 2, /* 0x0c */ + OR, aohand, 3, 3, /* 0x0d */ + "\tpush\tcs", sbhand, 1, 1, /* 0x0e */ + NULL, dfhand, 0, 0, /* 0x0f */ + ADC, aohand, 2, 4, /* 0x10 */ + ADC, aohand, 2, 4, /* 0x11 */ + ADC, aohand, 2, 4, /* 0x12 */ + ADC, aohand, 2, 4, /* 0x13 */ + ADC, aohand, 2, 2, /* 0x14 */ + ADC, aohand, 3, 3, /* 0x15 */ + "\tpush\tss", sbhand, 1, 1, /* 0x16 */ + "\tpop\tss", sbhand, 1, 1, /* 0x17 */ + SBB, aohand, 2, 4, /* 0x18 */ + SBB, aohand, 2, 4, /* 0x19 */ + SBB, aohand, 2, 4, /* 0x1a */ + SBB, aohand, 2, 4, /* 0x1b */ + SBB, aohand, 2, 2, /* 0x1c */ + SBB, aohand, 3, 3, /* 0x1d */ + "\tpush\tds", sbhand, 1, 1, /* 0x1e */ + "\tpop\tds", sbhand, 1, 1, /* 0x1f */ + AND, aohand, 2, 4, /* 0x20 */ + AND, aohand, 2, 4, /* 0x21 */ + AND, aohand, 2, 4, /* 0x22 */ + AND, aohand, 2, 4, /* 0x23 */ + AND, aohand, 2, 2, /* 0x24 */ + AND, aohand, 3, 3, /* 0x25 */ + "\tseg\tes", sbhand, 1, 1, /* 0x26 */ + "\tdaa", sbhand, 1, 1, /* 0x27 */ + SUB, aohand, 2, 4, /* 0x28 */ + SUB, aohand, 2, 4, /* 0x29 */ + SUB, aohand, 2, 4, /* 0x2a */ + SUB, aohand, 2, 4, /* 0x2b */ + SUB, aohand, 2, 2, /* 0x2c */ + SUB, aohand, 3, 3, /* 0x2d */ + "\tseg\tcs", sbhand, 1, 1, /* 0x2e */ + "\tdas", sbhand, 1, 1, /* 0x2f */ + XOR, aohand, 2, 4, /* 0x30 */ + XOR, aohand, 2, 4, /* 0x31 */ + XOR, aohand, 2, 4, /* 0x32 */ + XOR, aohand, 2, 4, /* 0x33 */ + XOR, aohand, 2, 2, /* 0x34 */ + XOR, aohand, 3, 3, /* 0x35 */ + "\tseg\tss", sbhand, 1, 1, /* 0x36 */ + "\taaa", sbhand, 1, 1, /* 0x37 */ + CMP, aohand, 2, 4, /* 0x38 */ + CMP, aohand, 2, 4, /* 0x39 */ + CMP, aohand, 2, 4, /* 0x3a */ + CMP, aohand, 2, 4, /* 0x3b */ + CMP, aohand, 2, 2, /* 0x3c */ + CMP, aohand, 3, 3, /* 0x3d */ + "\tseg\tds", sbhand, 1, 1, /* 0x3e */ + "\taas", sbhand, 1, 1, /* 0x3f */ + "\tinc\tax", sbhand, 1, 1, /* 0x40 */ + "\tinc\tcx", sbhand, 1, 1, /* 0x41 */ + "\tinc\tdx", sbhand, 1, 1, /* 0x42 */ + "\tinc\tbx", sbhand, 1, 1, /* 0x43 */ + "\tinc\tsp", sbhand, 1, 1, /* 0x44 */ + "\tinc\tbp", sbhand, 1, 1, /* 0x45 */ + "\tinc\tsi", sbhand, 1, 1, /* 0x46 */ + "\tinc\tdi", sbhand, 1, 1, /* 0x47 */ + "\tdec\tax", sbhand, 1, 1, /* 0x48 */ + "\tdec\tcx", sbhand, 1, 1, /* 0x49 */ + "\tdec\tdx", sbhand, 1, 1, /* 0x4a */ + "\tdec\tbx", sbhand, 1, 1, /* 0x4b */ + "\tdec\tsp", sbhand, 1, 1, /* 0x4c */ + "\tdec\tbp", sbhand, 1, 1, /* 0x4d */ + "\tdec\tsi", sbhand, 1, 1, /* 0x4e */ + "\tdec\tdi", sbhand, 1, 1, /* 0x4f */ + "\tpush\tax", sbhand, 1, 1, /* 0x50 */ + "\tpush\tcx", sbhand, 1, 1, /* 0x51 */ + "\tpush\tdx", sbhand, 1, 1, /* 0x52 */ + "\tpush\tbx", sbhand, 1, 1, /* 0x53 */ + "\tpush\tsp", sbhand, 1, 1, /* 0x54 */ + "\tpush\tbp", sbhand, 1, 1, /* 0x55 */ + "\tpush\tsi", sbhand, 1, 1, /* 0x56 */ + "\tpush\tdi", sbhand, 1, 1, /* 0x57 */ + "\tpop\tax", sbhand, 1, 1, /* 0x58 */ + "\tpop\tcx", sbhand, 1, 1, /* 0x59 */ + "\tpop\tdx", sbhand, 1, 1, /* 0x5a */ + "\tpop\tbx", sbhand, 1, 1, /* 0x5b */ + "\tpop\tsp", sbhand, 1, 1, /* 0x5c */ + "\tpop\tbp", sbhand, 1, 1, /* 0x5d */ + "\tpop\tsi", sbhand, 1, 1, /* 0x5e */ + "\tpop\tdi", sbhand, 1, 1, /* 0x5f */ + NULL, dfhand, 0, 0, /* 0x60 */ + NULL, dfhand, 0, 0, /* 0x61 */ + NULL, dfhand, 0, 0, /* 0x62 */ + NULL, dfhand, 0, 0, /* 0x63 */ + NULL, dfhand, 0, 0, /* 0x64 */ + NULL, dfhand, 0, 0, /* 0x65 */ + NULL, dfhand, 0, 0, /* 0x66 */ + NULL, dfhand, 0, 0, /* 0x67 */ + NULL, dfhand, 0, 0, /* 0x68 */ + NULL, dfhand, 0, 0, /* 0x69 */ + NULL, dfhand, 0, 0, /* 0x6a */ + NULL, dfhand, 0, 0, /* 0x6b */ + NULL, dfhand, 0, 0, /* 0x6c */ + NULL, dfhand, 0, 0, /* 0x6d */ + NULL, dfhand, 0, 0, /* 0x6e */ + NULL, dfhand, 0, 0, /* 0x6f */ + "\tjo", sjhand, 2, 2, /* 0x70 */ + "\tjno", sjhand, 2, 2, /* 0x71 */ + "\tjc", sjhand, 2, 2, /* 0x72 */ + "\tjnc", sjhand, 2, 2, /* 0x73 */ + "\tjz", sjhand, 2, 2, /* 0x74 */ + "\tjnz", sjhand, 2, 2, /* 0x75 */ + "\tjna", sjhand, 2, 2, /* 0x76 */ + "\tja", sjhand, 2, 2, /* 0x77 */ + "\tjs", sjhand, 2, 2, /* 0x78 */ + "\tjns", sjhand, 2, 2, /* 0x79 */ + "\tjp", sjhand, 2, 2, /* 0x7a */ + "\tjnp", sjhand, 2, 2, /* 0x7b */ + "\tjl", sjhand, 2, 2, /* 0x7c */ + "\tjnl", sjhand, 2, 2, /* 0x7d */ + "\tjng", sjhand, 2, 2, /* 0x7e */ + "\tjg", sjhand, 2, 2, /* 0x7f */ + AMBIG, imhand, 3, 5, /* 0x80 */ + AMBIG, imhand, 4, 6, /* 0x81 */ + AMBIG, imhand, 3, 5, /* 0x82 */ + AMBIG, imhand, 3, 5, /* 0x83 */ + TEST, mvhand, 2, 4, /* 0x84 */ + TEST, mvhand, 2, 4, /* 0x85 */ + "\txchg", mvhand, 2, 4, /* 0x86 */ + "\txchg", mvhand, 2, 4, /* 0x87 */ + MOV, mvhand, 2, 4, /* 0x88 */ + MOV, mvhand, 2, 4, /* 0x89 */ + MOV, mvhand, 2, 4, /* 0x8a */ + MOV, mvhand, 2, 4, /* 0x8b */ + MOV, mshand, 2, 4, /* 0x8c */ + "\tlea", mvhand, 2, 4, /* 0x8d */ + MOV, mshand, 2, 4, /* 0x8e */ + "\tpop", pohand, 2, 4, /* 0x8f */ + "\tnop", sbhand, 1, 1, /* 0x90 */ + "\txchg\tax,cx", sbhand, 1, 1, /* 0x91 */ + "\txchg\tax,dx", sbhand, 1, 1, /* 0x92 */ + "\txchg\tax,bx", sbhand, 1, 1, /* 0x93 */ + "\txchg\tax,sp", sbhand, 1, 1, /* 0x94 */ + "\txchg\tax,bp", sbhand, 1, 1, /* 0x95 */ + "\txchg\tax,si", sbhand, 1, 1, /* 0x96 */ + "\txchg\tax,di", sbhand, 1, 1, /* 0x97 */ + "\tcbw", sbhand, 1, 1, /* 0x98 */ + "\tcwd", sbhand, 1, 1, /* 0x99 */ + "\tcalli", cihand, 5, 5, /* 0x9a */ + "\twait", sbhand, 1, 1, /* 0x9b */ + "\tpushf", sbhand, 1, 1, /* 0x9c */ + "\tpopf", sbhand, 1, 1, /* 0x9d */ + "\tsahf", sbhand, 1, 1, /* 0x9e */ + "\tlahf", sbhand, 1, 1, /* 0x9f */ + MOV, mqhand, 3, 3, /* 0xa0 */ + MOV, mqhand, 3, 3, /* 0xa1 */ + MOV, mqhand, 3, 3, /* 0xa2 */ + MOV, mqhand, 3, 3, /* 0xa3 */ + "\tmovb", sbhand, 1, 1, /* 0xa4 */ + "\tmovw", sbhand, 1, 1, /* 0xa5 */ + "\tcmpb", sbhand, 1, 1, /* 0xa6 */ + "\tcmpw", sbhand, 1, 1, /* 0xa7 */ + TEST, tqhand, 2, 2, /* 0xa8 */ + TEST, tqhand, 3, 3, /* 0xa9 */ + "\tstob", sbhand, 1, 1, /* 0xaa */ + "\tstow", sbhand, 1, 1, /* 0xab */ + "\tlodb", sbhand, 1, 1, /* 0xac */ + "\tlodw", sbhand, 1, 1, /* 0xad */ + "\tscab", sbhand, 1, 1, /* 0xae */ + "\tscaw", sbhand, 1, 1, /* 0xaf */ + "\tmov\tal,", mihand, 2, 2, /* 0xb0 */ + "\tmov\tcl,", mihand, 2, 2, /* 0xb1 */ + "\tmov\tdl,", mihand, 2, 2, /* 0xb2 */ + "\tmov\tbl,", mihand, 2, 2, /* 0xb3 */ + "\tmov\tah,", mihand, 2, 2, /* 0xb4 */ + "\tmov\tch,", mihand, 2, 2, /* 0xb5 */ + "\tmov\tdh,", mihand, 2, 2, /* 0xb6 */ + "\tmov\tbh,", mihand, 2, 2, /* 0xb7 */ + "\tmov\tax,", mihand, 3, 3, /* 0xb8 */ + "\tmov\tcx,", mihand, 3, 3, /* 0xb9 */ + "\tmov\tdx,", mihand, 3, 3, /* 0xba */ + "\tmov\tbx,", mihand, 3, 3, /* 0xbb */ + "\tmov\tsp,", mihand, 3, 3, /* 0xbc */ + "\tmov\tbp,", mihand, 3, 3, /* 0xbd */ + "\tmov\tsi,", mihand, 3, 3, /* 0xbe */ + "\tmov\tdi,", mihand, 3, 3, /* 0xbf */ + NULL, dfhand, 0, 0, /* 0xc0 */ + NULL, dfhand, 0, 0, /* 0xc1 */ + "\tret", rehand, 3, 3, /* 0xc2 */ + "\tret", sbhand, 1, 1, /* 0xc3 */ + "\tles", mvhand, 2, 4, /* 0xc4 */ + "\tlds", mvhand, 2, 4, /* 0xc5 */ + MOV, mmhand, 3, 5, /* 0xc6 */ + MOV, mmhand, 4, 6, /* 0xc7 */ + NULL, dfhand, 0, 0, /* 0xc8 */ + NULL, dfhand, 0, 0, /* 0xc9 */ + "\treti", rehand, 3, 3, /* 0xca */ + "\treti", sbhand, 1, 1, /* 0xcb */ + "\tint", sbhand, 1, 1, /* 0xcc */ + "\tint", inhand, 2, 2, /* 0xcd */ + "\tinto", sbhand, 1, 1, /* 0xce */ + "\tiret", sbhand, 1, 1, /* 0xcf */ + AMBIG, srhand, 2, 4, /* 0xd0 */ + AMBIG, srhand, 2, 4, /* 0xd1 */ + AMBIG, srhand, 2, 4, /* 0xd2 */ + AMBIG, srhand, 2, 4, /* 0xd3 */ + "\taam", aahand, 2, 2, /* 0xd4 */ + "\taad", aahand, 2, 2, /* 0xd5 */ + NULL, dfhand, 0, 0, /* 0xd6 */ + "\txlat", sbhand, 1, 1, /* 0xd7 */ + ESC, eshand, 2, 2, /* 0xd8 */ + ESC, eshand, 2, 2, /* 0xd9 */ + ESC, eshand, 2, 2, /* 0xda */ + ESC, eshand, 2, 2, /* 0xdb */ + ESC, eshand, 2, 2, /* 0xdc */ + ESC, eshand, 2, 2, /* 0xdd */ + ESC, eshand, 2, 2, /* 0xde */ + ESC, eshand, 2, 2, /* 0xdf */ + "\tloopne", sjhand, 2, 2, /* 0xe0 */ + "\tloope", sjhand, 2, 2, /* 0xe1 */ + "\tloop", sjhand, 2, 2, /* 0xe2 */ + "\tjcxz", sjhand, 2, 2, /* 0xe3 */ + "\tin", iohand, 2, 2, /* 0xe4 */ + "\tinw", iohand, 2, 2, /* 0xe5 */ + "\tout", iohand, 2, 2, /* 0xe6 */ + "\toutw", iohand, 2, 2, /* 0xe7 */ + "\tcall", ljhand, 3, 3, /* 0xe8 */ + "\tjmp", ljhand, 3, 3, /* 0xe9 */ + "\tjmpi", cihand, 5, 5, /* 0xea */ + "\tj", sjhand, 2, 2, /* 0xeb */ + "\tin", sbhand, 1, 1, /* 0xec */ + "\tinw", sbhand, 1, 1, /* 0xed */ + "\tout", sbhand, 1, 1, /* 0xee */ + "\toutw", sbhand, 1, 1, /* 0xef */ + "\tlock", sbhand, 1, 1, /* 0xf0 */ + NULL, dfhand, 0, 0, /* 0xf1 */ + "\trepnz", sbhand, 1, 1, /* 0xf2 */ + "\trepz", sbhand, 1, 1, /* 0xf3 */ + "\thlt", sbhand, 1, 1, /* 0xf4 */ + "\tcmc", sbhand, 1, 1, /* 0xf5 */ + AMBIG, mahand, 2, 5, /* 0xf6 */ + AMBIG, mahand, 2, 6, /* 0xf7 */ + "\tclc", sbhand, 1, 1, /* 0xf8 */ + "\tstc", sbhand, 1, 1, /* 0xf9 */ + "\tcli", sbhand, 1, 1, /* 0xfa */ + "\tsti", sbhand, 1, 1, /* 0xfb */ + "\tcld", sbhand, 1, 1, /* 0xfc */ + "\tstd", sbhand, 1, 1, /* 0xfd */ + AMBIG, mjhand, 2, 4, /* 0xfe */ + AMBIG, mjhand, 2, 4 /* 0xff */ + }; + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This simple routine returns the name field of a symbol * + * table entry as a printable string. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +char * +getnam(k) + + register int k; + +{/* * * * * * * * * * START OF getnam() * * * * * * * * * */ + + register int j; + static char a[sizeof(symtab->n_name)+1]; + + for (j = 0; j < sizeof(symtab[k].n_name); ++j) + if ( ! symtab[k].n_name[j] ) + break; + else + a[j] = symtab[k].n_name[j]; + + a[j] = '\0'; + + return (a); + +}/* * * * * * * * * * * END OF getnam() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This function is responsible for mucking through the * + * relocation table in search of externally referenced * + * symbols to be output as operands. It accepts two long * + * arguments: the code-segment location at which an extern * + * reference is expected, and the offset value which is * + * embedded in the object code and used at link time to * + * bias the external value. In the most typical case, the * + * function will be called by lookup(), which always makes * + * a check for external names before searching the symbol * + * table proper. However, it may also be called directly * + * by any function (such as the move-immediate handler) * + * which wants to make an independent check for externals. * + * The caller is expected to supply, as the third argument * + * to the function, a pointer to a character buffer large * + * enough to hold any possible output string. Lookext() * + * will fill this buffer and return a logical TRUE if it * + * finds an extern reference; otherwise, it will return a * + * logical FALSE, leaving the buffer undisturbed. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +int +lookext(off,loc,buf) + + long off, loc; + char *buf; + +{/* * * * * * * * * * START OF lookext() * * * * * * * * * */ + + register int k; + char c[32]; + + if ((loc != -1L) && (relptr >= 0)) + for (k = 0; k <= relptr; ++k) + if ((relo[k].r_vaddr == loc) + && (relo[k].r_symndx < S_BSS)) + { + strcpy(buf,getnam(relo[k].r_symndx)); + if (off) + { + if (off < 0) + sprintf(c,"%ld",off); + else + sprintf(c,"+%ld",off); + strcat(buf,c); + } + return (1); + } + + return (0); + +}/* * * * * * * * * * END OF lookext() * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This function finds an entry in the symbol table by * + * value. Its input is a (long) machine address, and its * + * output is a pointer to a string containing the corre- * + * sponding symbolic name. The function first searches the * + * relocation table for a possible external reference; if * + * none is found, a linear search of the symbol table is * + * undertaken. If no matching symbol has been found at the * + * end of these searches, the function returns a pointer * + * to a string containing the ASCII equivalent of the ad- * + * dress which was to be located, so that, regardless of * + * the success of the search, the function's return value * + * is suitable for use as a memory-reference operand. The * + * caller specifies the type of symbol to be found (text, * + * data, bss, undefined, absolute, or common) by means of * + * the function's second parameter. The third parameter * + * specifies the format to be used in the event of a nu- * + * meric output: zero for absolute format, one for short * + * relative format, two for long relative format. The * + * fourth parameter is the address which would appear in * + * the relocation table for the reference in question, or * + * -1 if the relocation table is not to be searched. The * + * function attempts to apply a certain amount of intelli- * + * gence in its selection of symbols, so it is possible * + * that, in the absence of a type match, a symbol of the * + * correct value but different type will be returned. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +char * +lookup(addr,type,kind,ext) + + long addr; /* Machine address to be located */ + + int type, /* Type of symbol to be matched */ + kind; /* Addressing output mode to use */ + + long ext; /* Value for extern ref, if any */ + +{/* * * * * * * * * * START OF lookup() * * * * * * * * * */ + + register int j, k; + static char b[80]; + + struct + { + int i; + int t; + } + best; + + if (lookext(addr,ext,b)) + return (b); + + if (segflg) + if (segflg & 1) + type = N_TEXT; + else + type = N_DATA; + + for (k = 0, best.i = -1; k <= symptr; ++k) + if (symtab[k].n_value == addr) + if ((j = symtab[k].n_sclass & N_SECT) == type) + { + best.t = j; + best.i = k; + break; + } + else if (segflg || (HDR.a_flags & A_SEP)) + continue; + else if (best.i < 0) + best.t = j, best.i = k; + else if (symrank[type][j] > symrank[type][best.t]) + best.t = j, best.i = k; + + if (best.i >= 0) + return (getnam(best.i)); + + if (kind == LOOK_ABS) + sprintf(b,"0x%05.5x",addr); + else + { + long x = addr - (PC - kind); + if (x < 0) + sprintf(b,".%ld",x); + else + sprintf(b,".+%ld",x); + } + + return (b); + +}/* * * * * * * * * * * END OF lookup() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This function translates an 8088 addressing mode byte * + * to an equivalent assembler string, returning a pointer * + * thereto. If necessary, it performs successive inputs * + * of bytes from the object file in order to obtain offset * + * data, adjusting PC accordingly. (The addressing mode * + * byte appears in several 8088 opcodes; it is used to * + * specify source and destination operand locations.) The * + * third argument to the function is zero if the standard * + * registers are to be used, or eight if the segment reg- * + * isters are to be used; these constants are defined sym- * + * bolically in dis.h. NOTE: The mtrans() function must * + * NEVER be called except immediately after fetching the * + * mode byte. If any additional object bytes are fetched * + * after the fetch of the mode byte, mtrans() will not * + * produce correct output! * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +char * +mtrans(c,m,type) + + register int c; /* Primary instruction byte */ + register int m; /* Addressing mode byte */ + + int type; /* Type code: standard or seg */ + +{/* * * * * * * * * * START OF mtrans() * * * * * * * * * */ + + unsigned long pc; + int offset, oflag, dir, w, mod, reg, rm; + static char a[100]; + static char b[30]; + + offset = 0; + dir = c & 2; + w = c & 1; + mod = (m & 0xc0) >> 6; + reg = (m & 0x38) >> 3; + rm = m & 7; + pc = PC + 1; + + if (type) + w = 1; + + if ((oflag = mod) > 2) + oflag = 0; + + if (oflag) + { + int j, k; + if (oflag == 2) + { + FETCH(j); + FETCH(k); + offset = (k << 8) | j; + } + else + { + FETCH(j); + if (j & 0x80) + k = 0xff00; + else + k = 0; + offset = k | j; + } + } + + if (dir) + { + strcpy(a,REGS[type + ((w << 3) | reg)]); + strcat(a,","); + switch (mod) + { + case 0 : + if (rm == 6) + { + int j, k; + FETCH(j); + FETCH(k); + offset = (k << 8) | j; + strcat(a, + lookup((long)(offset),N_DATA,LOOK_ABS,pc)); + } + else + { + sprintf(b,"(%s)",REGS0[rm]); + strcat(a,b); + } + break; + case 1 : + case 2 : + if (mod == 1) + strcat(a,"*"); + else + strcat(a,"#"); + sprintf(b,"%d(",offset); + strcat(a,b); + strcat(a,REGS1[rm]); + strcat(a,")"); + break; + case 3 : + strcat(a,REGS[(w << 3) | rm]); + break; + } + } + else + { + switch (mod) + { + case 0 : + if (rm == 6) + { + int j, k; + FETCH(j); + FETCH(k); + offset = (k << 8) | j; + strcpy(a, + lookup((long)(offset),N_DATA,LOOK_ABS,pc)); + } + else + { + sprintf(b,"(%s)",REGS0[rm]); + strcpy(a,b); + } + break; + case 1 : + case 2 : + if (mod == 1) + strcpy(a,"*"); + else + strcpy(a,"#"); + sprintf(b,"%d(",offset); + strcat(a,b); + strcat(a,REGS1[rm]); + strcat(a,")"); + break; + case 3 : + strcpy(a,REGS[(w << 3) | rm]); + break; + } + strcat(a,","); + strcat(a,REGS[type + ((w << 3) | reg)]); + } + + return (a); + +}/* * * * * * * * * * * END OF mtrans() * * * * * * * * * * */ + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This simple routine truncates a string returned by the * + * mtrans() function, removing its source operand. This is * + * useful in handlers which ignore the "reg" field of the * + * mode byte. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void +mtrunc(a) + + register char *a; /* Ptr. to string to truncate */ + +{/* * * * * * * * * * START OF mtrunc() * * * * * * * * * */ + + register int k; + + for (k = strlen(a) - 1; k >= 0; --k) + if (a[k] == ',') + { + a[k] = '\0'; + break; + } + +}/* * * * * * * * * * * END OF mtrunc() * * * * * * * * * * */ + + diff --git a/dis88/old_a.out.h b/dis88/old_a.out.h new file mode 100644 index 0000000..1a36dfb --- /dev/null +++ b/dis88/old_a.out.h @@ -0,0 +1,117 @@ +/* The <a.out> header file describes the format of executable files. */ + +#ifndef _AOUT_H +#define _AOUT_H + +struct exec { /* a.out header */ + unsigned char a_magic[2]; /* magic number */ + unsigned char a_flags; /* flags, see below */ + unsigned char a_cpu; /* cpu id */ + unsigned char a_hdrlen; /* length of header */ + unsigned char a_unused; /* reserved for future use */ + unsigned short a_version; /* version stamp (not used at present) */ + long a_text; /* size of text segement in bytes */ + long a_data; /* size of data segment in bytes */ + long a_bss; /* size of bss segment in bytes */ + long a_entry; /* entry point */ + long a_total; /* total memory allocated */ + long a_syms; /* size of symbol table */ + + /* SHORT FORM ENDS HERE */ + long a_trsize; /* text relocation size */ + long a_drsize; /* data relocation size */ + long a_tbase; /* text relocation base */ + long a_dbase; /* data relocation base */ +}; + +#define A_MAGIC0 (unsigned char) 0x01 +#define A_MAGIC1 (unsigned char) 0x03 +#define BADMAG(X) ((X).a_magic[0] != A_MAGIC0 ||(X).a_magic[1] != A_MAGIC1) + +/* CPU Id of TARGET machine (byte order coded in low order two bits) */ +#define A_NONE 0x00 /* unknown */ +#define A_I8086 0x04 /* intel i8086/8088 */ +#define A_M68K 0x0B /* motorola m68000 */ +#define A_NS16K 0x0C /* national semiconductor 16032 */ +#define A_I80386 0x10 /* intel i80386 */ +#define A_SPARC 0x17 /* Sun SPARC */ + +#define A_BLR(cputype) ((cputype&0x01)!=0) /* TRUE if bytes left-to-right */ +#define A_WLR(cputype) ((cputype&0x02)!=0) /* TRUE if words left-to-right */ + +/* Flags. */ +#define A_UZP 0x01 /* unmapped zero page (pages) */ +#define A_PAL 0x02 /* page aligned executable */ +#define A_NSYM 0x04 /* new style symbol table */ +#define A_EXEC 0x10 /* executable */ +#define A_SEP 0x20 /* separate I/D */ +#define A_PURE 0x40 /* pure text */ /* not used */ +#define A_TOVLY 0x80 /* text overlay */ /* not used */ + +/* Offsets of various things. */ +#define A_MINHDR 32 +#define A_TEXTPOS(X) ((long)(X).a_hdrlen) +#define A_DATAPOS(X) (A_TEXTPOS(X) + (X).a_text) +#define A_HASRELS(X) ((X).a_hdrlen > (unsigned char) A_MINHDR) +#define A_HASEXT(X) ((X).a_hdrlen > (unsigned char) (A_MINHDR + 8)) +#define A_HASLNS(X) ((X).a_hdrlen > (unsigned char) (A_MINHDR + 16)) +#define A_HASTOFF(X) ((X).a_hdrlen > (unsigned char) (A_MINHDR + 24)) +#define A_TRELPOS(X) (A_DATAPOS(X) + (X).a_data) +#define A_DRELPOS(X) (A_TRELPOS(X) + (X).a_trsize) +#define A_SYMPOS(X) (A_TRELPOS(X) + (A_HASRELS(X) ? \ + ((X).a_trsize + (X).a_drsize) : 0)) + +struct reloc { + long r_vaddr; /* virtual address of reference */ + unsigned short r_symndx; /* internal segnum or extern symbol num */ + unsigned short r_type; /* relocation type */ +}; + +/* r_tyep values: */ +#define R_ABBS 0 +#define R_RELLBYTE 2 +#define R_PCRBYTE 3 +#define R_RELWORD 4 +#define R_PCRWORD 5 +#define R_RELLONG 6 +#define R_PCRLONG 7 +#define R_REL3BYTE 8 +#define R_KBRANCHE 9 + +/* r_symndx for internal segments */ +#define S_ABS ((unsigned short)-1) +#define S_TEXT ((unsigned short)-2) +#define S_DATA ((unsigned short)-3) +#define S_BSS ((unsigned short)-4) + +struct nlist { /* symbol table entry */ + char n_name[8]; /* symbol name */ + long n_value; /* value */ + unsigned char n_sclass; /* storage class */ + unsigned char n_numaux; /* number of auxiliary entries (not used) */ + unsigned short n_type; /* language base and derived type (not used) */ +}; + +/* Low bits of storage class (section). */ +#define N_SECT 07 /* section mask */ +#define N_UNDF 00 /* undefined */ +#define N_ABS 01 /* absolute */ +#define N_TEXT 02 /* text */ +#define N_DATA 03 /* data */ +#define N_BSS 04 /* bss */ +#define N_COMM 05 /* (common) */ + +/* High bits of storage class. */ +#define N_CLASS 0370 /* storage class mask */ +#define C_NULL +#define C_EXT 0020 /* external symbol */ +#define C_STAT 0030 /* static */ + +/* Function prototypes. */ +#ifndef _ANSI_H +#include "ansi.h" +#endif + +_PROTOTYPE( int nlist, (char *_file, struct nlist *_nl) ); + +#endif /* _AOUT_H */ |