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