From b1f8822af69c2ee9929a30d1b83d0c1073d1d7a6 Mon Sep 17 00:00:00 2001 From: Richard Burgess <> Date: Sat, 31 Dec 1994 12:23:54 +0000 Subject: [PATCH] autocommit for file dated 1994-12-31 12:23:54 --- mscode16/dumprun/dumprun.c | 1175 ++++++++++++++++++++++++++++++++++++ 1 file changed, 1175 insertions(+) create mode 100644 mscode16/dumprun/dumprun.c diff --git a/mscode16/dumprun/dumprun.c b/mscode16/dumprun/dumprun.c new file mode 100644 index 0000000..c76d73d --- /dev/null +++ b/mscode16/dumprun/dumprun.c @@ -0,0 +1,1175 @@ +/* Dumprun.c Dumps the contents of a MMURTL Run file (DLL or Device Driver*/ + + +#define U32 unsigned long +#define S32 long +#define U16 unsigned int +#define S16 int +#define U8 unsigned char +#define S8 char + +#define TRUE 1 +#define FALSE 1 + +#include +#include +#include +#include +#include "runfile.h" + +/* disassembler data */ + +#include "uproto.h" + +int seg_size = 32; /* set to 32 for /3 option */ +int fRaw = 0; /* dump raw byte too? */ +int nRaw; +U8 RawBuf[10]; + +S32 addrIn; +U32 fEOF = 0; + +/* The Intel 386 Software Writers Guide provides a table that uses the +following codes to assist in manual disassembly of 386 code. The +letters below are the same as the codes in the manual. The % (vertical +bar is an escape character - like in c - to signify expansion of the codes is +required when the string is being outut. +*/ + +char *opmap1[] = { +/* 0 */ + "ADD %Eb,%Gb", "ADD %Ev,%Gv", "ADD %Gb,%Eb", "ADD %Gv,%Ev", + "ADD AL,%Ib", "ADD %eAX,%Iv", "PUSH ES", "POP ES", + "OR %Eb,%Gb", "OR %Ev,%Gv", "OR %Gb,%Eb", "OR %Gv,%Ev", + "OR AL,%Ib", "OR %eAX,%Iv", "PUSH CS", "%2 ", +/* 1 */ + "ADC %Eb,%Gb", "ADC %Ev,%Gv", "ADC %Gb,%Eb", "ADC %Gv,%Ev", + "ADC AL,%Ib", "ADC %eAX,%Iv", "PUSH SS", "POP SS", + "SBB %Eb,%Gb", "SBB %Ev,%Gv", "SBB %Gb,%Eb", "SBB %Gv,%Ev", + "SBB AL,%Ib", "SBB %eAX,%Iv", "PUSH DS", "POP DS", +/* 2 */ + "AND %Eb,%Gb", "AND %Ev,%Gv", "AND %Gb,%Eb", "AND %Gv,%Ev", + "AND AL,%Ib", "AND %eAX,%Iv", "%pE", "DAA", + "SUB %Eb,%Gb", "SUB %Ev,%Gv", "SUB %Gb,%Eb", "SUB %Gv,%Ev", + "SUB AL,%Ib", "SUB %eAX,%Iv", "%pC", "DAS", +/* 3 */ + "XOR %Eb,%Gb", "XOR %Ev,%Gv", "XOR %Gb,%Eb", "XOR %Gv,%Ev", + "XOR AL,%Ib", "XOR %eAX,%Iv", "%pS", "AAA", + "CMP %Eb,%Gb", "CMP %Ev,%Gv", "CMP %Gb,%Eb", "CMP %Gv,%Ev", + "CMP AL,%Ib", "CMP %eAX,%Iv", "%pD", "AAS", +/* 4 */ + "INC %eAX", "INC %eCX", "INC %eDX", "INC %eBX", + "INC %eSP", "INC %eBP", "INC %eSI", "INC %eDI", + "DEC %eAX", "DEC %eCX", "DEC %eDX", "DEC %eBX", + "DEC %eSP", "DEC %eBP", "DEC %eSI", "DEC %eDI", +/* 5 */ + "PUSH %eAX", "PUSH %eCX", "PUSH %eDX", "PUSH %eBX", + "PUSH %eSP", "PUSH %eBP", "PUSH %eSI", "PUSH %eDI", + "POP %eAX", "POP %eCX", "POP %eDX", "POP %eBX", + "POP %eSP", "POP %eBP", "POP %eSI", "POP %eDI", +/* 6 */ + "PUSHA", "POPA", "BOUND %Gv,%Ma", "ARPL %Ew,%Rw", + "%pF", "%pG", "%so", "%sa", + "PUSH %Iv", "IMUL %Gv=%Ev*%Iv", "PUSH %Ib", "IMUL %Gv=%Ev*%Ib", + "INSB %Yb,DX", "INS%ew %Yv,DX", "OUTSB DX,%Xb", "OUTS%ew DX,%Xv", +/* 7 */ + "JO %Jb", "JNO %Jb", "JC %Jb", "JNC %Jb", + "JZ %Jb", "JNZ %Jb", "JBE %Jb", "JNBE %Jb", + "JS %Jb", "JNS %Jb", "JPE %Jb", "JPO %Jb", + "JL %Jb", "JGE %Jb", "JLE %Jb", "JG %Jb", +/* 8 */ + "%g1 %Eb,%Ib", "%g1 %Ev,%Iv", "MOV AL,%Ib", "%g1 %Ev,%Ib", + "TEST %Eb,%Gb", "TEST %Ev,%Gv", "XCHG %Eb,%Gb", "XCHG %Ev,%Gv", + "MOV %Eb,%Gb", "MOV %Ev,%Gv", "MOV %Gb,%Eb", "MOV %Gv,%Ev", + "MOV %Ew,%Sw", "LEA %Gv,%M ", "MOV %Sw,%Ew", "POP %Ev", +/* 9 */ + "NOP", "XCHG %eAX,%eCX", "XCHG %eAX,%eDX", "XCHG %eAX,%eBX", + "XCHG %eAX,%eSP", "XCHG %eAX,%eBP", "XCHG %eAX,%eSI", "XCHG %eAX,%eDI", + "CBW", "CDW", "CALL %Ap", "FWAIT", + "PUSH %eflags", "POP %eflags", "SAHF", "LAHF", +/* a */ + "MOV AL,%Ov", "MOV %eAX,%Ov", "MOV %Ov,al", "MOV %Ov,%eAX", + "MOVSB %Xb,%Yb", "MOVS%ew %Xv,%Yv", "CMPSB %Xb,%Yb", "CMPS%ew %Xv,%Yv", + "TEST AL,%Ib", "TEST %eAX,%Iv", "STOSB %Yb,AL", "STOS%ew %Yv,%eAX", + "LODSB AL,%Xb", "LODS%ew %eAX,%Xv", "SCASB AL,%Xb", "SCAS%ew %eAX,%Xv", +/* b */ + "MOV AL,%Ib", "MOV CL,%Ib", "MOV DL,%Ib", "MOV BL,%Ib", + "MOV AH,%Ib", "MOV CH,%Ib", "MOV DH,%Ib", "MOV BH,%Ib", + "MOV %eAX,%Iv", "MOV %eCX,%Iv", "MOV %eDX,%Iv", "MOV %eBX,%Iv", + "MOV %eSP,%Iv", "MOV %eBP,%Iv", "MOV %eSI,%Iv", "MOV %eDI,%Iv", +/* c */ + "%g2 %Eb,%Ib", "%g2 %Ev,%Ib", "RET %Iw", "RET", + "LES %Gv,%Mp", "LDS %Gv,%Mp", "MOV %Eb,%Ib", "MOV %Ev,%Iv", + "ENTER %Iw,%Ib", "LEAVE", "RETF %Iw", "RETF", + "INT 3", "INT %Ib", "INTO", "IRET", +/* d */ + "%g2 %Eb,1", "%g2 %Ev,1", "%g2 %Eb,cl", "%g2 %Ev,cl", + "AAM", "AAD", 0, "XLAT", + +/* + "ESC 0,%Ib", "ESC 1,%Ib", "ESC 2,%Ib", "ESC 3,%Ib", + "ESC 4,%Ib", "ESC 5,%Ib", "ESC 6,%Ib", "ESC 7,%Ib", +*/ + + "%f0", "%f1", "%f2", "%f3", + "%f4", "%f5", "%f6", "%f7", + + +/* e */ + "LOOPNE %Jb", "LOOPE %Jb", "LOOP %Jb", "JCXZ %Jb", + "IN AL,%Ib", "IN %eAX,%Ib", "OUT %Ib,AL", "OUT %Ib,%eAX", + "CALL %Jv", "JMP %Jv", "JMP %Ap", "JMP %Jb", + "IN AL,DX", "IN %eAX,DX", "OUT DX,AL", "OUT DX,%eAX", +/* f */ + "LOCK%p ", 0, "REPNE%p ", "REP(e)%p ", + "HLT", "CMC", "%g3", "%g0", + "CLC", "STC", "CLI", "STI", + "CLD", "STD", "%g4", "%g5" + }; + +char *SecOp00[] = { +/* 0 */ + "%g6", "%g7", "LAR %Gv,%Ew", "LSL %Gv,%Ew", 0, 0, "CLTS", 0, + 0, 0, 0, 0, 0, 0, 0, 0 }; + +char *SecOp20[] = { +/* 2 */ + "MOV %Rd,%Cd", "MOV %Rd,%Dd", "MOV %Cd,%Rd", "MOV %Dd,%Rd", + "MOV %Rd,%Td", 0, "MOV %Td,%Rd", 0, + 0, 0, 0, 0, 0, 0, 0, 0}; + +char *SecOp80[] = { + "JO %Jv", "JNO %Jv", "JC %Jv", "JNC %Jv", /*RAB Rev JNC /JC */ + "JZ %Jv", "JNZ %Jv", "JBE %Jv", "JNBE %Jv", + "JS %Jv", "JNS %Jv", "JPE %Jv", "JPO %Jv", + "JL %Jv", "JGE %Jv", "JLE %Jv", "JG %Jv", +/* 9 */ + "SETO %Eb", "SETNO %Eb", "SETNC %Eb", "SETC %Eb", + "SETZ %Eb", "SETNZ %Eb", "SETBE %Eb", "SETNBE %Eb", + "SETS %Eb", "SETNS %Eb", "SETP %Eb", "SETNP %Eb", + "SETL %Eb", "SETGE %Eb", "SETLE %Eb", "SETG %Eb", +/* a */ + "PUSH FS", "POP FS", 0, "BT %Ev,%Gv", + "SHLD %Ev,%Gv,%Ib", "SHLD %Ev,%Gv,cl", 0, 0, + "PUSH GS", "POP GS", 0, "BTS %Ev,%Gv", + "SHRD %Ev,%Gv,%Ib", "SHRD %Ev,%Gv,cl", 0, "IMUL %Gv,%Ev", + +/* b */ + 0, 0, "LSS %Mp", "BTR %Ev,%Gv", + "LFS %Mp", "LGS %Mp", "MOVZX %Gv,%Eb", "MOVZX %Gv,%Ew", + 0, 0, "%g8 %Ev,%Ib", "BTC %Ev,%Gv", + "BSF %Gv,%Ev", "BSR%Gv,%Ev", "MOVSX %Gv,%Eb", "MOVSX %Gv,%Ew", + }; + +/* NOTE: Second byte of 2 byte OpCodes are Invalid if Over 0xBF */ + + +char *groups[9][8] = { /* group 0 is group 3 for %Ev set */ + { "TEST %Ev,%Iv", "TEST %Ev,%Iv,", "NOT %Ev", "NEG %Ev", + "MUL %eAX,%Ev", "IMUL %eAX,%Ev", "DIV %eAX,%Ev", "IDIV %eAX,%Ev" }, + { "ADD", "OR", "ADC", "SBB", "AND", "SUB", "XOR", "CMP" }, + { "ROL", "ROR", "RCL", "RCR", "SHL", "SHR", "SHL", "SAR" }, + { "TEST %Eb,%Ib", "TEST %Eb,%Ib,", "NOT %Eb", "NEG %Eb", + "MUL AL,%Eb", "IMUL AL,%Eb", "DIV AL,%Eb", "IDIV AL,%Eb" }, + { "INC %Eb", "DEC %Eb", 0, 0, 0, 0, 0, 0 }, + { "INC %Ev", "DEC %Ev", "CALL %Ev", "CALL %Ep", + "JMP %Ev", "JMP %Ep", "PUSH %Ev", 0 }, + { "SLDT %Ew", "STR %Ew", "LLDT %Ew", "LTR %Ew", + "VERR %Ew", "VERW %Ew", 0, 0 }, + { "SGDT %Ms", "SIDT %Ms", "LGDT %Ms", "LIDT %Ms", + "SMSW %Ew", 0, "LMSW %Ew", 0 }, + { 0, 0, 0, 0, "BT", "BTS", "BTR", "BTC" } + }; + + /* for display */ +char *seg_names[]= {"ES","CS","SS","DS","FS","GS"}; +char *breg_names[]={"AL","CL","DL","BL","AH","CH","DH","BH" }; +char *wreg_names[]={"AX","CX","DX","BX","SP","BP","SI","DI" }; +char *dreg_names[]={"EAX","ECX","EDX","EBX","ESP","EBP","ESI","EDI" }; + +S16 prefix; +U8 modrmv; +S8 fmodrmv; +U8 sibv; +S8 fsibv; +S16 opsize; +S16 addrsize; + + +/* Run file data */ + +char *pCode, *pData, *pStack; /* Ptrs in User mem to load to */ +long sCode, sData, sStack; /* Size of segments */ +unsigned long oCode, oData; /* Offset in file to Code & Data */ +unsigned long offCode, offData; /* Virtual Offset for Code & Data Segs */ +unsigned long nCDFIX, oCDFIX, + nCCFIX, oCCFIX, + nDDFIX, oDDFIX, + nDCFIX, oDCFIX; + +char *pStart; + +struct tagtype tag; + +FILE *run_fh = 0; /* Current .RUN, .DLL, or .DDR (output) */ +FILE *out_fh = 0; /* Output file */ + +char runname[40]; +char outname[40]; + +char fUASM = 0; +char fDumpData = 0; +char fOutFile = 0; + +/********************************************* + Dumps all bytes pointed to to stream with + offset printed in front of each line. +*/ + +void Dump(long cb) +{ +U32 i, val, addr; +U16 j; +unsigned char buff[17]; +unsigned char line[78]; /* Addr xx xx xx xx... ASCII */ + + addr = 0; + + while (cb) { + if (cb > 15) + j=16; + else + j = cb; + + sprintf(line, "%08lX ", addr); /* print current offset */ + + fread (buff, 1, j, run_fh); /* Read j bytes from stream */ + + for (i=0; i 0x7F) + buff[i] = 0x2E; + line[i+61] = buff[i]; /* printed char */ + } + line[59] = 0x20; + line[60] = 0x20; + line[i+61] = 0; + + fprintf(out_fh, "%s\r\n", line); /* put in chars */ + + addr += j; + cb -=j; + } + return; +} + + + +/***************************************************** +Gets a byte to disassemble saving the raw bytes that +make it up in RawBuf[nRaw]. +******************************************************/ + +U8 getbyte(void) +{ +S32 i; +U8 b; + +i=fgetc(run_fh); +if (i==EOF) fEOF = 1; +b = i & 0xff; +if (fRaw) + RawBuf[nRaw++] = b; +addrIn++; +return b; +} + + +/*************************************************/ +/* Get Mod/RM field byte for current instruction */ + +U8 modrm(void) +{ + if (!fmodrmv) { + modrmv = getbyte(); + fmodrmv = 1; + } + return modrmv; +} + + +/*************************************************/ +/* Get 'scale-index-base' byte for current instruction */ + +U8 sib(void) +{ + if (!fsibv) { + sibv = getbyte(); + fsibv = 1; + } + return sibv; +} + +/**********************************************************/ +/* Macros to shift or mask a byte so bit type data such as + reg or mod can be pulled out of certain instruction + bytes. +*/ + +#define mod(a) (((a)>>6)&7) +#define reg(a) (((a)>>3)&7) +#define rm(a) ((a)&7) +#define ss(a) (((a)>>6)&7) +#define indx(a) (((a)>>3)&7) +#define base(a) ((a)&7) + +/*------------------------------------------------------------------------*/ + +/************************************** +* Write a decimal number to a file fout +***************************************/ + +void put_num(U32 value, FILE *fout) +{ +S8 stack[10]; +register U16 i; + + if(value & 0x80000000) { + fputc('-', fout); + value = -value; } + i = 0; + do + stack[i++] = (value % 10) + '0'; + while(value /= 10); + while(i) { + fputc(stack[--i], fout); + } +} + +/************************************** + Write a Hex byte to a file fout. +***************************************/ + +void put_hexb(U8 value, FILE *fout) +{ +S8 stack[10]; +U16 i, j; + + i = 0; j = 2; + do { + stack[i] = (value % 16) + '0'; + if (stack[i] > 0x39) + stack[i] += 7; + i++; + } + while(value /= 16); + while (i < j--) { /* zero pad front end to width */ + fputc('0', fout); + } + while(i) { + fputc(stack[--i], fout); + } +} + +/************************************** + Write a Hex number to a file fout. +***************************************/ + +void put_hexw(U16 value, FILE *fout) +{ +S8 stack[10]; +U16 i, j; + + i = 0; + j = 4; + do { + stack[i] = (value % 16) + '0'; + if (stack[i] > 0x39) + stack[i] += 7; + i++; + } + while(value /= 16); + while (i < j--) { /* zero pad front end to width */ + fputc('0', fout); + } + while(i) { + fputc(stack[--i], fout); + } +} + +/************************************** + Write a hex dword to a file fout. +***************************************/ + +void put_hexd(U32 value, FILE *fout) +{ +S8 stack[10]; +U16 i, j; + + i = 0; + j = 8; + do { + stack[i] = (value % 16) + '0'; + if (stack[i] > 0x39) + stack[i] += 7; + i++; + } + while(value /= 16); + while (i < j--) { /* zero pad front end to width */ + fputc('0', fout); + } + while(i) { + fputc(stack[--i], fout); + } +} + +/*------------------------------------------------------------------------*/ +/* determines how many bytes left in the instruction from the + letter in the table (which is passed in here). "v" is a variable + number based on current segment size of code descriptor. +*/ + +int bytes(char c) +{ + switch (c) + { + case 'b': + return 1; + case 'w': + return 2; + case 'd': + return 4; + case 'v': + if (opsize == 32) + return 4; + else + return 2; + } + return 0; +} + +/************************************************************** +Get the correct number of bytes for immediate data from the +code stream and output it as hex. +***************************************************************/ + +void ohex(char c, int extend, int optional, int defsize) +{ +int n, s, i, j; +S32 delta; +unsigned char buf[6]; +char *name; + + n=0; + s=0; + + switch (c) + { + case 'a': + break; + case 'b': /* byte */ + n = 1; + break; + case 'w': /* word */ + n = 2; + break; + case 'd': /* dword */ + n = 4; + break; + case 's': /* fword */ + n = 6; + break; + case 'c': + case 'v': + if (defsize == 32) + n = 4; + else + n = 2; + break; + case 'p': /* 32 or 48 bit pointer */ + if (defsize == 32) + n = 6; + else + n = 4; + s = 1; + break; + } + + for (i=0; i n) + { + if (!optional) + fprintf(out_fh,"+"); + n = 4; + } + switch (n) + { + case 1: { + fprintf(out_fh,"%02X",buf[0]); +/* put_hexb(buf[0], out_fh); */ + break; + } + case 2: { + fprintf(out_fh,"%02X%02X",buf[1],buf[0]); +/* put_hexb(buf[1], out_fh); + put_hexb(buf[0], out_fh); +*/ + break; + } + case 4: { + fprintf(out_fh,"%02X%02X%02X%02X",buf[3],buf[2],buf[1],buf[0]); +/* + put_hexb(buf[3], out_fh); + put_hexb(buf[2], out_fh); + put_hexb(buf[1], out_fh); + put_hexb(buf[0], out_fh); +*/ + break; + } + } +} + +/*------------------------------------------------------------------------*/ + +void reg_name(U8 which, char size) +{ + if (size == 'F') + { + fprintf(out_fh, "st(%d)",which); + + return; + } + if (((size == 'v') && (opsize == 32)) || (size == 'd')) + { + fprintf(out_fh,"E"); + } + if (size == 'b') + { + fprintf(out_fh, "%s", breg_names[which]); + } + else + { + fprintf(out_fh, "%s", wreg_names[which]); + } +} + +/****************************************************************** + This takes in a two chars that represent part of the op code and + puts out the proper text to match what the letter represents. + c is the first char after the dollar sign and t is next one. See + opcode1[] strings for what the chars mean. +*******************************************************************/ + +void escape(char c, char t) +{ + U32 v; + S32 delta, vofs, tmp; + S8 vofsb; + S16 vofsw; + char *name; + int extend; + U8 b2, w; + + extend = (addrsize == 32) ? 4 : 2; + + switch (c) + { + case 'A': /* Direct Address */ + ohex(t, extend, 0, addrsize); + break; + case 'C': /* Reg of R/M picks control reg */ + fprintf(out_fh, "CR%d",reg(modrm())); + break; + case 'D': /* Reg of R/M pick debug reg */ + fprintf(out_fh, "DR%d",modrm()); + break; + case 'E': /* R/M picks operand */ + do_modrm(t); + break; + case 'G': /* Reg of R/M picks general reg */ + if (t == 'F') + reg_name(rm(modrm()), t); + else + reg_name(reg(modrm()), t); + break; + case 'I': /* Immediate data */ + ohex(t, 0, 0, opsize); + break; + case 'J': /* Relative IP offset */ + switch (bytes(t)) + { + case 1: + vofsb = getbyte(); /* must remian signed! */ + vofs = vofsb; + break; + case 2: + vofsb = getbyte(); /*Must be Signed bytes/Words */ + vofsw = getbyte()<<8; + vofs = vofsw + vofsb; + break; + case 4: + vofs = getbyte(); + tmp = getbyte(); + vofs |= tmp << 8; + tmp = getbyte(); + vofs |= tmp << 16; + tmp = getbyte(); + vofs |= tmp << 24; + break; + } + delta = addrIn + vofs; + fprintf(out_fh, "%08lX", delta); + break; + case 'M': /* R/M picks memory */ + do_modrm(t); + break; + case 'O': /* NO R/M, Offset only */ + expand_out("%p:["); + ohex(t, extend, 0, addrsize); + fprintf(out_fh,"]"); + break; + case 'R': /* Mod of R/M pick REG only */ + do_modrm(t); + break; + case 'S': /* Reg of R/M picks seg reg */ + fprintf(out_fh, "%s", seg_names[reg(modrm())]); + break; + case 'T': /* Reg of R/M picks test reg */ + fprintf(out_fh, "TR%d",modrm()); + break; + case 'X': /* DS:ESI */ + fprintf(out_fh,"DS:["); + if (addrsize == 32) + fprintf(out_fh,"E"); + fprintf(out_fh,"SI]"); + break; + case 'Y': /* ES:EDI */ + fprintf(out_fh,"ES:["); + if (addrsize == 32) + fprintf(out_fh,"E"); + fprintf(out_fh,"DI]"); + break; + case '2': /* Prefix of 2 byte opcode */ + b2 = getbyte(); + if (b2 < 0x10) + expand_out(SecOp00[b2]); + else if ((b2 > 0x1F) && (b2 < 0x30)) + expand_out(SecOp20[b2-0x20]); + else if ((b2 > 0x7F) && (b2 < 0xC0)) + expand_out(SecOp80[b2-0x80]); + else + fprintf(out_fh, ""); + break; + case 'e': /* If "USE32" t is part of reg name */ + if (opsize == 32) + { + if (t == 'w') /* put out "d" if t is "w" on USE32 segs*/ + fprintf(out_fh,"D"); + else + { + fprintf(out_fh,"E"); /* put out "E" if not t <> "w" then put t */ + fputc(t, out_fh); + } + } + else { + fputc(t, out_fh); /* when USE16 just put out esc char */ + } + break; + case 'f': /* floating point */ + fprintf(out_fh,""); + +/* floating_point(t-'0'); */ + + break; + case 'g': /* do R/M group 'n' */ + expand_out(groups[t-'0'][reg(modrm())]); + break; + case 'p': /* Segment prefix */ + switch (t) + { + case 'C': /* CS */ + case 'D': /* DS */ + case 'E': /* ES */ + case 'F': /* FS */ + case 'G': /* GS */ + case 'S': /* SS */ + prefix = t; + expand_out(opmap1[getbyte()]); + break; + case ':': + if (prefix) { + fputc(prefix, out_fh); + fprintf(out_fh,"S:"); + } + break; + case ' ': + expand_out(opmap1[getbyte()]); + break; + } + break; + case 's': /* Size override */ + switch (t) + { + case 'a': + addrsize = 48 - addrsize; /* a is address */ + expand_out(opmap1[getbyte()]); + break; + case 'o': /* o is operand */ + opsize = 48 - opsize; + expand_out(opmap1[getbyte()]); + break; + } + break; + } +} + + +/****************************************** +This expands and outputs the instruction +string passed in if it find the escape +character (vertical bar). +******************************************/ + +void expand_out(char *s) +{ + int i; + char c; + + if (s == 0) /* if NULL pointer, then it's BAD */ + { + fprintf(out_fh,""); + } + while ((c = *s++) != 0) /* put next char in c */ + { + if (c == '%') /* if c is % then ESCAPE */ + { + c = *s++; /* get letter representing value */ + escape(c, *s++); + } + else + if (c == ' ') /* if space, put TAB in string */ + fprintf(out_fh," "); + else { + fputc(c, out_fh); /* else put out the char found! */ + } + } +} + + +/* outputs 'scale-index-base' instructions */ + +void do_sib(int m) +{ + int s, i, b; + s = ss(sib()); + i = indx(sib()); + b = base(sib()); + switch (b) + { + case 0: expand_out("%p:[EAX"); break; + case 1: expand_out("%p:[ECX"); break; + case 2: expand_out("%p:[EDX"); break; + case 3: expand_out("%p:[EBX"); break; + case 4: expand_out("%p:[ESP"); break; + case 5: + if (m == 0) + { + expand_out("%p:["); + ohex('d', 4, 0, addrsize); + } + else + expand_out("%p:[EBP"); + break; + case 6: expand_out("%p:[ESI"); break; + case 7: expand_out("%p:[EDI"); break; + } + switch (i) + { + case 0: fprintf(out_fh,"+EAX"); break; + case 1: fprintf(out_fh,"+ECX"); break; + case 2: fprintf(out_fh,"+EDX"); break; + case 3: fprintf(out_fh,"+EBX"); break; + case 4: break; + case 5: fprintf(out_fh,"+EBP"); break; + case 6: fprintf(out_fh,"+ESI"); break; + case 7: fprintf(out_fh,"+EDI"); break; + } + if (i != 4) + switch (s) + { + case 0: break; + case 1: fprintf(out_fh,"*2"); break; + case 2: fprintf(out_fh,"*4"); break; + case 3: fprintf(out_fh,"*8"); break; + + } +} +/*------------------------------------------------------------------------*/ +void do_modrm(char t) +{ + int m; + int r; + int extend; + + m = mod(modrm()); + r = rm(modrm()); + extend = (addrsize == 32) ? 4 : 2; + + if (m == 3) + { + reg_name(r, t); + return; + } + if ((m == 0) && (r == 5) && (addrsize == 32)) + { + expand_out("%p:["); + ohex('d', extend, 0, addrsize); + fprintf(out_fh,"]"); + return; + } + if ((m == 0) && (r == 6) && (addrsize == 16)) + { + expand_out("%p:["); + ohex('w', extend, 0, addrsize); + fprintf(out_fh,"]"); + return; + } + if ((addrsize != 32) || (r != 4)) + expand_out("%p:["); + if (addrsize == 16) + { + switch (r) + { + case 0: fprintf(out_fh,"BX+SI"); break; + case 1: fprintf(out_fh,"BX+DI"); break; + case 2: fprintf(out_fh,"BP+SI"); break; + case 3: fprintf(out_fh,"BP+DI"); break; + case 4: fprintf(out_fh,"SI"); break; + case 5: fprintf(out_fh,"DI"); break; + case 6: fprintf(out_fh,"BP"); break; + case 7: fprintf(out_fh,"BX"); break; + } + } + else + { + switch (r) + { + case 0: fprintf(out_fh,"EAX"); break; + case 1: fprintf(out_fh,"ECX"); break; + case 2: fprintf(out_fh,"EDX"); break; + case 3: fprintf(out_fh,"EBX"); break; + case 4: do_sib(m); break; + case 5: fprintf(out_fh,"EBP"); break; + case 6: fprintf(out_fh,"ESI"); break; + case 7: fprintf(out_fh,"EDI"); break; + } + } + switch (m) + { + case 1: + ohex('b', extend, 0, addrsize); /* was 1 */ + break; + case 2: + fprintf(out_fh,"+"); + ohex('v', extend, 0, addrsize); /* was 1 */ + break; + } + fprintf(out_fh,"]"); +} + +/*********************************************** + This disassembles one instruction each time it + is called. +************************************************/ + +U32 disassemble(void) +{ + int i; + char *cmp, *brp; + U8 *wp; + U32 delta; + char *name, *lname; + + prefix = 0; + fmodrmv = 0; + fsibv = 0; + nRaw = 0; + opsize = addrsize = seg_size; + + fprintf(out_fh, "%08lX ", addrIn); + + expand_out(opmap1[getbyte()]); /* decode instruction and output */ + + if (fRaw) { + i = 0; + fprintf(out_fh, " "); + while (nRaw--) { + put_hexb(RawBuf[i++], out_fh); + fprintf(out_fh, " "); + } + } + + fprintf(out_fh, "\r\n"); + return addrIn; +} + + +/************************************************ +* Write part of an instruction to the file "fi" +*************************************************/ + +void put_str(char *ptr, FILE *fi) +{ + while(*ptr) + fputc(*ptr++, fi); +} + +/******************************************* +* Report a non-recoverable error +********************************************/ + +void fatal_error(char *string) +{ + put_str(string, stderr); + put_str("Disassembly aborted\r\n", stderr); + + exit(-1); +} + +/********************************************************* + This reads and dumps a RUN file with complete tag field + descriptions and data. +*********************************************************/ + +void DumpRunFile(FILE *fh) +{ +int ii; +long i, dret, nPages, nobj; +char fDone, filetype, junk; + + addrIn = 0; /* Default Address */ + offCode = 0; /* Default virtual code */ + fDone = 0; + while (!fDone) { + tag.id = 0; + fprintf(out_fh, "\r\nFile LFA: %ld\r\n", ftell(fh)); + nobj = fread (&tag, 1, 5, fh); + if (nobj) { + ii = tag.id; + fprintf(out_fh, "Tage Value (hex): %02X\r\n", ii); + fprintf(out_fh, "Tage Length (dec): %ld\r\n", tag.len); + } + else + fDone = TRUE; + switch (tag.id) { + case IDTAG: + nobj = fread (&filetype, 1, 1, fh); + if (filetype == 1) + fprintf(out_fh, "File type: STANDARD RUN FILE\r\n"); + else if (filetype == 2) + fprintf(out_fh, "File type: DYNAMIC LINK LIBRAY\r\n"); + else if (filetype == 3) + fprintf(out_fh, "File type: DEVICE DRIVER\r\n"); + else { + fprintf(out_fh, "File type: UNKNOWN (ID=%d)\r\n",filetype); + fDone = 1; + } + break; + case SEGTAG: + fprintf(out_fh, "Segment Sizes:\r\n"); + nobj = fread (&sStack, 1, 4, fh); + if (nobj) nobj = fread (&sCode, 1, 4, fh); + if (nobj) nobj = fread (&sData, 1, 4, fh); + fprintf(out_fh, " Stack %ld\r\n", sStack); + fprintf(out_fh, " Code %ld\r\n", sCode); + fprintf(out_fh, " Data %ld\r\n", sData); + break; + case DOFFTAG: + nobj = fread (&offData, 1, 4, fh); + fprintf(out_fh, "Virtual Data Offset: %08lXh\r\n", offData); + break; + case COFFTAG: + nobj = fread (&offCode, 1, 4, fh); + fprintf(out_fh, "Virtual Code Offset: %08lXh\r\n", offCode); + addrIn = offCode; /* Virtual Address */ + break; + case STRTTAG: + nobj = fread (&pStart, 1, 4, fh); + fprintf(out_fh, "Start Address: %08lXh\r\n", pStart); + break; + case CODETAG: + fprintf(out_fh, "Code Segment Contents...\r\n"); + if (fUASM) { + while ((disassemble() - offCode) < tag.len); + } + else + while (tag.len--) + nobj = fread (&junk, 1, 1, fh); + break; + case DATATAG: + fprintf(out_fh, "Data Segment Contents...\r\n"); + if (fDumpData) { + Dump(tag.len); + } + else { + while (tag.len--) + nobj = fread (&junk, 1, 1, fh); + } + break; + case CDFIXTAG: + fprintf(out_fh, "CD Fixups - Refs to Data at CSeg offsets:\r\n"); + while ((tag.len) && (nobj)) { + nobj = fread (&i, 1, 4, fh); + tag.len-=4; + fprintf(out_fh, " Offset- %08lXh\r\n", i); + } + break; + case CCFIXTAG: + fprintf(out_fh, "CC Fixups - Refs to Code at CSeg offsets:\r\n"); + while ((tag.len) && (nobj)) { + nobj = fread (&i, 1, 4, fh); + tag.len-=4; + fprintf(out_fh, " Offset- %08lXh\r\n", i); + } + break; + case DDFIXTAG: + fprintf(out_fh, "DD Fixups - Refs to Data at DSeg offsets:\r\n"); + while ((tag.len) && (nobj)) { + nobj = fread (&i, 1, 4, fh); + tag.len-=4; + fprintf(out_fh, " Offset- %08lXh\r\n", i); + } + break; + case DCFIXTAG: + fprintf(out_fh, "DD Fixups - Refs to Code at DSeg offsets:\r\n"); + while ((tag.len) && (nobj)) { + nobj = fread (&i, 1, 4, fh); + tag.len-=4; + fprintf(out_fh, " Offset- %08lXh\r\n", i); + } + break; + case ENDTAG: + nobj = fread (&i, 1, 4, fh); + fprintf(out_fh, "END Tag Value: %ld\r\n", i); + fDone = TRUE; + break; + default: + while ((tag.len--) && (nobj)) + nobj = fread (&junk, 1, 1, fh); + break; + } + } +} + +/*************************** +* Main program DUMPRUNFILE +****************************/ + +void main(S16 argc, S8 *argv[]) +{ +S8 *ptr, *pname; +S16 i, j, fdone; + + out_fh = 0; /* default the list file */ + + for(i=1; i < argc; ++i) { + ptr = argv[i]; + if (*ptr == '/') { + ptr++; + switch(*ptr) { + case 'U' : /* UnAssemble Code */ + case 'u' : + fUASM = 1; + break; + case 'D' : /* Dump Symbols */ + case 'd' : + fDumpData = 1; + break; + case 'O' : /* Output Hex code with Unassembly */ + case 'o' : + fRaw = 1; + break; + default: + printf("Invalid option/swtich \n"); + if (run_fh) + fclose(run_fh); + exit(1); + break; + } + } + else { + if(!run_fh) { + strncpy(runname, argv[i], 39); + run_fh = fopen(argv[i], "rb"); + } + else if (!out_fh) { + strncpy(outname, argv[i], 39); + if(!(out_fh = fopen(argv[i], "w"))) { + printf("Can't open OUTPUT file\n"); + exit(1); + } + fOutFile = 1; + } + else { + printf("Too many options\n"); /* Too many parameters */ + exit(1); + } + } + } + +/* Input file not explicitly named errors out */ + + if (!run_fh) { + printf("Usage: DumpRun runfile outputfile /U /D \r\n"); + printf("/U = Unassemble Code segment\r\n"); + printf("/O = Output code in hex with Unassembly (must use /U)\r\n"); + printf("/D = Dump data segment contents in hex format\r\n"); + printf("If outputfile isn't specifiled output is sent to screenr\r\n"); + printf("Can't open RUNFILE.\n"); /* Can't open file */ + exit(1); + } + +/* Output file not explicitly named is set to stdout */ + + if (!out_fh) + out_fh = stdout; + + +if (fOutFile) { + printf("DumpRunFile Ver x1.0 (c) R.A. Burgess 1993, 1994\r\n"); + printf("Dump being sent to file: %s \r\n\r\n", outname); +} + +fprintf(out_fh, "DumpRunFile Ver x1.0 (c) R.A. Burgess 1993, 1994\r\n\r\n"); + +DumpRunFile(run_fh); +if (run_fh) + fclose(run_fh); +if (fOutFile) + fclose(out_fh); +exit(0); + +} + +/*********************** End of Module *****************/ -- 2.40.0