80386 disassembler for Xenix
pgd at bbt.se
pgd at bbt.se
Mon Dec 31 19:38:14 AEST 1990
This is a disassembler program i have been using for a while.
It reads Xenix/386 and Xenix/286 object files. The output is 386 assembly
code.
usage: disasm infile >outfile
The object modules understood is only xenix x.out format. But this is
easily extendable to coff format.
I generally use some emacs macros, to convert the most common
sequences to comething c-like, and then hand-translate to c.
Any emacs hacker should not look at the macros -- they are not very
smart. To use the macros, load the file into emacs, do ESC ESC,
yank in the macros file, and execute it.
Watch out for bugs, if you are disassembling an 80286 object module.
Note that a bigger part of this program is taken directly from GDB,
and thus follows the GNU GPL.
If you improve on this program, i would be happy to receive those
improvements.
P.Garbha (pgd at compuram.bbt.se)
#!/bin/sh
# This is a shell archive (shar 3.32)
# made 12/31/1990 08:28 UTC by pgd at compuram
# Source directory /u/pgd/da
#
# existing files WILL be overwritten
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 30568 -rw-r----- disasm.c
# 15573 -rw------- 386opcodes.h
# 3117 -rw------- 387opcodes.h
# 12558 -rw------- macros
#
if touch 2>&1 | fgrep 'amc' > /dev/null
then TOUCH=touch
else TOUCH=true
fi
# ============= disasm.c ==============
echo "x - extracting disasm.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > disasm.c &&
X/*
X * Xenix disassembly program by P.Garbha (pgd at compuram.bbt.se)
X *
X * 80386 instruction printer by Pace Willisson (pace at prep.ai.mit.edu)
X * July 1988
X * Copyright (C) 1988 Free Software Foundation, Inc.
X */
X
X
X#include <stdio.h>
X#include <ctype.h>
X#include <a.out.h>
X#include <sys/relsym.h>
X#include <string.h>
X
X#include "386opcodes.h"
X
X#define MAXSEG 20
X#define THRESHOLD 0x100
X
Xstatic int prefixes;
X
Xstatic char obuf[100];
Xstatic char *obufp;
Xstatic char scratchbuf[1000];
Xstatic unsigned char *start_codep;
Xstatic unsigned char *codep;
Xstatic int mod;
Xstatic int rm;
Xstatic int reg;
X
Xstruct xexec xoutx;
Xstruct xext xoutxe;
Xstruct xseg xoutxs[MAXSEG];
Xstruct {
X short signature;
X short lengthb; /* length of file, lsb */
X short lengthp; /* length of file in 512-byte pages */
X short relitems; /* number of relocation table items */
X short hdrsize; /* size of header in 16-byte paragraphs */
X short maxparas1;
X short maxparas2;
X short stackoff; /* Offset of stack segment in load module */
X short initsp; /* Initial sp */
X short checksum; /* Word checksum */
X short initip; /* Initial ip */
X short csoff; /* Offset of code segment */
X short reloff; /* Offset of the first relocation item */
X short ovlno; /* Overlay number */
X} exehdr;
X
Xint segcount = 0;
Xstruct xseg *textsegp = 0, *datasegp = 0, *symsegp = 0;
Xint textseg = -1, dataseg = -1;
Xunsigned char *textp, *datap, *xtextp;
X
Xint textsize, datasize, database;
X
Xstruct symtab {
X char *symstring;
X unsigned int symval;
X short symrefcount;
X short symflags;
X};
X
X#define TEXTSEG 0000001
X#define DATASEG 0000002
X#define GENERATED 0000004
X#define BYTEREF 0000010
X#define WORDREF 0000020
X#define DWORDREF 0000040
X#define JUMPREF 0000100
X#define CALLREF 0000200
X#define DEFINED 0000400
X#define PUSHLIMMED 0001000
X#define ASCIZ 0002000
X#define ADDRREF 0004000
X
X#define NOENTER 0100000
X
Xstruct symtab *lookup(), *enter();
Xchar *symname(), *getimmed(), *datasymbol(), *ascizdata();
X
X#define SYMHS 20033
Xstruct symtab *symhash[SYMHS];
Xint symcount = 0;
X
Xint pass2 = 0;
X
Xinit()
X{
X register int i;
X
X for (i = 0; i < SYMHS; i++) {
X symhash[i] = NULL;
X }
X}
X
Xmain(argc, argv)
X char **argv;
X{
X init();
X if (argc < 2) fatal("No input file");
X loadaout(argv[1]);
X dopass1();
X symtabpass();
X dopass2();
X dodata();
X exit(0);
X}
X
Xdopass1()
X{
X int ipc;
X char buf[200];
X int len;
X
X ipc = 0;
X while (ipc < textsize) {
X len = i386dis(ipc, textp+ipc, buf);
X ipc += len;
X }
X}
X
Xdopass2()
X{
X int ipc;
X int oipc = 0;
X char buf[200];
X int len;
X register struct symtab *lbp;
X int i, mode;
X int unreachable = 0, firsttime = 0;
X
X pass2 = 1;
X ipc = 0;
X while (ipc < textsize) {
X if (textp != xtextp) abort();
X lbp = lookup(ipc, TEXTSEG);
X if (lbp && lbp->symrefcount == 1 && lbp->symflags & (WORDREF|DWORDREF) && !(lbp->symflags & (CALLREF|JUMPREF))) {
X mode = lbp->symflags;
X printf("%s:\t\t; %0x (%d)\n", symname(lbp), ipc, lbp->symrefcount);
X for (;;) {
X register unsigned int addr;
X register struct symtab *symp;
X codep = textp+ipc;
X addr = *(unsigned int *)codep;
X symp = lookup(addr, TEXTSEG|JUMPREF);
X if (symp)
X printf("\t.dword\t%s\n", symname(symp));
X else
X printf("\t.dword\t%#x\n", addr);
X len = 4;
X ++ipc;
X for (i = 1; i < len; i++) {
X if (lbp = lookup(ipc, TEXTSEG)) {
X /*
X * This is a hack, just to
X * void breaking a jump table
X * by a garbage label.
X * We assume no code segment
X * starts with the 0 opcode
X */
X if (textp[ipc] < 0xf) {
X ipc++;
X continue;
X }
X printf("Code overlapping, backing up\n");
X oipc = ipc + len;
X break;
X }
X ipc++;
X }
X if (i < len || i == len && lookup(ipc, TEXTSEG))
X break;
X }
X } else {
X register int opcode;
X
X opcode = *(textp+ipc);
X if (lbp) {
X printf("%s:\t\t; %0x (%d)\n", symname(lbp), ipc, lbp->symrefcount);
X unreachable = 0;
X }
X if (unreachable && opcode == 0) {
X printf("\t.byte\t0\t\t; unreachable");
X len = 1;
X } else if (unreachable && opcode == 0x90) {
X printf("\tnop\t\t\t; unreachable");
X len = 1;
X } else {
X if (unreachable && firsttime) {
X printf("Warning: Unreachable code\n");
X firsttime = 0;
X }
X len = i386dis(ipc, textp+ipc, buf);
X putchar('\t');
X fputs(buf, stdout);
X }
X /*
X * Check for moving into unreachable code
X */
X if (opcode==0xeb||opcode==0xe9||opcode==0xc3||opcode==0xc2||opcode==0xa||opcode==0xcb) {
X unreachable = firsttime = 1;
X }
X /* printf("\t\t; %#x", *start_codep); */
X putchar('\n');
X ++ipc;
X for (i = 1; i < len; i++) {
X register struct symtab *symp;
X if (symp = lookup(ipc, TEXTSEG)) {
X if (unreachable) {
X printf("Code overlapping, backing up\n");
X break;
X }
X printf("Warning: Hidden label: %s\n", symname(symp));
X }
X ipc++;
X }
X }
X }
X}
X
X/*
X * Print out data area
X */
Xdodata()
X{
X int dpc;
X register struct symtab *lbp;
X register int c;
X
X dpc = 0;
X while (dpc < datasize) {
X lbp = lookup(dpc+database, DATASEG);
X while (lbp && (lbp->symflags & ASCIZ)) {
X for (;;) {
X dpc++;
X if (dpc >= datasize)
X return;
X if (lbp = lookup(dpc+database, DATASEG))
X break;
X }
X }
X if (lbp) {
X printf("%s:\t\t; %0x (%d)", symname(lbp), dpc+database, lbp->symrefcount);
X if (lbp->symflags & BYTEREF) printf(" BYTE ");
X if (lbp->symflags & WORDREF) printf(" WORD ");
X if (lbp->symflags & DWORDREF) printf(" DWORD ");
X if (lbp->symflags & ASCIZ) printf(" ASCIZ ");
X if (lbp->symflags & ADDRREF) printf(" ADDR ");
X putchar('\n');
X }
X if (!pass2) {
X dpc++;
X continue;
X }
X
X switch (lbp ? lbp->symflags & (BYTEREF|WORDREF|DWORDREF|ADDRREF) : BYTEREF) {
X case BYTEREF:
X default:
X deflt:
X c = datap[dpc];
X printf("\t.byte\t%#x\t;", c);
X if (c>=' ' && c < 127)
X printf("'%c'", c);
X else
X printf(" ");
X printf(" %#x\n", dpc /*+database */);
X dpc++;
X break;
X
X case WORDREF:
X if (dpc+1 < datasize
X && !lookup(dpc+database+1, DATASEG)) {
X printf("\t.word\t%#x\t; %d\t%#x\n",
X *((unsigned short *)(datap+dpc)), dpc);
X dpc += 2;
X break;
X }
X goto deflt;
X
X case DWORDREF:
X if (dpc+3 < datasize
X && !lookup(dpc+database+1, DATASEG)
X && !lookup(dpc+database+2, DATASEG)
X && !lookup(dpc+database+3, DATASEG)) {
X printf("\t.dword\t%#x\t; %d\t%#x\n",
X *((unsigned long *)(datap+dpc)), dpc);
X dpc += 4;
X break;
X }
X goto deflt;
X }
X }
X
X}
X
Xckprefix ()
X{
X prefixes = 0;
X while (1) {
X switch (*codep) {
X case 0xf3:
X prefixes |= PREFIX_REPZ;
X break;
X case 0xf2:
X prefixes |= PREFIX_REPNZ;
X break;
X case 0xf0:
X prefixes |= PREFIX_LOCK;
X break;
X case 0x2e:
X prefixes |= PREFIX_CS;
X break;
X case 0x36:
X prefixes |= PREFIX_SS;
X break;
X case 0x3e:
X prefixes |= PREFIX_DS;
X break;
X case 0x26:
X prefixes |= PREFIX_ES;
X break;
X case 0x64:
X prefixes |= PREFIX_FS;
X break;
X case 0x65:
X prefixes |= PREFIX_GS;
X break;
X case 0x66:
X prefixes |= PREFIX_DATA;
X break;
X case 0x67:
X prefixes |= PREFIX_ADR;
X break;
X case 0x9b:
X prefixes |= PREFIX_FWAIT;
X break;
X default:
X return;
X }
X codep++;
X }
X}
X
Xstatic int dflag;
Xstatic int aflag;
Xstatic int Sflag;
X
Xstatic char op1out[100], op2out[100], op3out[100];
Xstatic int start_pc;
X
X/*
X * disassemble the first instruction in 'inbuf'. You have to make
X * sure all of the bytes of the instruction are filled in.
X * On the 386's of 1988, the maximum length of an instruction is 15 bytes.
X * (see topic "Redundant prefixes" in the "Differences from 8086"
X * section of the "Virtual 8086 Mode" chapter.)
X * 'pc' should be the address of this instruction, it will
X * be used to print the target address if this is a relative jump or call
X * 'outbuf' gets filled in with the disassembled instruction. it should
X * be long enough to hold the longest disassembled instruction.
X * 100 bytes is certainly enough, unless symbol printing is added later
X * The function returns the length of this instruction in bytes.
X */
Xi386dis (pc, inbuf, outbuf)
X int pc;
X unsigned char *inbuf;
X char *outbuf;
X{
X struct dis386 *dp;
X char *p;
X int i;
X int enter_instruction;
X char *first, *second, *third;
X int needcomma;
X
X obuf[0] = 0;
X op1out[0] = 0;
X op2out[0] = 0;
X op3out[0] = 0;
X
X start_pc = pc;
X start_codep = inbuf;
X codep = inbuf;
X
X ckprefix ();
X
X if (*codep == 0xc8)
X enter_instruction = 1;
X else
X enter_instruction = 0;
X
X obufp = obuf;
X
X if (prefixes & PREFIX_REPZ)
X oappend ("repz ");
X if (prefixes & PREFIX_REPNZ)
X oappend ("repnz ");
X if (prefixes & PREFIX_LOCK)
X oappend ("lock ");
X
X if ((prefixes & PREFIX_FWAIT) && ((*codep < 0xd8) || (*codep > 0xdf))) {
X /* fwait not followed by floating point instruction */
X oappend ("fwait");
X strcpy (outbuf, obuf);
X return (1);
X }
X
X /* these would be initialized to 0 if disassembling for 8086 or 286 */
X dflag = aflag = Sflag = 0;
X if ((xoutx.x_cpu & XC_CPU) == XC_386) {
X dflag = aflag = 1;
X }
X
X if (prefixes & PREFIX_DATA)
X dflag ^= 1;
X
X if (prefixes & PREFIX_ADR) {
X aflag ^= 1;
X oappend ("addr16 ");
X }
X
X if (*codep == 0x0f)
X dp = &dis386_twobyte[*++codep];
X else
X dp = &dis386[*codep];
X codep++;
X mod = (*codep >> 6) & 3;
X reg = (*codep >> 3) & 7;
X rm = *codep & 7;
X
X if (dp->name == NULL && dp->bytemode1 == FLOATCODE) {
X dofloat ();
X } else {
X if (dp->name == NULL)
X dp = &grps[dp->bytemode1][reg];
X
X putop (dp->name);
X
X obufp = op1out;
X if (dp->op1)
X (*dp->op1)(dp->bytemode1);
X
X obufp = op2out;
X if (dp->op2)
X (*dp->op2)(dp->bytemode2);
X
X obufp = op3out;
X if (dp->op3)
X (*dp->op3)(dp->bytemode3);
X }
X
X obufp = obuf + strlen (obuf);
X/* for (i = strlen (obuf); i < 6; i++)
X oappend (" ");
X oappend (" "); */
X oappend ("\t");
X
X /* enter instruction is printed with operands in the
X * same order as the intel book; everything else
X * is printed in reverse order
X */
X if (enter_instruction) {
X first = op1out;
X second = op2out;
X third = op3out;
X } else {
X first = op3out;
X second = op2out;
X third = op1out;
X }
X needcomma = 0;
X if (*first) {
X oappend (first);
X needcomma = 1;
X }
X if (*second) {
X if (needcomma)
X oappend (",");
X oappend (second);
X needcomma = 1;
X }
X if (*third) {
X if (needcomma)
X oappend (",");
X oappend (third);
X }
X strcpy (outbuf, obuf);
X return (codep - inbuf);
X}
X
X#include "387opcodes.h"
X
Xdofloat ()
X{
X struct dis386 *dp;
X unsigned char floatop;
X
X floatop = codep[-1];
X
X if (mod != 3) {
X putop (float_mem[(floatop - 0xd8) * 8 + reg]);
X obufp = op1out;
X OP_E (v_mode);
X return;
X }
X codep++;
X
X dp = &float_reg[floatop - 0xd8][reg];
X if (dp->name == NULL) {
X putop (fgrps[dp->bytemode1][rm]);
X /* instruction fnstsw is only one with strange arg */
X if (floatop == 0xdf && *codep == 0xe0)
X strcpy (op1out, "%eax");
X } else {
X putop (dp->name);
X obufp = op1out;
X if (dp->op1)
X (*dp->op1)(dp->bytemode1);
X obufp = op2out;
X if (dp->op2)
X (*dp->op2)(dp->bytemode2);
X }
X}
X
X/* ARGSUSED */
XOP_ST (ignore)
X{
X oappend ("%st");
X}
X
X/* ARGSUSED */
XOP_STi (ignore)
X{
X sprintf (scratchbuf, "%%st(%d)", rm);
X oappend (scratchbuf);
X}
X
X
X/* capital letters in template are macros */
Xputop (template)
X char *template;
X{
X char *p;
X
X for (p = template; *p; p++) {
X switch (*p) {
X default:
X *obufp++ = *p;
X break;
X case 'C': /* For jcxz/jecxz */
X if (aflag == 0)
X *obufp++ = 'e';
X break;
X case 'N':
X if ((prefixes & PREFIX_FWAIT) == 0)
X *obufp++ = 'n';
X break;
X case 'S':
X /* operand size flag */
X Sflag = 1;
X if (dflag)
X *obufp++ = 'l';
X else
X *obufp++ = 'w';
X break;
X }
X }
X *obufp = 0;
X}
X
Xoappend (s)
X char *s;
X{
X strcpy (obufp, s);
X obufp += strlen (s);
X *obufp = 0;
X}
X
Xappend_prefix ()
X{
X if (prefixes & PREFIX_CS)
X oappend ("%cs:");
X if (prefixes & PREFIX_DS)
X oappend ("%ds:");
X if (prefixes & PREFIX_SS)
X oappend ("%ss:");
X if (prefixes & PREFIX_ES)
X oappend ("%es:");
X if (prefixes & PREFIX_FS)
X oappend ("%fs:");
X if (prefixes & PREFIX_GS)
X oappend ("%gs:");
X}
X
XOP_indirE (bytemode)
X{
X oappend ("*");
X OP_E (bytemode);
X}
X
XOP_E (bytemode)
X{
X int disp;
X int havesib; /* have "scaled index base" byte */
X int didoutput = 0;
X int base;
X int index;
X int scale;
X int havebase;
X
X /* skip mod/rm byte */
X codep++;
X
X havesib = 0;
X havebase = 0;
X disp = 0;
X
X if (mod == 3) { /* Register mod's */
X switch (bytemode) {
X case b_mode:
X oappend (names8[rm]);
X break;
X case w_mode:
X oappend (names16[rm]);
X break;
X case v_mode:
X if (dflag)
X oappend (names32[rm]);
X else
X oappend (names16[rm]);
X break;
X default:
X oappend ("<bad dis table>");
X break;
X }
X return;
X }
X
X append_prefix();
X
X if (rm == 4 && aflag) {
X havesib = 1;
X havebase = 1;
X scale = (*codep >> 6) & 3;
X index = (*codep >> 3) & 7;
X base = *codep & 7;
X codep++;
X }
X
X if (!aflag && mod < 3) {
X switch (mod) {
X case 0:
X if (rm == 6) {
X disp = get16();
X oappend(datasymbol(disp, WORDREF, 1));
X return;
X }
X break;
X
X case 1:
X sprintf(scratchbuf, "%#x", *codep++);
X oappend(scratchbuf);
X break;
X
X case 2:
X disp = get16();
X oappend(datasymbol(disp, WORDREF, 1));
X break;
X }
X
X switch (rm) {
X case 0: oappend("(%bx,%si)"); return;
X case 1: oappend("(%bx,%di)"); return;
X case 2: oappend("(%bp,%si)"); return;
X case 3: oappend("(%bp,%di)"); return;
X case 4: oappend("(%si)"); return;
X case 5: oappend("(%di)"); return;
X case 6: oappend("(%bp)"); return;
X case 7: oappend("(%bx)"); return;
X }
X }
X switch (mod) {
X case 0:
X switch (rm) {
X case 4: /* DS:[d32+(scaled index)] */
X if (!aflag)
X break;
X /* implies havesib and havebase */
X if (base == 5) {
X havebase = 0;
X disp = get32 ();
X }
X break;
X case 5: /* DS:d32 */
X if (!aflag)
X break;
X disp = get32 ();
X break;
X case 6: /* DS:d16 */
X if (aflag)
X break;
X disp = get16 ();
X break;
X default: /* DS:[Ereg] */
X havebase = 1;
X base = rm;
X break;
X }
X break;
X
X case 1: /* DS:[Ereg+d8] */
X disp = *(char *)codep++;
X if (rm != 4) {
X havebase = 1;
X base = rm;
X }
X break;
X
X case 2: /* DS:[Ereg+d32] */
X if (aflag) {
X disp = get32 ();
X if (rm != 4) {
X havebase = 1;
X base = rm;
X }
X } else {
X disp = get16();
X }
X break;
X }
X
X/* if (mod < 3) { */
X if (havesib) {
X if (mod == 0) {
X if (base == 5) { /* DS:[d32+(scaled index)] */
X if (prefixes & PREFIX_CS) {
X register struct symtab *symp;
X int mode = scale==2 ? WORDREF
X : scale==3 ? DWORDREF
X : 0;
X symp = lookup(disp, TEXTSEG|mode);
X if (pass2)
X if (symp)
X sprintf (scratchbuf, "%s", symname(symp));
X else
X sprintf (scratchbuf, "%s", datasymbol(disp, mode, 1));
X oappend(scratchbuf);
X } else
X oappend(datasymbol(disp, 0, 1));
X }
X } else if (base == 5) { /* SS:[EBP+...] */
X sprintf (scratchbuf, "%d", disp);
X oappend(scratchbuf);
X } else if (base == 4) { /* SS:[ESP+...] */
X sprintf(scratchbuf, "%d", disp);
X oappend(scratchbuf);
X } else { /* DS:[...] */
X if (mod == 1) { /* Byte offset */
X sprintf (scratchbuf, "%d", disp);
X oappend(scratchbuf);
X } else { /* Longword offset */
X oappend(datasymbol(disp, 0, 1));
X }
X }
X } else if (aflag && rm == 5 || /* DS:d32 or SS:[EBP...] */
X !aflag && rm == 6) { /* DS:d16 */
X if (mod == 0) { /* DS:d32 or DS:d16 */
X /* Normal "direct" data address */
X oappend(datasymbol(/* Sflag && !dflag ? disp + database : */ disp,
X bytemode==b_mode ? BYTEREF :
X bytemode==w_mode ? WORDREF :
X Sflag ? dflag ? DWORDREF
X : WORDREF : 0, 1));
X } else {
X sprintf(scratchbuf, "%d", disp);
X oappend(scratchbuf);
X }
X#if 0
X } else if (mod == 2) { /* DS:[ereg+d8] */
X sprintf(scratchbuf, "%d", disp);
X oappend(scratchbuf);
X#endif
X } else { /* DS:[ereg+d32] */
X oappend(datasymbol(disp, 0, 1));
X }
X/* } */
X
X if (havebase || havesib) {
X oappend ("(");
X if (!havebase && !havesib) oappend("????");
X if (havebase)
X oappend ((aflag ? names32 : names16_OP_E)[base]);
X if (havesib) {
X if (index != 4) {
X sprintf (scratchbuf, ",%s", names32[index]);
X oappend (scratchbuf);
X sprintf (scratchbuf, ",%d", 1 << scale);
X oappend (scratchbuf);
X }
X }
X oappend (")");
X }
X}
X
XOP_G (bytemode)
X{
X switch (bytemode) {
X case b_mode:
X oappend (names8[reg]);
X break;
X case w_mode:
X oappend (names16[reg]);
X break;
X case d_mode:
X oappend (names32[reg]);
X break;
X case v_mode:
X if (dflag)
X oappend (names32[reg]);
X else
X oappend (names16[reg]);
X break;
X default:
X oappend ("<internal disassembler error>");
X break;
X }
X}
X
Xget32 ()
X{
X int x = 0;
X
X x = *codep++ & 0xff;
X x |= (*codep++ & 0xff) << 8;
X x |= (*codep++ & 0xff) << 16;
X x |= (*codep++ & 0xff) << 24;
X return (x);
X}
X
Xget16 ()
X{
X int x = 0;
X
X x = *codep++ & 0xff;
X x |= (*codep++ & 0xff) << 8;
X return (x);
X}
X
XOP_REG (code)
X{
X char *s;
X
X switch (code) {
X case indir_dx_reg:
X s = "(%dx)";
X break;
X case ax_reg:
X case cx_reg:
X case dx_reg:
X case bx_reg:
X case sp_reg:
X case bp_reg:
X case si_reg:
X case di_reg:
X s = names16[code - ax_reg];
X break;
X case es_reg:
X case ss_reg:
X case cs_reg:
X case ds_reg:
X case fs_reg:
X case gs_reg:
X s = names_seg[code - es_reg];
X break;
X case al_reg:
X case ah_reg:
X case cl_reg:
X case ch_reg:
X case dl_reg:
X case dh_reg:
X case bl_reg:
X case bh_reg:
X s = names8[code - al_reg];
X break;
X case eAX_reg:
X case eCX_reg:
X case eDX_reg:
X case eBX_reg:
X case eSP_reg:
X case eBP_reg:
X case eSI_reg:
X case eDI_reg:
X if (dflag)
X s = names32[code - eAX_reg];
X else
X s = names16[code - eAX_reg];
X break;
X default:
X s = "<internal disassembler error>";
X break;
X }
X oappend (s);
X}
X
XOP_I (bytemode)
X{
X int op;
X
X switch (bytemode) {
X case b_mode:
X op = *codep++ & 0xff;
X break;
X case v_mode:
X if (dflag)
X op = get32 ();
X else
X op = get16 ();
X break;
X case w_mode:
X op = get16 ();
X break;
X default:
X oappend ("<internal disassembler error>");
X return;
X }
X oappend (getimmed(op));
X}
X
XOP_sI (bytemode)
X{
X int op;
X
X switch (bytemode) {
X case b_mode:
X op = *(char *)codep++;
X break;
X case v_mode:
X if (dflag)
X op = get32 ();
X else
X op = (short)get16();
X break;
X case w_mode:
X op = (short)get16 ();
X break;
X default:
X oappend ("<internal disassembler error>");
X return;
X }
X oappend (getimmed(op));
X}
X
X/*
X * Jump opcodes
X */
XOP_J (bytemode)
X{
X int disp, addr;
X int mask = -1;
X register struct symtab *symp;
X
X switch (bytemode) {
X case b_mode:
X disp = *(char *)codep++;
X break;
X case v_mode:
X if (dflag)
X disp = get32 ();
X else {
X disp = (short)get16 ();
X /* for some reason, a data16 prefix on a jump instruction
X means that the pc is masked to 16 bits after the
X displacement is added! */
X mask = 0xffff;
X }
X break;
X default:
X oappend ("<internal disassembler error>");
X return;
X }
X
X addr = (start_pc + codep - start_codep + disp) & mask;
X symp = lookup(addr, TEXTSEG|JUMPREF);
X if (pass2) {
X if (symp)
X sprintf (scratchbuf, "%s", symname(symp));
X else
X sprintf (scratchbuf, "%s", datasymbol(addr, 0, 1));
X oappend (scratchbuf);
X }
X}
X
X/* ARGSUSED */
XOP_SEG (dummy)
X{
X static char *sreg[] = {
X "%es","%cs","%ss","%ds","%fs","%gs","%?","%?",
X };
X
X oappend (sreg[reg]);
X}
X
X/*
X * A subroutine address, or a jump/call far destination
X */
XOP_DIR (size)
X{
X int seg, offset, addr;
X register struct symtab *symp;
X
X switch (size) {
X case lptr:
X if (aflag) {
X offset = get32 ();
X seg = get16 ();
X } else {
X offset = get16 ();
X seg = get16 ();
X }
X sprintf (scratchbuf, "0x%x,0x%x", seg, offset);
X oappend (scratchbuf);
X break;
X
X case v_mode: /* Call instruction destination */
X if (aflag)
X offset = get32 ();
X else
X offset = (short)get16 ();
X
X addr = start_pc + codep - start_codep + offset;
X symp = lookup(addr, TEXTSEG|CALLREF);
X if (pass2)
X if (symp)
X oappend(symname(symp));
X else
X oappend(datasymbol(addr, 0, 1));
X
X break;
X default:
X oappend ("<internal disassembler error>");
X break;
X }
X}
X
X/* ARGSUSED */
XOP_OFF (bytemode)
X{
X int off;
X
X if (aflag)
X off = get32 ();
X else
X off = get16 ();
X
X oappend(datasymbol(off, 0, 0));
X}
X
X/* ARGSUSED */
XOP_ESDI (dummy)
X{
X oappend ("%es:(");
X oappend (aflag ? "%edi" : "%di");
X oappend (")");
X}
X
X/* ARGSUSED */
XOP_DSSI (dummy)
X{
X oappend ("%ds:(");
X oappend (aflag ? "%esi" : "%si");
X oappend (")");
X}
X
X/* ARGSUSED */
XOP_ONE (dummy)
X{
X oappend ("1");
X}
X
X/* ARGSUSED */
XOP_C (dummy)
X{
X codep++; /* skip mod/rm */
X sprintf (scratchbuf, "%%cr%d", reg);
X oappend (scratchbuf);
X}
X
X/* ARGSUSED */
XOP_D (dummy)
X{
X codep++; /* skip mod/rm */
X sprintf (scratchbuf, "%%db%d", reg);
X oappend (scratchbuf);
X}
X
X/* ARGSUSED */
XOP_T (dummy)
X{
X codep++; /* skip mod/rm */
X sprintf (scratchbuf, "%%tr%d", reg);
X oappend (scratchbuf);
X}
X
XOP_rm (bytemode)
X{
X switch (bytemode) {
X case d_mode:
X oappend (names32[rm]);
X break;
X case w_mode:
X oappend (names16[rm]);
X break;
X }
X}
X
X/*
X * Load the file to disassemble, into memory
X * Decoding the Xenix a.out header
X */
Xloadaout(fname)
X{
X int fd;
X register int i;
X short magic;
X
X fd = open(fname, 0);
X if (fd == 0) {
X perror(fname); exit(1);
X }
X if (read(fd, &magic, 2) != 2) {
X perror(fname); exit(1);
X }
X lseek(fd, 0L, 0);
X if (magic == X_MAGIC) {
X if (read(fd, &xoutx, sizeof xoutx) != sizeof xoutx) {
X perror(fname); exit(1);
X }
X/* if ((xoutx.x_cpu & XC_CPU) != XC_386)
X fatal("Not a 80386 executable file - %s\n", fname); */
X if (read(fd, &xoutxe, sizeof xoutxe) != sizeof xoutxe) {
X perror(fname); exit(1);
X }
X if (!(xoutx.x_renv & XE_SEG))
X fatal("Not a Xenix segmented file - %s\n", fname);
X lseek(fd, xoutxe.xe_segpos, 0);
X segcount = xoutxe.xe_segsize / sizeof(struct xseg);
X if (segcount > MAXSEG)
X fatal("Too many segments (%d)", segcount);
X if (read(fd, xoutxs, segcount * sizeof(struct xseg)) != segcount * sizeof(struct xseg)) {
X perror(fname); exit(1);
X }
X for (i = 0; i < segcount; i++) {
X switch (xoutxs[i].xs_type) {
X case XS_TTEXT:
X if (textsegp) fatal("Multiple text segments");
X textsegp = &xoutxs[i];
X textseg = textsegp->xs_seg;
X break;
X
X case XS_TDATA:
X if (datasegp) fatal("Multiple data segments");
X datasegp = &xoutxs[i];
X dataseg = datasegp->xs_seg;
X break;
X
X case XS_TSYMS:
X if (xoutxs[i].xs_attr != XS_SXSEG)
X continue;
X if (symsegp) fatal("Multiple symbol segments");
X symsegp = &xoutxs[i];
X break;
X
X case XS_TREL:
X break;
X default:
X fatal("Unknown segment: %x", xoutxs[i].xs_type);
X }
X }
X if (textsegp == NULL) fatal("Undefined text segment");
X if (datasegp == NULL) fatal("Undefined data segment");
X if (symsegp != NULL)
X readsymbols(fd);
X textp = (unsigned char *)malloc(textsegp->xs_psize);
X if (textp == NULL) fatal("Out of memory");
X xtextp = textp;
X datap = (unsigned char *)malloc(datasegp->xs_psize);
X if (datap == NULL) fatal("Out of memory");
X lseek(fd, textsegp->xs_filpos, 0);
X if (read(fd, textp, textsegp->xs_psize) != textsegp->xs_psize) {
X perror(fname); fatal("File read error (text segment)");
X }
X lseek(fd, datasegp->xs_filpos, 0);
X if (read(fd, datap, datasegp->xs_psize) != datasegp->xs_psize) {
X perror(fname);
X fatal("File read error (data segment)");
X }
X textsize = textsegp->xs_vsize;
X datasize = datasegp->xs_vsize;
X database = datasegp->xs_rbase;
X } else if (magic == 0x5a4d) {
X /* msdos .exe file */
X if (read(fd, &exehdr, sizeof exehdr) != sizeof exehdr) {
X perror(fname); exit(1);
X }
X datasize = exehdr.csoff * 16;
X textsize = exehdr.lengthp * 512 - datasize - exehdr.hdrsize*16;
X if (exehdr.lengthb)
X textsize += exehdr.lengthb - 512;
X database = 0;
X textp = (unsigned char *)malloc(textsize);
X if (textp == NULL) fatal("Out of memory");
X xtextp = textp;
X datap = (unsigned char *)malloc(datasize);
X if (datap == NULL) fatal("Out of memory");
X lseek(fd, exehdr.hdrsize * 16, 0);
X if (read(fd, datap, datasize) != datasize) {
X perror(fname);
X fatal("File read error (data segment)");
X }
X if (read(fd, textp, textsize) != textsize) {
X perror(fname); fatal("File read error (text segment)");
X }
X } else
X fatal("Not a recognized executable file - %s\n", fname);
X close(fd);
X}
X
Xreadsymbols(fd)
X{
X register char *symp;
X char *symendp;
X int type, seg, value;
X char *name;
X int i;
X
X symp = (char *)malloc(symsegp->xs_psize);
X if (symp == NULL) fatal("Out of memory");
X lseek(fd, symsegp->xs_filpos, 0);
X if ((i = read(fd, symp, symsegp->xs_psize)) != symsegp->xs_psize)
X fatal("Symbol Table read error");
X symendp = symp + symsegp->xs_psize;
X while (symp < symendp) {
X type = ((struct sym *)symp)->s_type;
X seg = ((struct sym *)symp)->s_seg;
X value = ((struct sym *)symp)->s_value;
X name = symp + sizeof(struct sym);
X symp += sizeof(struct sym) + strlen(name) + 1;
X if (seg == textseg)
X enter(name, value, TEXTSEG|DEFINED);
X else if (seg == dataseg)
X enter(name, value, DATASEG|DEFINED);
X }
X}
X
Xfatal(f, args)
X{
X vfprintf(stderr, f, &args);
X fprintf(stderr, "\n");
X exit(1);
X}
X
X/*
X * Look up a symbol in symboltable.
X * Enter it as undefined if not
X * already there.
X */
Xstruct symtab *lookup(addr, ref)
X unsigned int addr;
X{
X register struct symtab *symtp,**symhp;
X int seg = ref & (TEXTSEG|DATASEG);
X
X symhp = &symhash[addr % SYMHS];
X while (symtp = *symhp) {
X if (addr == symtp->symval && (seg & symtp->symflags)) {
X if (!pass2) {
X symtp->symflags |= ref;
X symtp->symrefcount++;
X }
X return symtp;
X }
X if ((++symhp) >= &symhash[SYMHS])
X symhp = symhash;
X }
X if (pass2 || ref & NOENTER || !aflag && addr < THRESHOLD)
X return NULL;
X symtp = enter(NULL, addr, ref|GENERATED);
X symtp->symrefcount++;
X return symtp;
X}
X
X/*
X * enter a symbol into symboltable.
X */
Xstruct symtab *enter(id, addr, ref)
X char *id;
X unsigned addr;
X{
X register struct symtab *symtp, **symhp, **osymhp;
X int seg = ref & (DATASEG|TEXTSEG);
X
X symcount++;
X osymhp = symhp = &symhash[addr % SYMHS];
X while (symtp = *symhp) {
X if (++symhp >= &symhash[SYMHS])
X symhp = symhash;
X if (symhp == osymhp)
X fatal("Symbol table overflow");
X if (addr == symtp->symval && (seg & symtp->symflags))
X return symtp;
X/* fprintf(stderr, "Multiple definitions of symbol %s addr=%x, seg=%d, ref=%d\n", id ? id : "", addr, seg, ref); */
X }
X symtp = (struct symtab *)malloc(sizeof(struct symtab));
X *symhp = symtp;
X symtp->symflags = ref;
X symtp->symval = addr;
X symtp->symrefcount = 0;
X if (id)
X symtp->symstring = strdup(id);
X else {
X symtp->symstring = NULL;
X symtp->symflags |= GENERATED;
X }
X return symtp;
X}
X
Xchar *
Xsymname(symp)
X struct symtab *symp;
X{
X static char id[20];
X
X if (symp->symstring)
X return symp->symstring;
X sprintf(id, "%s0%x", symp->symflags & TEXTSEG ?
X (symp->symflags & CALLREF ? "P_" : "L") :
X symp->symflags & DATASEG ? "D" : "X", symp->symval);
X return id;
X}
X
Xchar *
Xgetimmed(val)
X unsigned int val;
X{
X static char scratch[20];
X register struct symtab *symp;
X
X if (*start_codep == 0x68)
X sprintf(scratch, "$%s", datasymbol(val, PUSHLIMMED, 0));
X else
X sprintf(scratch, "$%s", datasymbol(val, 0, 0));
X return scratch;
X}
X
X
Xchar *
Xdatasymbol(addr, ref, hexdef)
X unsigned int addr;
X{
X register struct symtab *symp;
X static char scratch[20];
X
X if (addr == 0) {
X return "0";
X }
X if (addr >= database && addr < database + xoutx.x_data + xoutx.x_bss) {
X symp = lookup(addr, DATASEG|ref);
X if (pass2) {
X if (symp != NULL) {
X if (symp->symflags & ASCIZ)
X return ascizdata(addr);
X if (symp->symstring)
X return symp->symstring;
X }
X sprintf(scratch, "D_0%x", addr);
X return scratch;
X }
X }
X if (addr < 10 /* || !hexdef */)
X sprintf(scratch, "%d", addr);
X else
X sprintf(scratch, "%#x", addr);
X return scratch;
X}
X
Xscomp(syp1, syp2)
X register struct symtab **syp1, **syp2;
X{
X if ((*syp1)->symval < (*syp2)->symval)
X return -1;
X else if ((*syp1)->symval > (*syp2)->symval)
X return 1;
X return 0;
X}
X
Xsymtabpass()
X{
X struct symtab *symarr[SYMHS];
X register int i, j;
X int labno;
X register struct symtab *symp;
X char id[20];
X int syc;
X
X /*
X * Look for "case" jump tables
X */
X for (i = 0; i < SYMHS; i++) {
X if ((symp = symhash[i]) && symp->symrefcount == 1 && symp->symflags & (WORDREF|DWORDREF) && !(symp->symflags & (CALLREF|JUMPREF))) {
X unsigned int addr = symp->symval;
X unsigned int disp;
X register struct symtab *labp;
X while (addr < textsize) {
X register int j;
X for (j = 1; j < 4; j++)
X if (lookup(addr+j, NOENTER))
X goto bloop;
X disp = *(unsigned int *)(textp+addr);
X if (disp > 0 && disp < textsize)
X labp = lookup(disp, TEXTSEG|JUMPREF);
X addr += 4;
X }
X bloop: ;
X }
X }
X
X syc = 0;
X for (i = 0; i < SYMHS; i++)
X if (symarr[syc] = symhash[i])
X syc++;
X qsort(symarr, syc, sizeof(struct symtab *), scomp);
X printf("%d symbols defined\n", syc);
X
X /*
X * Assign label names for code labels
X */
X labno = 0;
X for (i = 0; i < syc; i++) {
X if ((symp = symarr[i]) && symp->symstring == NULL
X && symp->symflags & TEXTSEG) {
X
X sprintf(id, "L%d", ++labno);
X symp->symstring = strdup(id);
X }
X }
X
X /*
X * Look for asciz strings
X */
X for (i = 0; i < syc; i++) {
X unsigned addr1, addr2;
X if ((symp = symarr[i]) == NULL)
X continue;
X if (symp->symflags & DATASEG && symp->symflags & PUSHLIMMED
X && symp->symrefcount == 1) {
X for (j = i+1; j < syc; j++)
X if (symarr[j] && symarr[j]->symflags & DATASEG)
X break;
X if (j == syc)
X break;
X addr1 = symp->symval;
X addr2 = symarr[j]->symval;
X if (addr2 > database + xoutx.x_data
X || addr1 < database)
X continue;
X for (j = addr1; j < addr2; j++)
X if (datap[j - database] == '\0')
X break;
X dummy();
X if (j < addr2 && ((j + 4) & ~3) == addr2)
X/* if (j == addr2-1 || j == addr2-2 || j == addr2-3) */
X symarr[i]->symflags |= ASCIZ;
X
X }
X }
X
X /*
X * Assign label names for data labels
X */
X labno = 0;
X for (i = 0; i < syc; i++) {
X if ((symp = symarr[i]) && symp->symstring == NULL
X && symp->symflags & DATASEG) {
X
X sprintf(id, "D%d", ++labno);
X symp->symstring = strdup(id);
X }
X }
X}
X
Xdummy() {}
X
Xchar *
Xascizdata(addr)
X{
X register unsigned char *cp1 = datap + addr - database;
X static char buf[1000];
X register unsigned char *cp2 = buf;
X register c;
X
X *cp2++ = '"';
X while (c = *cp1++) {
X switch (c) {
X case '\n': *cp2++ = '\\'; *cp2++ = 'n'; break;
X case '\t': *cp2++ = '\\'; *cp2++ = 't'; break;
X case '\r': *cp2++ = '\\'; *cp2++ = 'r'; break;
X default:
X if (c >= ' ' && c < 127)
X *cp2++ = c;
X else {
X *cp2++ = '\\';
X if (c & 0300) *cp2++ = (c >> 6) + '0';
X if (c & 0070) *cp2++ = ((c >> 3) & 7) + '0';
X *cp2++ = (c & 7) + '\0';
X }
X }
X if (cp2 >= buf+sizeof(buf)-2)
X fatal("Too long asciz string");
X }
X *cp2++ = '"';
X *cp2++ = '\0';
X return buf;
X}
SHAR_EOF
$TOUCH -am 1231092790 disasm.c &&
chmod 0640 disasm.c ||
echo "restore of disasm.c failed"
set `wc -c disasm.c`;Wc_c=$1
if test "$Wc_c" != "30568"; then
echo original size 30568, current size $Wc_c
fi
# ============= 386opcodes.h ==============
echo "x - extracting 386opcodes.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > 386opcodes.h &&
X/*
X * The main tables describing the instructions is essentially a copy
X * of the "Opcode Map" chapter (Appendix A) of the Intel 80386
X * Programmers Manual. Usually, there is a capital letter, followed
X * by a small letter. The capital letter tell the addressing mode,
X * and the small letter tells about the operand size. Refer to
X * the Intel manual for details.
X */
X
X#define Eb OP_E, b_mode
X#define indirEb OP_indirE, b_mode
X#define Gb OP_G, b_mode
X#define Ev OP_E, v_mode
X#define indirEv OP_indirE, v_mode
X#define Ew OP_E, w_mode
X#define Ma OP_E, v_mode
X#define M OP_E, 0
X#define Mp OP_E, 0 /* ? */
X#define Gv OP_G, v_mode
X#define Gw OP_G, w_mode
X#define Rw OP_rm, w_mode
X#define Rd OP_rm, d_mode
X#define Ib OP_I, b_mode
X#define sIb OP_sI, b_mode /* sign extened byte */
X#define Iv OP_I, v_mode
X#define Iw OP_I, w_mode
X#define Jb OP_J, b_mode
X#define Jv OP_J, v_mode
X#define ONE OP_ONE, 0
X#define Cd OP_C, d_mode
X#define Dd OP_D, d_mode
X#define Td OP_T, d_mode
X
X#define eAX OP_REG, eAX_reg
X#define eBX OP_REG, eBX_reg
X#define eCX OP_REG, eCX_reg
X#define eDX OP_REG, eDX_reg
X#define eSP OP_REG, eSP_reg
X#define eBP OP_REG, eBP_reg
X#define eSI OP_REG, eSI_reg
X#define eDI OP_REG, eDI_reg
X#define AL OP_REG, al_reg
X#define CL OP_REG, cl_reg
X#define DL OP_REG, dl_reg
X#define BL OP_REG, bl_reg
X#define AH OP_REG, ah_reg
X#define CH OP_REG, ch_reg
X#define DH OP_REG, dh_reg
X#define BH OP_REG, bh_reg
X#define AX OP_REG, ax_reg
X#define DX OP_REG, dx_reg
X#define indirDX OP_REG, indir_dx_reg
X
X#define Sw OP_SEG, w_mode
X#define Ap OP_DIR, lptr
X#define Av OP_DIR, v_mode
X#define Ob OP_OFF, b_mode
X#define Ov OP_OFF, v_mode
X#define Xb OP_DSSI, b_mode
X#define Xv OP_DSSI, v_mode
X#define Yb OP_ESDI, b_mode
X#define Yv OP_ESDI, v_mode
X
X#define es OP_REG, es_reg
X#define ss OP_REG, ss_reg
X#define cs OP_REG, cs_reg
X#define ds OP_REG, ds_reg
X#define fs OP_REG, fs_reg
X#define gs OP_REG, gs_reg
X
Xint OP_E(), OP_indirE(), OP_G(), OP_I(), OP_sI(), OP_REG();
Xint OP_J(), OP_SEG();
Xint OP_DIR(), OP_OFF(), OP_DSSI(), OP_ESDI(), OP_ONE(), OP_C();
Xint OP_D(), OP_T(), OP_rm();
X
X
X#define b_mode 1
X#define v_mode 2
X#define w_mode 3
X#define d_mode 4
X
X#define es_reg 100
X#define cs_reg 101
X#define ss_reg 102
X#define ds_reg 103
X#define fs_reg 104
X#define gs_reg 105
X#define eAX_reg 107
X#define eCX_reg 108
X#define eDX_reg 109
X#define eBX_reg 110
X#define eSP_reg 111
X#define eBP_reg 112
X#define eSI_reg 113
X#define eDI_reg 114
X
X#define lptr 115
X
X#define al_reg 116
X#define cl_reg 117
X#define dl_reg 118
X#define bl_reg 119
X#define ah_reg 120
X#define ch_reg 121
X#define dh_reg 122
X#define bh_reg 123
X
X#define ax_reg 124
X#define cx_reg 125
X#define dx_reg 126
X#define bx_reg 127
X#define sp_reg 128
X#define bp_reg 129
X#define si_reg 130
X#define di_reg 131
X
X#define indir_dx_reg 150
X
X#define GRP1b NULL, NULL, 0
X#define GRP1S NULL, NULL, 1
X#define GRP1Ss NULL, NULL, 2
X#define GRP2b NULL, NULL, 3
X#define GRP2S NULL, NULL, 4
X#define GRP2b_one NULL, NULL, 5
X#define GRP2S_one NULL, NULL, 6
X#define GRP2b_cl NULL, NULL, 7
X#define GRP2S_cl NULL, NULL, 8
X#define GRP3b NULL, NULL, 9
X#define GRP3S NULL, NULL, 10
X#define GRP4 NULL, NULL, 11
X#define GRP5 NULL, NULL, 12
X#define GRP6 NULL, NULL, 13
X#define GRP7 NULL, NULL, 14
X#define GRP8 NULL, NULL, 15
X
X#define FLOATCODE 50
X#define FLOAT NULL, NULL, FLOATCODE
X
Xstruct dis386 {
X char *name;
X int (*op1)();
X int bytemode1;
X int (*op2)();
X int bytemode2;
X int (*op3)();
X int bytemode3;
X};
X
Xstruct dis386 dis386[] = {
X { "addb", Eb, Gb }, /* 00 */
X { "addS", Ev, Gv },
X { "addb", Gb, Eb },
X { "addS", Gv, Ev },
X { "addb", AL, Ib },
X { "addS", eAX, Iv },
X { "pushl", es },
X { "popl", es },
X { "orb", Eb, Gb }, /* 08 */
X { "orS", Ev, Gv },
X { "orb", Gb, Eb },
X { "orS", Gv, Ev },
X { "orb", AL, Ib },
X { "orS", eAX, Iv },
X { "pushl", cs },
X { "(bad)" }, /* 2-byte escape */
X
X { "adcb", Eb, Gb }, /* 10 */
X { "adcS", Ev, Gv },
X { "adcb", Gb, Eb },
X { "adcS", Gv, Ev },
X { "adcb", AL, Ib },
X { "adcS", eAX, Iv },
X { "pushl", ss },
X { "popl", ss },
X { "sbbb", Eb, Gb }, /* 18 */
X { "sbbS", Ev, Gv },
X { "sbbb", Gb, Eb },
X { "sbbS", Gv, Ev },
X { "sbbb", AL, Ib },
X { "sbbS", eAX, Iv },
X { "pushl", ds },
X { "popl", ds },
X
X { "andb", Eb, Gb }, /* 20 */
X { "andS", Ev, Gv },
X { "andb", Gb, Eb },
X { "andS", Gv, Ev },
X { "andb", AL, Ib },
X { "andS", eAX, Iv },
X { "(bad)" }, /* (SEG=ES) */
X { "daa" },
X { "subb", Eb, Gb }, /* 28 */
X { "subS", Ev, Gv },
X { "subb", Gb, Eb },
X { "subS", Gv, Ev },
X { "subb", AL, Ib },
X { "subS", eAX, Iv },
X { "(bad)" }, /* (SEG=CS) */
X { "das" },
X
X { "xorb", Eb, Gb }, /* 30 */
X { "xorS", Ev, Gv },
X { "xorb", Gb, Eb },
X { "xorS", Gv, Ev },
X { "xorb", AL, Ib },
X { "xorS", eAX, Iv },
X { "(bad)" },
X { "aaa" },
X { "cmpb", Eb, Gb },
X { "cmpS", Ev, Gv },
X { "cmpb", Gb, Eb },
X { "cmpS", Gv, Ev },
X { "cmpb", AL, Ib },
X { "cmpS", eAX, Iv },
X { "(bad)" },
X { "aas" },
X { "incS", eAX },
X { "incS", eCX },
X { "incS", eDX },
X { "incS", eBX },
X { "incS", eSP },
X { "incS", eBP },
X { "incS", eSI },
X { "incS", eDI },
X { "decS", eAX },
X { "decS", eCX },
X { "decS", eDX },
X { "decS", eBX },
X { "decS", eSP },
X { "decS", eBP },
X { "decS", eSI },
X { "decS", eDI },
X { "pushS", eAX },
X { "pushS", eCX },
X { "pushS", eDX },
X { "pushS", eBX },
X { "pushS", eSP },
X { "pushS", eBP },
X { "pushS", eSI },
X { "pushS", eDI },
X { "popS", eAX },
X { "popS", eCX },
X { "popS", eDX },
X { "popS", eBX },
X { "popS", eSP },
X { "popS", eBP },
X { "popS", eSI },
X { "popS", eDI },
X { "pusha" },
X { "popa" },
X { "boundS", Gv, Ma },
X { "arpl", Ew, Gw },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "pushS", Iv },
X { "imulS", Gv, Ev, Iv },
X { "pushl", sIb },
X { "imulS", Gv, Ev, Ib },
X { "insb", Yb, indirDX },
X { "insS", Yv, indirDX },
X { "outsb", indirDX, Xb },
X { "outsS", indirDX, Xv },
X { "jo", Jb },
X { "jno", Jb },
X { "jb", Jb },
X { "jae", Jb },
X { "je", Jb },
X { "jne", Jb },
X { "jbe", Jb },
X { "ja", Jb },
X { "js", Jb },
X { "jns", Jb },
X { "jp", Jb },
X { "jnp", Jb },
X { "jl", Jb },
X { "jnl", Jb },
X { "jle", Jb },
X { "jg", Jb },
X { GRP1b },
X { GRP1S },
X { "(bad)" },
X { GRP1Ss },
X { "testb", Eb, Gb },
X { "testS", Ev, Gv },
X { "xchgb", Eb, Gb },
X { "xchgS", Ev, Gv },
X { "movb", Eb, Gb },
X { "movS", Ev, Gv },
X { "movb", Gb, Eb },
X { "movS", Gv, Ev },
X { "movw", Ew, Sw },
X { "leaS", Gv, M },
X { "movw", Sw, Ew },
X { "popS", Ev },
X { "nop" },
X { "xchgS", eCX, eAX },
X { "xchgS", eDX, eAX },
X { "xchgS", eBX, eAX },
X { "xchgS", eSP, eAX },
X { "xchgS", eBP, eAX },
X { "xchgS", eSI, eAX },
X { "xchgS", eDI, eAX },
X { "cwtl" },
X { "cltd" },
X { "lcall", Ap },
X { "(bad)" },
X { "pushf" },
X { "popf" },
X { "sahf" },
X { "lahf" },
X { "movb", AL, Ob },
X { "movS", eAX, Ov },
X { "movb", Ob, AL },
X { "movS", Ov, eAX },
X { "movsb", Yb, Xb },
X { "movsS", Yv, Xv },
X { "cmpsb", Yb, Xb },
X { "cmpsS", Yv, Xv },
X { "testb", AL, Ib },
X { "testS", eAX, Iv },
X { "stosb", Yb, AL },
X { "stosS", Yv, eAX },
X { "lodsb", AL, Xb },
X { "lodsS", eAX, Xv },
X { "scasb", AL, Xb },
X { "scasS", eAX, Xv },
X { "movb", AL, Ib },
X { "movb", CL, Ib },
X { "movb", DL, Ib },
X { "movb", BL, Ib },
X { "movb", AH, Ib },
X { "movb", CH, Ib },
X { "movb", DH, Ib },
X { "movb", BH, Ib },
X { "movS", eAX, Iv },
X { "movS", eCX, Iv },
X { "movS", eDX, Iv },
X { "movS", eBX, Iv },
X { "movS", eSP, Iv },
X { "movS", eBP, Iv },
X { "movS", eSI, Iv },
X { "movS", eDI, Iv },
X { GRP2b },
X { GRP2S },
X { "ret", Iw },
X { "ret" },
X { "lesS", Gv, Mp },
X { "ldsS", Gv, Mp },
X { "movb", Eb, Ib },
X { "movS", Ev, Iv },
X { "enter", Iw, Ib },
X { "leave" },
X { "lret", Iw },
X { "lret" },
X { "int3" },
X { "int", Ib },
X { "into" },
X { "iret" },
X { GRP2b_one },
X { GRP2S_one },
X { GRP2b_cl },
X { GRP2S_cl },
X { "aam", Ib },
X { "aad", Ib },
X { "(bad)" },
X { "xlat" },
X { FLOAT },
X { FLOAT },
X { FLOAT },
X { FLOAT },
X { FLOAT },
X { FLOAT },
X { FLOAT },
X { FLOAT },
X { "loopne", Jb },
X { "loope", Jb },
X { "loop", Jb },
X { "jCcxz", Jb },
X { "inb", AL, Ib },
X { "inS", eAX, Ib },
X { "outb", Ib, AL },
X { "outS", Ib, eAX },
X { "call", Av },
X { "jmp", Jv },
X { "ljmp", Ap },
X { "jmp", Jb },
X { "inb", AL, indirDX },
X { "inS", eAX, indirDX },
X { "outb", indirDX, AL },
X { "outS", indirDX, eAX },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "hlt" },
X { "cmc" },
X { GRP3b },
X { GRP3S },
X { "clc" },
X { "stc" },
X { "cli" },
X { "sti" },
X { "cld" },
X { "std" },
X { GRP4 },
X { GRP5 },
X};
X
Xstruct dis386 dis386_twobyte[] = {
X { GRP6 },
X { GRP7 },
X { "larS", Gv, Ew },
X { "lslS", Gv, Ew },
X { "(bad)" },
X { "(bad)" },
X { "clts" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "movl", Rd, Cd },
X { "movl", Rd, Dd },
X { "movl", Cd, Rd },
X { "movl", Dd, Rd },
X { "movl", Rd, Td },
X { "(bad)" },
X { "movl", Td, Rd },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "jo", Jv },
X { "jno", Jv },
X { "jb", Jv },
X { "jae", Jv },
X { "je", Jv },
X { "jne", Jv },
X { "jbe", Jv },
X { "ja", Jv },
X { "js", Jv },
X { "jns", Jv },
X { "jp", Jv },
X { "jnp", Jv },
X { "jl", Jv },
X { "jge", Jv },
X { "jle", Jv },
X { "jg", Jv },
X { "seto", Eb },
X { "setno", Eb },
X { "setb", Eb },
X { "setae", Eb },
X { "sete", Eb },
X { "setne", Eb },
X { "setbe", Eb },
X { "seta", Eb },
X { "sets", Eb },
X { "setns", Eb },
X { "setp", Eb },
X { "setnp", Eb },
X { "setl", Eb },
X { "setge", Eb },
X { "setle", Eb },
X { "setg", Eb },
X { "pushl", fs },
X { "popl", fs },
X { "(bad)" },
X { "btS", Ev, Gv },
X { "shldS", Ev, Gv, Ib },
X { "shldS", Ev, Gv, CL },
X { "(bad)" },
X { "(bad)" },
X { "pushl", gs },
X { "popl", gs },
X { "(bad)" },
X { "btsS", Ev, Gv },
X { "shrdS", Ev, Gv, Ib },
X { "shrdS", Ev, Gv, CL },
X { "(bad)" },
X { "imulS", Gv, Ev },
X { "(bad)" },
X { "(bad)" },
X { "lssS", Gv, Mp },
X { "btrS", Ev, Gv },
X { "lfsS", Gv, Mp },
X { "lgsS", Gv, Mp },
X { "movzbS", Gv, Eb },
X { "movzwS", Gv, Ew },
X { "(bad)" },
X { "(bad)" },
X { GRP8 },
X { "btcS", Ev, Gv },
X { "bsfS", Gv, Ev },
X { "bsrS", Gv, Ev },
X { "movsbS", Gv, Eb },
X { "movswS", Gv, Ew },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X};
X
X
Xstatic char *names32[]={
X "%eax","%ecx","%edx","%ebx", "%esp","%ebp","%esi","%edi",
X};
Xstatic char *names16[] = {
X "%ax","%cx","%dx","%bx","%sp","%bp","%si","%di",
X};
Xstatic char *names8[] = {
X "%al","%cl","%dl","%bl","%ah","%ch","%dh","%bh",
X};
Xstatic char *names_seg[] = {
X "%es","%cs","%ss","%ds","%fs","%gs","%?","%?",
X};
Xstatic char *names16_OP_E[] = {
X "%bx,%si", "%bx,%di", "%bp,%si", "%bp,%di", "%si", "%di","%bp","%bx",
X};
X
Xstruct dis386 grps[][8] = {
X {
X { "addb", Eb, Ib },
X { "orb", Eb, Ib },
X { "adcb", Eb, Ib },
X { "sbbb", Eb, Ib },
X { "andb", Eb, Ib },
X { "subb", Eb, Ib },
X { "xorb", Eb, Ib },
X { "cmpb", Eb, Ib }
X },
X {
X { "addS", Ev, Iv },
X { "orS", Ev, Iv },
X { "adcS", Ev, Iv },
X { "sbbS", Ev, Iv },
X { "andS", Ev, Iv },
X { "subS", Ev, Iv },
X { "xorS", Ev, Iv },
X { "cmpS", Ev, Iv }
X },
X {
X { "addS", Ev, sIb },
X { "orS", Ev, sIb },
X { "adcS", Ev, sIb },
X { "sbbS", Ev, sIb },
X { "andS", Ev, sIb },
X { "subS", Ev, sIb },
X { "xorS", Ev, sIb },
X { "cmpS", Ev, sIb }
X },
X {
X { "rolb", Eb, Ib },
X { "rorb", Eb, Ib },
X { "rclb", Eb, Ib },
X { "rcrb", Eb, Ib },
X { "shlb", Eb, Ib },
X { "shrb", Eb, Ib },
X { "(bad)" },
X { "sarb", Eb, Ib },
X },
X {
X { "rolS", Ev, Ib },
X { "rorS", Ev, Ib },
X { "rclS", Ev, Ib },
X { "rcrS", Ev, Ib },
X { "shlS", Ev, Ib },
X { "shrS", Ev, Ib },
X { "(bad)" },
X { "sarS", Ev, Ib },
X },
X {
X { "rolb", Eb },
X { "rorb", Eb },
X { "rclb", Eb },
X { "rcrb", Eb },
X { "shlb", Eb },
X { "shrb", Eb },
X { "(bad)" },
X { "sarb", Eb },
X },
X {
X { "rolS", Ev },
X { "rorS", Ev },
X { "rclS", Ev },
X { "rcrS", Ev },
X { "shlS", Ev },
X { "shrS", Ev },
X { "(bad)" },
X { "sarS", Ev },
X },
X {
X { "rolb", Eb, CL },
X { "rorb", Eb, CL },
X { "rclb", Eb, CL },
X { "rcrb", Eb, CL },
X { "shlb", Eb, CL },
X { "shrb", Eb, CL },
X { "(bad)" },
X { "sarb", Eb, CL },
X },
X {
X { "rolS", Ev, CL },
X { "rorS", Ev, CL },
X { "rclS", Ev, CL },
X { "rcrS", Ev, CL },
X { "shlS", Ev, CL },
X { "shrS", Ev, CL },
X { "(bad)" },
X { "sarS", Ev, CL }
X },
X {
X { "testb", Eb, Ib },
X { "(bad)", Eb },
X { "notb", Eb },
X { "negb", Eb },
X { "mulb", AL, Eb },
X { "imulb", AL, Eb },
X { "divb", AL, Eb },
X { "idivb", AL, Eb }
X },
X {
X { "testS", Ev, Iv },
X { "(bad)" },
X { "notS", Ev },
X { "negS", Ev },
X { "mulS", eAX, Ev },
X { "imulS", eAX, Ev },
X { "divS", eAX, Ev },
X { "idivS", eAX, Ev },
X },
X {
X { "incb", Eb },
X { "decb", Eb },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X },
X {
X { "incS", Ev },
X { "decS", Ev },
X { "call", indirEv },
X { "lcall", indirEv },
X { "jmp", indirEv },
X { "ljmp", indirEv },
X { "pushS", Ev },
X { "(bad)" },
X },
X {
X { "sldt", Ew },
X { "str", Ew },
X { "lldt", Ew },
X { "ltr", Ew },
X { "verr", Ew },
X { "verw", Ew },
X { "(bad)" },
X { "(bad)" }
X },
X {
X { "sgdt", Ew },
X { "sidt", Ew },
X { "lgdt", Ew },
X { "lidt", Ew },
X { "smsw", Ew },
X { "(bad)" },
X { "lmsw", Ew },
X { "(bad)" },
X },
X {
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "btS", Ev, Ib },
X { "btsS", Ev, Ib },
X { "btrS", Ev, Ib },
X { "btcS", Ev, Ib },
X }
X};
X
X#define PREFIX_REPZ 1
X#define PREFIX_REPNZ 2
X#define PREFIX_LOCK 4
X#define PREFIX_CS 8
X#define PREFIX_SS 0x10
X#define PREFIX_DS 0x20
X#define PREFIX_ES 0x40
X#define PREFIX_FS 0x80
X#define PREFIX_GS 0x100
X#define PREFIX_DATA 0x200
X#define PREFIX_ADR 0x400
X#define PREFIX_FWAIT 0x800
X
SHAR_EOF
$TOUCH -am 0715132790 386opcodes.h &&
chmod 0600 386opcodes.h ||
echo "restore of 386opcodes.h failed"
set `wc -c 386opcodes.h`;Wc_c=$1
if test "$Wc_c" != "15573"; then
echo original size 15573, current size $Wc_c
fi
# ============= 387opcodes.h ==============
echo "x - extracting 387opcodes.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > 387opcodes.h &&
X
Xchar *float_mem[] = {
X /* d8 */
X "fadds",
X "fmuls",
X "fcoms",
X "fcomps",
X "fsubs",
X "fsubrs",
X "fdivs",
X "fdivrs",
X /* d9 */
X "flds",
X "(bad)",
X "fsts",
X "fstps",
X "fldenv",
X "fldcw",
X "fNstenv",
X "fNstcw",
X /* da */
X "fiaddl",
X "fimull",
X "ficoml",
X "ficompl",
X "fisubl",
X "fisubrl",
X "fidivl",
X "fidivrl",
X /* db */
X "fildl",
X "(bad)",
X "fistl",
X "fistpl",
X "(bad)",
X "fldt",
X "(bad)",
X "fstpt",
X /* dc */
X "faddl",
X "fmull",
X "fcoml",
X "fcompl",
X "fsubl",
X "fsubrl",
X "fdivl",
X "fdivrl",
X /* dd */
X "fldl",
X "(bad)",
X "fstl",
X "fstpl",
X "frstor",
X "(bad)",
X "fNsave",
X "fNstsw",
X /* de */
X "fiadd",
X "fimul",
X "ficom",
X "ficomp",
X "fisub",
X "fisubr",
X "fidiv",
X "fidivr",
X /* df */
X "fild",
X "(bad)",
X "fist",
X "fistp",
X "fbld",
X "fildll",
X "fbstp",
X "fistpll",
X };
X
X #define ST OP_ST, 0
X #define STi OP_STi, 0
X int OP_ST(), OP_STi();
X
X #define FGRPd9_2 NULL, NULL, 0
X #define FGRPd9_4 NULL, NULL, 1
X #define FGRPd9_5 NULL, NULL, 2
X #define FGRPd9_6 NULL, NULL, 3
X #define FGRPd9_7 NULL, NULL, 4
X #define FGRPda_5 NULL, NULL, 5
X #define FGRPdb_4 NULL, NULL, 6
X #define FGRPde_3 NULL, NULL, 7
X #define FGRPdf_4 NULL, NULL, 8
X
X struct dis386 float_reg[][8] = {
X {
X { "fadd", ST, STi },
X { "fmul", ST, STi },
X { "fcom", STi },
X { "fcomp", STi },
X { "fsub", ST, STi },
X { "fsubr", ST, STi },
X { "fdiv", ST, STi },
X { "fdivr", ST, STi },
X },
X {
X { "fld", STi },
X { "fxch", STi },
X { FGRPd9_2 },
X { "(bad)" },
X { FGRPd9_4 },
X { FGRPd9_5 },
X { FGRPd9_6 },
X { FGRPd9_7 },
X },
X {
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { FGRPda_5 },
X { "(bad)" },
X { "(bad)" },
X },
X {
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { FGRPdb_4 },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X },
X {
X { "fadd", STi, ST },
X { "fmul", STi, ST },
X { "(bad)" },
X { "(bad)" },
X { "fsub", STi, ST },
X { "fsubr", STi, ST },
X { "fdiv", STi, ST },
X { "fdivr", STi, ST },
X },
X {
X { "ffree", STi },
X { "(bad)" },
X { "fst", STi },
X { "fstp", STi },
X { "fucom", STi },
X { "fucomp", STi },
X { "(bad)" },
X { "(bad)" },
X },
X {
X { "faddp", STi, ST },
X { "fmulp", STi, ST },
X { "(bad)" },
X { FGRPde_3 },
X { "fsubp", STi, ST },
X { "fsubrp", STi, ST },
X { "fdivp", STi, ST },
X { "fdivrp", STi, ST },
X },
X {
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X { FGRPdf_4 },
X { "(bad)" },
X { "(bad)" },
X { "(bad)" },
X },
X};
X
X
Xchar *fgrps[][8] = {
X{
X "fnop","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
X},
X{
X "fchs","fabs","(bad)","(bad)","ftst","fxam","(bad)","(bad)",
X},
X{
X "fld1","fldl2t","fldl2e","fldpi","fldlg2","fldln2","fldz","(bad)",
X},
X{
X "f2xm1","fyl2x","fptan","fpatan","fxtract","fprem1","fdecstp","fincstp",
X},
X{
X "fprem","fyl2xp1","fsqrt","fsincos","frndint","fscale","fsin","fcos",
X},
X{
X "(bad)","fucompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
X},
X{
X "feni(287 only)","fdisi(287 only)","fNclex","fNinit",
X "fNsetpm(287 only)","(bad)","(bad)","(bad)",
X},
X{
X "(bad)","fcompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
X},
X{
X "fNstsw","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
X},
X};
X
X
SHAR_EOF
$TOUCH -am 0714175390 387opcodes.h &&
chmod 0600 387opcodes.h ||
echo "restore of 387opcodes.h failed"
set `wc -c 387opcodes.h`;Wc_c=$1
if test "$Wc_c" != "3117"; then
echo original size 3117, current size $Wc_c
fi
# ============= macros ==============
echo "x - extracting macros (Text)"
sed 's/^X//' << 'SHAR_EOF' > macros &&
X;;
X;; Command file for post-processing output from disasm
X;;
X
X(progn
X(goto-char (point-min))
X(message "remove trailing tabs")
X(replace-regexp "\t$" "" nil)
X
X(goto-char (point-min))
X(message "remove nop instructions")
X(replace-regexp " nop ; unreachable$" "" nil)
X
X(goto-char (point-min))
X(message "remove all 'Hidden label' messages")
X(replace-regexp "^Warning: Hidden label: L[0-9]+\n" "" nil)
X
X(goto-char (point-min))
X(message "Convert data references")
X(replace-regexp "\\(0x18[89][0-9a-f][0-9a-f][0-9a-f][0-9a-f]\\)" "D\\1" nil)
X
X(goto-char (point-min))
X(message "Make -1's from 0xffffffff's")
X(replace-string "0xffffffff" "-1" nil)
X
X;; Make some simplifications
X
X;; replace all $_... and $D... to &... to simplify later processing
X(goto-char (point-min))
X(message "Convert 'address of' to &")
X(replace-regexp "\$\\([_D]\\)" "&\\1" nil)
X
X(goto-char (point-min))
X(message "Convert 'movl &...' to assignment statement")
X(replace-regexp "movl \\(&.*\\),\\(.*\\)$" "\\2 = \\1;" nil)
X
X;; move with converts
X(goto-char (point-min))
X(message "Convert movswl to assignment")
X(replace-regexp "movswl \\(.*\\),\\(%e..\\)$" "\\2 = (short)\\1;" nil)
X(goto-char (point-min))
X(message "Convert movsbl to assignment")
X(replace-regexp "movsbl \\(.*\\),\\(%e..\\)$" "\\2 = (char)\\1;" nil)
X(goto-char (point-min))
X(message "Convert movsbw to assignment")
X(replace-regexp "movsbw \\(.*\\),\\(%[a-z][a-z]\\)$" "\\2 = (char)\\1;" nil)
X
X(goto-char (point-min))
X(message "Convert movzwl to assignment")
X(replace-regexp "movzwl \\(.*\\),\\(%e..\\)$" "\\2 = (ushort)\\1;" nil)
X(goto-char (point-min))
X(message "Convert movzbl to assignment")
X(replace-regexp "movzbl \\(.*\\),\\(%e..\\)$" "\\2 = (uchar)\\1;" nil)
X(goto-char (point-min))
X(message "Convert movzbw to assignment")
X(replace-regexp "movzbw \\(.*\\),\\(%[a-z][a-z]\\)$" "\\2 = (uchar)\\1;" nil)
X
X;; Convert register moves to assignment statements
X(goto-char (point-min))
X(message "Convert register moves to assignments")
X(replace-regexp "movl \\(.*\\),\\(%e..\\)$" "\\2 = \\1;" nil)
X(goto-char (point-min))
X(replace-regexp "movl \\(%e..\\),\\(.*\\)$" "\\2 = \\1;" nil)
X(goto-char (point-min))
X(replace-regexp "movw \\(%..\\),\\(.*\\)$" "(word)\\2 = \\1;" nil)
X(goto-char (point-min))
X(replace-regexp "movw \\(.*\\),\\(%..\\)$" "\\2 = (word)\\1;" nil)
X(goto-char (point-min))
X(replace-regexp "movb \\(%..\\),\\(.*\\)$" "(byte)\\2 = \\1;" nil)
X(goto-char (point-min))
X(replace-regexp "movb \\(.*\\),\\(%..\\)$" "\\2 = (byte)\\1;" nil)
X
X(goto-char (point-min))
X(message "Convert 'leal' to assignment")
X(replace-regexp "leal \\(.*\\),\\(%e..\\)$" "\\2 = &\\1;" nil)
X
X
X(goto-char (point-min))
X(message "Convert immediate moves to assignments")
X(replace-regexp "movb $\\([0-9]*\\|0x[0-9a-f]*\\),\\(.*\\)$" "(byte)\\2 = \\1;" nil)
X(goto-char (point-min))
X(replace-regexp "movw $\\([0-9]*\\|0x[0-9a-f]*\\),\\(.*\\)$" "(word)\\2 = \\1;" nil)
X(goto-char (point-min))
X(replace-regexp "movl $\\([0-9]*\\|0x[0-9a-f]*\\),\\(.*\\)$" "\\2 = \\1;" nil)
X
X(goto-char (point-min))
X(message "Fix return's")
X(replace-string "leave
X ret" "return" nil)
X
X(goto-char (point-min))
X(replace-string "popl %esi
X popl %edi
X popl %ebx
X return" "return" nil)
X
X(goto-char (point-min))
X(replace-string "popl %esi
X popl %edi
X return" "return" nil)
X
X(goto-char (point-min))
X(replace-string "popl %esi
X popl %ebx
X return" "return" nil)
X
X(goto-char (point-min))
X(replace-string "popl %esi
X return" "return" nil)
X
X(goto-char (point-min))
X(message "Make return 0's")
X(replace-string "%eax = 0
X return" "return 0;
X" nil)
X
X(goto-char (point-min))
X(message "Convert jump statement conditionals")
X(replace-string " je " " j== " nil)
X(goto-char (point-min))
X(replace-string " jne " " j!= " nil)
X(goto-char (point-min))
X(replace-string " jl " " j< " nil)
X(goto-char (point-min))
X(replace-string " jnl " " j>= " nil)
X(goto-char (point-min))
X(replace-string " jg " " j> " nil)
X(goto-char (point-min))
X(replace-string " jle " " j<= " nil)
X
X(goto-char (point-min))
X(message "Convert simple compare and branch to if-statement")
X(replace-regexp "cmpl \\($.*\\),\\(.*\\)
X j\\([!=<>]*\\) \\(.*$\\)" "if (\\2 \\3 \\1) goto \\4;" nil)
X(goto-char (point-min))
X(replace-regexp "cmpl \\(.*\\),\\(%[a-z]*\\)
X j\\([!=<>]*\\) \\(.*$\\)" "if (\\2 \\3 \\1) goto \\4;" nil)
X(goto-char (point-min))
X(replace-regexp "cmpl \\(%[a-z]*\\),\\(.*\\)
X j\\([!=<>]*\\) \\(.*$\\)" "if (\\2 \\3 \\1) goto \\4;" nil)
X
X(goto-char (point-min))
X(replace-regexp "cmpw \\($.*\\),\\(.*\\)
X j\\([!=<>]*\\) \\(.*$\\)" "if ((word)\\2 \\3 \\1) goto \\4;" nil)
X(goto-char (point-min))
X(replace-regexp "cmpw \\(.*\\),\\(%[a-z]*\\)
X j\\([!=<>]*\\) \\(.*$\\)" "if (\\2 \\3 (word)\\1) goto \\4;" nil)
X(goto-char (point-min))
X(replace-regexp "cmpw \\(%[a-z]*\\),\\(.*\\)
X j\\([!=<>]*\\) \\(.*$\\)" "if ((word)\\2 \\3 \\1) goto \\4;" nil)
X
X(goto-char (point-min))
X(replace-regexp "cmpb \\($.*\\),\\(.*\\)
X j\\([!=<>]*\\) \\(.*$\\)" "if ((byte)\\2 \\3 \\1) goto \\4;" nil)
X(goto-char (point-min))
X(replace-regexp "cmpb \\(.*\\),\\(%[a-z]*\\)
X j\\([!=<>]*\\) \\(.*$\\)" "if (\\2 \\3 (byte)\\1) goto \\4;" nil)
X(goto-char (point-min))
X(replace-regexp "cmpb \\(%[a-z]*\\),\\(.*\\)
X j\\([!=<>]*\\) \\(.*$\\)" "if ((byte)\\2 \\3 \\1) goto \\4;" nil)
X
X(goto-char (point-min))
X(message "Convert bit test statements to if's")
X(replace-regexp "testl $\\([0-9]+\\|0x[0-9a-f]+\\),\\(.*\\)
X j!= \\(.*\\)$" "if (\\2 & $\\1) goto \\3;" nil)
X(goto-char (point-min))
X(replace-regexp "testl \\(%e..\\),\\(.*\\)
X j!= \\(.*\\)$" "if (\\1 & \\2) goto \\3;" nil)
X(goto-char (point-min))
X(replace-regexp "testl \\(%e..\\),\\(.*\\)
X j== \\(.*\\)$" "if (!(\\1 & \\2)) goto \\3;" nil)
X(goto-char (point-min))
X(replace-regexp "testw $\\([0-9]+\\|0x[0-9a-f]+\\),\\(.*\\)
X j!= \\(.*\\)$" "if ((word)\\2 & $\\1) goto \\3;" nil)
X(goto-char (point-min))
X(replace-regexp "testb $\\([0-9]+\\|0x[0-9a-f]+\\),\\(.*\\)
X j!= \\(.*\\)$" "if ((byte)\\2 & $\\1) goto \\3;" nil)
X
X(goto-char (point-min))
X(replace-regexp "testl $\\([0-9]+\\|0x[0-9a-f]+\\),\\(.*\\)
X j== \\(.*\\)$" "if (!(\\2 & $\\1)) goto \\3;" nil)
X(goto-char (point-min))
X(replace-regexp "testw $\\([0-9]+\\|0x[0-9a-f]+\\),\\(.*\\)
X j== \\(.*\\)$" "if (!((word)\\2 & $\\1)) goto \\3;" nil)
X(goto-char (point-min))
X(replace-regexp "testb $\\([0-9]+\\|0x[0-9a-f]+\\),\\(.*\\)
X j== \\(.*\\)$" "if (!((byte)\\2 & $\\1)) goto \\3;" nil)
X
X(goto-char (point-min))
X(message "Fix a bug in the disasm program")
X(replace-regexp "\\(orb .*\\)
XWarning: Unreachable code" "\\1" nil)
X
X(goto-char (point-min))
X(message "Convert or to statement")
X(replace-regexp "\<orl \\(%[a-z]+\\),\\1
X j\\([!=<>]*\\) \\(.*$\\)" "if (\\1 \\2 0) goto \\3;" nil)
X(goto-char (point-min))
X(replace-regexp "\<orw \\(%[a-z]+\\),\\1
X j\\([!=<>]*\\) \\(.*$\\)" "if ((word)\\1 \\2 0) goto \\3;" nil)
X(goto-char (point-min))
X(replace-regexp "\<orb \\(%[a-z]+\\),\\1
X j\\([!=<>]*\\) \\(.*$\\)" "if ((word)\\1 \\2 0) goto \\3;" nil)
X
X
X(goto-char (point-min))
X(message "Convert jmp's to goto")
X(replace-string " jmp " " goto " nil)
X
X(goto-char (point-min))
X(message "Convert dec's and inc's")
X(replace-regexp " decl \\(.*\\)$" " \\1--;" nil)
X(goto-char (point-min))
X(replace-regexp " incl \\(.*\\)$" " \\1++;" nil)
X
X(goto-char (point-min))
X(replace-regexp " decw \\(.*\\)$" " (word)\\1--;" nil)
X(goto-char (point-min))
X(replace-regexp " incw \\(.*\\)$" " (word)\\1++;" nil)
X
X(goto-char (point-min))
X(message "Converting shl's and shr's")
X(replace-regexp " shl[lwb] $\\([0-9]+\\|0x[0-9a-f]+\\),\\(.*\\)$" " \\2 <<= $\\1;" nil)
X(goto-char (point-min))
X(replace-regexp " shl[lwb] \\(%[a-z]+\\)$" " \\1 <<= 1;" nil)
X(goto-char (point-min))
X(replace-regexp " shl[lwb] \\(%[a-z]+\\),\\(%[a-z]+\\)$" " \\1 <<= \\2;" nil)
X(goto-char (point-min))
X(replace-regexp " shr[lwb] $\\([0-9]+\\|0x[0-9a-f]+\\),\\(.*\\)$" " (unsigned)\\2 >>= $\\1;" nil)
X(goto-char (point-min))
X(replace-regexp " sar[lwb] $\\([0-9]+\\|0x[0-9a-f]+\\),\\(.*\\)$" " (int)\\2 >>= $\\1;" nil)
X
X(goto-char (point-min))
X(message "Subroutine entry")
X(replace-regexp "pushl %ebp
X %ebp = %esp;
X subl $\\(.*\\),%esp" "enter \\1" nil)
X
X(goto-char (point-min))
X(message "Converting and's, or's and xor's")
X(replace-regexp "andl \\($[0-9]*\\|$0x[0-9a-f]*\\|%[a-z]+\\),\\(.*\\)$" "\\2 &= \\1;" nil)
X(goto-char (point-min))
X(replace-regexp "andw \\($[0-9]*\\|$0x[0-9a-f]*\\|%[a-z]+\\),\\(.*\\)$" "(word)\\2 &= \\1;" nil)
X(goto-char (point-min))
X(replace-regexp "andb \\($[0-9]*\\|$0x[0-9a-f]*\\|%[a-z]+\\),\\(.*\\)$" "(byte)\\2 &= \\1;" nil)
X(goto-char (point-min))
X(replace-regexp "xorl \\($[0-9]*\\|$0x[0-9a-f]*\\|%[a-z]+\\),\\(.*\\)$" "\\2 ^= \\1;" nil)
X(goto-char (point-min))
X(replace-regexp "xorw \\($[0-9]*\\|$0x[0-9a-f]*\\|%[a-z]+\\),\\(.*\\)$" "(word)\\2 ^= \\1;" nil)
X(goto-char (point-min))
X(replace-regexp "xorb \\($[0-9]*\\|$0x[0-9a-f]*\\|%[a-z]+\\),\\(.*\\)$" "(byte)\\2 ^= \\1;" nil)
X(goto-char (point-min))
X(replace-regexp "orl \\($[0-9]*\\|$0x[0-9a-f]*\\|%[a-z]+\\),\\(.*\\)$" "\\2 |= \\1;" nil)
X(goto-char (point-min))
X(replace-regexp "orw \\($[0-9]*\\|$0x[0-9a-f]*\\|%[a-z]+\\),\\(.*\\)$" "(word)\\2 |= \\1;" nil)
X(goto-char (point-min))
X(replace-regexp "orb \\($[0-9]*\\|$0x[0-9a-f]*\\|%[a-z]+\\),\\(.*\\)$" "(byte)\\2 |= \\1;" nil)
X
X(goto-char (point-min))
X(message "Converting not's and neg's")
X(replace-regexp " %eax = \\(.*\\);
X notl %eax$" " %eax = ~( \\1 );" nil)
X(goto-char (point-min))
X(replace-regexp " notl \\(.*\\)$" " \\1 = ~( \\1 );" nil)
X(goto-char (point-min))
X(replace-regexp " %eax = \\(.*\\);
X negl %eax$" " %eax = -( \\1 );" nil)
X(goto-char (point-min))
X(replace-regexp " negl \\(.*\\)$" " \\1 = -( \\1 );" nil)
X
X
X(goto-char (point-min))
X(message "Make arg names")
X(replace-regexp "\\([^-_0-9a-z]\\)8(%ebp)" "\\1ARG_1" nil)
X(goto-char (point-min))
X(replace-regexp "\\([^-_0-9a-z]\\)12(%ebp)" "\\1ARG_2" nil)
X(goto-char (point-min))
X(replace-regexp "\\([^-_0-9a-z]\\)16(%ebp)" "\\1ARG_3" nil)
X(goto-char (point-min))
X(replace-regexp "\\([^-_0-9a-z]\\)20(%ebp)" "\\1ARG_4" nil)
X(goto-char (point-min))
X(replace-regexp "\\([^-_0-9a-z]\\)24(%ebp)" "\\1ARG_5" nil)
X(goto-char (point-min))
X(replace-regexp "\\([^-_0-9a-z]\\)28(%ebp)" "\\1ARG_6" nil)
X(goto-char (point-min))
X(replace-regexp "\\([^-_0-9a-z]\\)32(%ebp)" "\\1ARG_7" nil)
X(goto-char (point-min))
X(replace-regexp "\\([^-_0-9a-z]\\)36(%ebp)" "\\1ARG_8" nil)
X(goto-char (point-min))
X(replace-regexp "\\([^-_0-9a-z]\\)40(%ebp)" "\\1ARG_9" nil)
X(goto-char (point-min))
X(replace-regexp "-\\([0-9]+\\)(%ebp)" "L_\\1" nil)
X
X(goto-char (point-min))
X(message "Remove leading '_' from names")
X(replace-string "\n_" "\n#\n_" nil)
X(goto-char (point-min))
X(replace-regexp "\\([^_0-9a-z]\\)_\\([0-9a-z_]+\\)" "\\1\\2" nil)
X
X(goto-char (point-min))
X(message "pushl's")
X(replace-regexp "\\(%e..\\) = \\(.*\\);
X pushl \\1" "pushl \\1 = \\2" nil)
X
X(goto-char (point-min))
X(message "Return result from function calls")
X(replace-regexp " \\([_a-z][_a-z0-9]*(.*)\\);
X \\(.*\\) = %eax;$" " \\2 = %eax = \\1" nil)
X
X(goto-char (point-min))
X(message "Convert simple single-parameter procedure calls to c-sequence")
X(replace-regexp "pushl \\(.*\\)
X call \\(.*\\)
X addl $4,%esp" "\\2(\\1);" nil)
X
X(goto-char (point-min))
X(message "Convert simple double-parameter procedure calls to c-sequence")
X(replace-regexp "pushl \\(.*\\)
X pushl \\(.*\\)
X call \\(.*\\)
X addl $8,%esp" "\\3(\\2,\\1);" nil)
X
X(goto-char (point-min))
X(message "Convert simple triple-parameter procedure calls to c-sequence")
X(replace-regexp "pushl \\(.*\\)
X pushl \\(.*\\)
X pushl \\(.*\\)
X call \\(.*\\)
X addl $0xc,%esp" "\\4(\\3,\\2,\\1);" nil)
X
X(goto-char (point-min))
X(message "Convert simple quadruple-parameter procedure calls to c-sequence")
X(replace-regexp "pushl \\(.*\\)
X pushl \\(.*\\)
X pushl \\(.*\\)
X pushl \\(.*\\)
X call \\(.*\\)
X addl $0x10,%esp" "\\5(\\4,\\3,\\2,\\1);" nil)
X
X(goto-char (point-min))
X(message "Convert simple 5-parameter procedure calls to c-sequence")
X(replace-regexp "pushl \\(.*\\)
X pushl \\(.*\\)
X pushl \\(.*\\)
X pushl \\(.*\\)
X pushl \\(.*\\)
X call \\(.*\\)
X addl $0x14,%esp" "\\6(\\5,\\4,\\3,\\2,\\1);" nil)
X
X(goto-char (point-min))
X(message "Convert simple 6-parameter procedure calls to c-sequence")
X(replace-regexp "pushl \\(.*\\)
X pushl \\(.*\\)
X pushl \\(.*\\)
X pushl \\(.*\\)
X pushl \\(.*\\)
X pushl \\(.*\\)
X call \\(.*\\)
X addl $0x18,%esp" "\\7(\\6,\\5,\\4,\\3,\\2,\\1);" nil)
X
X(goto-char (point-min))
X(message "Zero-parameters procedure calls")
X(replace-regexp " call \\(.*\\)
X \\([^ag]\\)" " \\1();
X \\2" nil)
X
X(message "End of file")
X(goto-char (point-min))
X(replace-regexp " \\(%[a-z]+\\) ^= \\1;" " \\1 = 0;" nil)
X
X;; new code
X(replace-regexp " %eax = \\(.*\\);
X return" " return \\1;" nil)
X)
SHAR_EOF
$TOUCH -am 0714185290 macros &&
chmod 0600 macros ||
echo "restore of macros failed"
set `wc -c macros`;Wc_c=$1
if test "$Wc_c" != "12558"; then
echo original size 12558, current size $Wc_c
fi
exit 0
More information about the Alt.sources
mailing list