]> pd.if.org Git - mmurtl/commitdiff
autocommit for file dated 1994-12-31 12:23:54
authorRichard Burgess <>
Sat, 31 Dec 1994 12:23:54 +0000 (12:23 +0000)
committerNathan Wagner <nw@hydaspes.if.org>
Mon, 17 Oct 2016 14:03:47 +0000 (14:03 +0000)
mscode16/dumprun/dumprun.c [new file with mode: 0644]

diff --git a/mscode16/dumprun/dumprun.c b/mscode16/dumprun/dumprun.c
new file mode 100644 (file)
index 0000000..c76d73d
--- /dev/null
@@ -0,0 +1,1175 @@
+/* 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