--- /dev/null
+/* 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