]> pd.if.org Git - mmurtl/commitdiff
autocommit for file dated 1994-08-28 11:25:28
authorRichard Burgess <>
Sun, 28 Aug 1994 11:25:28 +0000 (11:25 +0000)
committerNathan Wagner <nw@hydaspes.if.org>
Mon, 17 Oct 2016 14:03:47 +0000 (14:03 +0000)
ossource/uasm.c [new file with mode: 0644]

diff --git a/ossource/uasm.c b/ossource/uasm.c
new file mode 100644 (file)
index 0000000..c1b9d07
--- /dev/null
@@ -0,0 +1,712 @@
+/* This is the MMURTL Debugger disassembler.\r
+\r
+  MMURTL Operating System Source Code\r
+  Copyright 1991,1992,1993,1994 Richard A. Burgess\r
+  ALL RIGHTS RESERVED\r
+  Version 1.0\r
+*/\r
+\r
+#define U32 unsigned long\r
+#define U16 unsigned short\r
+#define U8 unsigned char\r
+#define S32 signed long\r
+#define S16 signed short\r
+#define S8 signed char\r
+\r
+static U8 getbyte(void);\r
+static U8 modrm(void);\r
+static U8 sib(void);\r
+static int bytes(char c);\r
+static void ohex(char c, int extend, int optional, int defsize);\r
+static void reg_name(U8 which, char size);\r
+static void escape(char c, char t);\r
+static void decode(char *s);\r
+static void do_sib(int m);\r
+static void do_modrm(char t);\r
+U32 disassemble(U32 Addr);\r
+\r
+extern long xprintf(char *fmt, ...);           /* From Monitor.c */\r
+\r
+#define SEGSIZE  32\r
+static U8 *addrIn;\r
+\r
+/*  The Intel 386 DX Programmer's Reference Manual provides a table that\r
+uses the following codes to assist in disassembly of 386 code (page A-3).\r
+The letters below are the same as the codes in the manual.  The ~ (tilde)\r
+is an escape character to signify expansion of the codes is\r
+required when the string is being outut to the screen.\r
+\r
+Tilde tokens in strings:\r
+   First char after '~':\r
+ A - Direct address\r
+ C - Reg of R/M picks control register\r
+ D - Reg of R/M picks debug register\r
+ E - R/M picks operand\r
+ F - Flag register\r
+ G - Reg of R/M selects a general register\r
+ I - Immediate data\r
+ J - Relative IP offset\r
+ M - R/M picks memory\r
+ O - No R/M, offset only\r
+ R - Mod of R/M picks register only\r
+ S - Reg of R/M picks segment register\r
+ T - reg of R/M picks test register\r
+ X - DS:ESI\r
+ Y - ES:EDI\r
+ 2 - prefix of two-byte opcode\r
+ e - put in 'e' if use32 (second char is part of reg name)\r
+     put in 'w' for use16 or 'd' for use32 (second char is 'w')\r
+ f - Floating point (second char is esc value)\r
+ g - do R/M group 'n'\r
+ p - prefix\r
+ s - Size override (second char is a,o)\r
+\r
+   Second char after '~':\r
+ a - Two words in memory (BOUND)\r
+ b - Byte\r
+ c - Byte or word\r
+ d - DWord\r
+ p - 32 or 48 bit pointer\r
+ s - Six byte pseudo-descriptor\r
+ v - Word or DWord\r
+ w - Word\r
+ 1-8 - group number, esc value, etc\r
+*/\r
+\r
+static 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",       "JNC ~Jb",      "JC ~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
+static 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
+static char *SecOp80[] = {\r
+  "JO ~Jv", "JNO ~Jv", "JC ~Jv", "JNC ~Jv",\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
+/* 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
+/* NOTE: Second byte of 2 byte OpCodes are Invalid if over 0xBF */\r
+\r
+\r
+static 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
+static char *seg_names[]= {"ES","CS","SS","DS","FS","GS"};\r
+static char *breg_names[]={"AL","CL","DL","BL","AH","CH","DH","BH" };\r
+static char *wreg_names[]={"AX","CX","DX","BX","SP","BP","SI","DI" };\r
+static char *dreg_names[]={"EAX","ECX","EDX","EBX","ESP","EBP","ESI","EDI" };\r
+\r
+static S16 prefix;\r
+static U8 modrmv;\r
+static S8 fmodrmv;\r
+static U8 sibv;\r
+static S8 fsibv;\r
+static S16 opsize;\r
+\r
+/*****************************************************\r
+Gets a byte to disassemble and update addrIn.\r
+******************************************************/\r
+\r
+static U8 getbyte(void)\r
+{\r
+U8 b;\r
+;\r
+#asm\r
+       MOV EAX, _addrIn\r
+       MOV AL, CS:[EAX]\r
+       MOV [EBP-1], AL\r
+#endasm\r
+\r
+ ++addrIn;\r
+ return b;\r
+}\r
+\r
+\r
+/*************************************************/\r
+/* Get Mod/RM field byte for current instruction */\r
+\r
+static 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
+static U8 sib(void)\r
+{\r
+  if (!fsibv) {\r
+    sibv = getbyte();\r
+    fsibv = 1;\r
+    }\r
+  return sibv;\r
+}\r
+\r
+/**********************************************************/\r
+/* The register is encode as bit 3,4,5 in the byte.\r
+   xxRRRxxx\r
+   This macro extracts it.  Used in several places.\r
+*/\r
+\r
+#define reg(a) (((a)>>3)&7)\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).\r
+*/\r
+\r
+static 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
+static void ohex(char c, int extend, int optional, int defsize)\r
+{\r
+int n, s, i;\r
+unsigned char buf[6];\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
+       xprintf("%02x%02x",buf[n-1],buf[n-2]);\r
+    n -= 2;\r
+  }\r
+\r
+  if (extend > n)\r
+  {\r
+    if (!optional)\r
+       xprintf("+");\r
+       n = 4;\r
+  }\r
+  switch (n)\r
+  {\r
+    case 1: {\r
+                       xprintf("%02x",buf[0]);\r
+               break;\r
+               }\r
+    case 2:    {\r
+                       xprintf("%02x%02x",buf[1],buf[0]);\r
+               break;\r
+               }\r
+    case 4:    {\r
+                       xprintf("%02x%02x%02x%02x",buf[3],buf[2],buf[1],buf[0]);\r
+               break;\r
+               }\r
+  }\r
+}\r
+\r
+/*------------------------------------------------------------------------*/\r
+\r
+static void reg_name(U8 which, char size)\r
+{\r
+  if (size == 'F')\r
+  {\r
+    xprintf( "st(%d)",which);\r
+\r
+    return;\r
+  }\r
+  if (((size == 'v') && (opsize == 32)) || (size == 'd'))\r
+  {\r
+    xprintf("E");\r
+  }\r
+  if (size == 'b')\r
+  {\r
+    xprintf( "%s", breg_names[which]);\r
+  }\r
+  else\r
+  {\r
+    xprintf( "%s", wreg_names[which]);\r
+  }\r
+}\r
+\r
+/******************************************************************\r
+   This takes in 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 tilde and t is next one. See\r
+   opcode1[] strings for what the chars mean.\r
+*******************************************************************/\r
+\r
+static void escape(char c, char t)\r
+{\r
+  S32  delta, vals;\r
+  U8 b2;\r
+  S8 valsb;\r
+  S16 valsw;\r
+\r
+  switch (c)\r
+  {\r
+    case 'A':                             /* Direct Address */\r
+           ohex(t, 4, 0, 32);\r
+           break;\r
+    case 'C':                             /* Reg of R/M picks control reg */\r
+               xprintf("CR%d",reg(modrm()));\r
+           break;\r
+    case 'D':                             /* Reg of R/M pick debug reg */\r
+               xprintf("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((modrm()&7), 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
+          valsb = getbyte();           /* must remian signed! */\r
+          vals = valsb;\r
+          break;\r
+        case 2:\r
+          valsb = getbyte();        /*RAB  Made SIGNEd bytes/Words */\r
+          valsw = getbyte()<<8;\r
+          vals = valsw + valsb;\r
+          break;\r
+        case 4:\r
+          vals = getbyte();\r
+          vals |= getbyte() << 8;\r
+          vals |= getbyte() << 16;\r
+          vals |= getbyte() << 24;\r
+          break;\r
+               }\r
+               delta = addrIn + vals;\r
+           xprintf( "%x",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
+               decode("~p:[");\r
+               ohex(t, 4, 0, 32);\r
+               xprintf("]");\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
+           xprintf( "%s", seg_names[reg(modrm())]);\r
+               break;\r
+    case 'T':                             /* Reg of R/M picks test reg */\r
+               xprintf( "TR%d",modrm());\r
+               break;\r
+    case 'X':                             /* DS:ESI */\r
+               xprintf("DS:[ESI]");\r
+               break;\r
+       case 'Y':                             /* ES:EDI */\r
+               xprintf("ES:[EDI]");\r
+               break;\r
+    case '2':                             /* Prefix of 2 byte opcode */\r
+               b2 = getbyte();\r
+               if (b2 < 0x10)\r
+                       decode(SecOp00[b2]);\r
+               else if ((b2 > 0x1F) && (b2 < 0x30))\r
+                       decode(SecOp20[b2-0x20]);\r
+               else if ((b2 > 0x7F) && (b2 < 0xC0))\r
+                       decode(SecOp80[b2-0x80]);\r
+               else\r
+                   xprintf("<bogus>");\r
+               break;\r
+       case 'e':                 /*  t is part of reg name */\r
+               if (opsize == 32)\r
+               {\r
+                       if (t == 'w')     /* put out "d" if t is "w" on 32 bit opsize */\r
+                               xprintf("D");\r
+                       else\r
+                       {\r
+                         xprintf("E");  /* put out "E" if not t <> "w" then put t */\r
+                         xprintf("%c",t);\r
+                       }\r
+               }\r
+               else {\r
+                         xprintf("%c",t);\r
+               }\r
+               break;\r
+    case 'f':                /* floating point */\r
+           xprintf("<Float Op>");\r
+\r
+/*             floating_point(t-'0');  */\r
+\r
+               break;\r
+    case 'g':                             /* do R/M group 'n' */\r
+               decode(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
+          decode(opmap1[getbyte()]);\r
+          break;\r
+               case ':':\r
+          if (prefix) {\r
+               xprintf("%cS:",prefix);\r
+          }\r
+          break;\r
+       case ' ':\r
+          decode(opmap1[getbyte()]);\r
+          break;\r
+               }\r
+               break;\r
+    case 's':                                                          /* Size override */\r
+               if (t=='o') {                                           /* o is operand */\r
+                 opsize = 48 - opsize;\r
+                 decode(opmap1[getbyte()]);\r
+           }\r
+           break;\r
+  }\r
+}\r
+\r
+\r
+/******************************************\r
+This expands and outputs the instruction\r
+string passed in if it finds the escape\r
+character (tilde).\r
+******************************************/\r
+\r
+static void decode(char *s)\r
+{\r
+  char c;\r
+\r
+  if (s == 0)                   /* if NULL pointer, then it's BAD */\r
+  {\r
+    xprintf("<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 == ' ')             /* space */\r
+               xprintf(" ");\r
+         else {\r
+               xprintf("%c",c);         /* else put out the char found! */\r
+               }\r
+  }\r
+}\r
+\r
+\r
+/* outputs 'scale-index-base' instructions */\r
+\r
+static void do_sib(int m)\r
+{\r
+  int s, i, b;\r
+  s = ((sib()) >> 6) & 7;              /* SSxxxxxx Scale */\r
+  i = ((sib()) >> 3) & 7;              /* xxIIIxxx Index */\r
+  b = sib() & 7;                               /* xxxxxBBB Base  */\r
+  switch (b)\r
+  {\r
+    case 0: decode("~p:[EAX"); break;\r
+    case 1: decode("~p:[ECX"); break;\r
+    case 2: decode("~p:[EDX"); break;\r
+    case 3: decode("~p:[EBX"); break;\r
+    case 4: decode("~p:[ESP"); break;\r
+    case 5:\r
+      if (m == 0)\r
+      {\r
+        decode("~p:[");\r
+        ohex('d', 4, 0, 32);\r
+      }\r
+      else\r
+        decode("~p:[EBP");\r
+      break;\r
+    case 6: decode("~p:[ESI"); break;\r
+    case 7: decode("~p:[EDI"); break;\r
+  }\r
+  switch (i)\r
+  {\r
+    case 0: xprintf("+EAX"); break;\r
+    case 1: xprintf("+ECX"); break;\r
+    case 2: xprintf("+EDX"); break;\r
+    case 3: xprintf("+EBX"); break;\r
+    case 4: break;\r
+    case 5: xprintf("+EBP"); break;\r
+    case 6: xprintf("+ESI"); break;\r
+    case 7: xprintf("+EDI"); break;\r
+  }\r
+  if (i != 4)\r
+    switch (s)\r
+    {\r
+      case 0: break;\r
+      case 1: xprintf("*2"); break;\r
+      case 2: xprintf("*4"); break;\r
+      case 3: xprintf("*8"); break;\r
+\r
+    }\r
+}\r
+/*------------------------------------------------------------------------*/\r
+static void do_modrm(char t)\r
+{\r
+  int m;\r
+  int r;\r
+\r
+  m = ((modrm()) >> 6) & 7;\r
+  r = modrm() & 7;\r
+\r
+  if (m == 3)\r
+  {\r
+    reg_name(r, t);\r
+    return;\r
+  }\r
+  if ((m == 0) && (r == 5))\r
+  {\r
+    decode("~p:[");\r
+    ohex('d', 4, 0, 32);\r
+    xprintf("]");\r
+    return;\r
+  }\r
+\r
+  if (r != 4)\r
+    decode("~p:[");\r
+\r
+  switch (r)\r
+    {\r
+      case 0: xprintf("EAX"); break;\r
+      case 1: xprintf("ECX"); break;\r
+      case 2: xprintf("EDX"); break;\r
+      case 3: xprintf("EBX"); break;\r
+      case 4: do_sib(m); break;\r
+      case 5: xprintf("EBP"); break;\r
+      case 6: xprintf("ESI"); break;\r
+      case 7: xprintf("EDI"); break;\r
+  }\r
+  switch (m)\r
+  {\r
+    case 1:\r
+      ohex('b', 4, 0, 32);\r
+      break;\r
+    case 2:\r
+      xprintf("+");\r
+      ohex('v', 4, 0, 32);\r
+      break;\r
+  }\r
+  xprintf("]");\r
+}\r
+\r
+/***********************************************\r
+  This disassembles one instruction each time it\r
+  is called.\r
+************************************************/\r
+\r
+U32 disassemble(U32 Addr)\r
+{\r
+  prefix = 0;\r
+  fmodrmv = 0;\r
+  fsibv = 0;\r
+  opsize = SEGSIZE;     /* default operand size is DWORD */\r
+  addrIn = Addr;\r
+\r
+  xprintf( "%08x   ", addrIn);\r
+\r
+  decode(opmap1[getbyte()]);   /* decode instruction and output */\r
+\r
+  xprintf( "\r\n");\r
+  return addrIn;\r
+}\r