Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

579 lines
23 KiB

  1. /* @ Author: Gerd Immeyer @ Version: */
  2. /* */
  3. /* @ Creation Date: 10.19.89 @ Modification Date: */
  4. /* */
  5. /***************************************************************************/
  6. //
  7. // Munged for my purposes on 10/20/99 (v-johnwh)
  8. //
  9. #include <string.h>
  10. typedef unsigned long DWORD;
  11. typedef unsigned long ULONG;
  12. typedef unsigned short USHORT;
  13. typedef unsigned __int64 ULONGLONG;
  14. typedef int BOOL;
  15. typedef ULONG *PULONG;
  16. typedef void * PVOID;
  17. #define ADDR_V86 ((USHORT)0x0002)
  18. #define ADDR_16 ((USHORT)0x0004)
  19. #define FALSE 0
  20. #define TRUE 1
  21. #define BIT20(b) (b & 0x07)
  22. #define BIT53(b) (b >> 3 & 0x07)
  23. #define BIT76(b) (b >> 6 & 0x03)
  24. #define MAXL 16
  25. #define MAXOPLEN 10
  26. #define REGDS 3
  27. #define REGSS 15
  28. #define REGEBX 6
  29. #define REGEBP 10
  30. #define REGEDI 4
  31. #define REGESI 5
  32. #define REGEAX 9
  33. #define REGECX 8
  34. #define REGEDX 7
  35. #define REGESP 14
  36. #define Off(x) ((x).off)
  37. #define Type(x) ((x).type)
  38. #define OBOFFSET 26
  39. #define OBOPERAND 34
  40. #define OBLINEEND 77
  41. #define MAX_SYMNAME_SIZE 1024
  42. #include "86dis.h"
  43. ULONG X86BrkptLength = 1L;
  44. ULONG X86TrapInstr = 0xcc;
  45. /***** static tables and variables *****/
  46. static char regtab[] = "alcldlblahchdhbhaxcxdxbxspbpsidi"; /* reg table */
  47. static char *mrmtb16[] = { "bx+si", /* modRM string table (16-bit) */
  48. "bx+di",
  49. "bp+si",
  50. "bp+di",
  51. "si",
  52. "di",
  53. "bp",
  54. "bx"
  55. };
  56. static char *mrmtb32[] = { "eax", /* modRM string table (32-bit) */
  57. "ecx",
  58. "edx",
  59. "ebx",
  60. "esp",
  61. "ebp",
  62. "esi",
  63. "edi"
  64. };
  65. static char seg16[8] = { REGDS, REGDS, REGSS, REGSS,
  66. REGDS, REGDS, REGSS, REGDS };
  67. static char reg16[8] = { REGEBX, REGEBX, REGEBP, REGEBP,
  68. REGESI, REGEDI, REGEBP, REGEBX };
  69. static char reg16_2[4] = { REGESI, REGEDI, REGESI, REGEDI };
  70. static char seg32[8] = { REGDS, REGDS, REGDS, REGDS,
  71. REGSS, REGSS, REGDS, REGDS };
  72. static char reg32[8] = { REGEAX, REGECX, REGEDX, REGEBX,
  73. REGESP, REGEBP, REGESI, REGEDI };
  74. static char sregtab[] = "ecsdfg"; // first letter of ES, CS, SS, DS, FS, GS
  75. char hexdigit[] = { '0', '1', '2', '3', '4', '5', '6', '7',
  76. '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
  77. typedef struct _DECODEDATA
  78. {
  79. int mod; /* mod of mod/rm byte */
  80. int rm; /* rm of mod/rm byte */
  81. int ttt; /* return reg value (of mod/rm) */
  82. unsigned char *pMem; /* current position in instruction */
  83. ADDR EAaddr[2]; // offset of effective address
  84. int EAsize[2]; // size of effective address item
  85. char *pchEAseg[2]; // normal segment for operand
  86. BOOL fMovX; // indicates a MOVSX or MOVZX
  87. BOOL fMmRegEa; // Use mm? registers in reg-only EA.
  88. } DECODEDATA;
  89. /*...........................internal function..............................*/
  90. /* */
  91. /* generate a mod/rm string */
  92. /* */
  93. void DIdoModrm (char **ppchBuf, int segOvr, DECODEDATA *decodeData)
  94. {
  95. int mrm; /* modrm byte */
  96. char *src; /* source string */
  97. int sib;
  98. int ss;
  99. int ind;
  100. int oldrm;
  101. mrm = *(decodeData->pMem)++; /* get the mrm byte from instruction */
  102. decodeData->mod = BIT76(mrm); /* get mod */
  103. decodeData->ttt = BIT53(mrm); /* get reg - used outside routine */
  104. decodeData->rm = BIT20(mrm); /* get rm */
  105. if (decodeData->mod == 3) { /* register only mode */
  106. if (decodeData->fMmRegEa) {
  107. *(*ppchBuf)++ = 'm';
  108. *(*ppchBuf)++ = 'm';
  109. *(*ppchBuf)++ = decodeData->rm + '0';
  110. } else {
  111. src = &regtab[decodeData->rm * 2]; /* point to 16-bit register */
  112. if (decodeData->EAsize[0] > 1) {
  113. src += 16; /* point to 16-bit register */
  114. if (!(decodeData->fMovX))
  115. *(*ppchBuf)++ = 'e'; /* make it a 32-bit register */
  116. }
  117. *(*ppchBuf)++ = *src++; /* copy register name */
  118. *(*ppchBuf)++ = *src;
  119. }
  120. decodeData->EAsize[0] = 0; // no EA value to output
  121. return;
  122. }
  123. if (1) { /* 32-bit addressing mode */
  124. oldrm = decodeData->rm;
  125. if (decodeData->rm == 4) { /* rm == 4 implies sib byte */
  126. sib = *(decodeData->pMem)++; /* get s_i_b byte */
  127. decodeData->rm = BIT20(sib); /* return base */
  128. }
  129. *(*ppchBuf)++ = '[';
  130. if (decodeData->mod == 0 && decodeData->rm == 5) {
  131. decodeData->pMem += 4;
  132. }
  133. if (oldrm == 4) { // finish processing sib
  134. ind = BIT53(sib);
  135. if (ind != 4) {
  136. *(*ppchBuf)++ = '+';
  137. ss = 1 << BIT76(sib);
  138. if (ss != 1) {
  139. *(*ppchBuf)++ = '*';
  140. *(*ppchBuf)++ = (char)(ss + '0');
  141. }
  142. }
  143. }
  144. }
  145. // output any displacement
  146. if (decodeData->mod == 1) {
  147. decodeData->pMem++;
  148. }
  149. else if (decodeData->mod == 2) {
  150. long tmp = 0;
  151. if (1) {
  152. decodeData->pMem += 4;
  153. }
  154. else {
  155. decodeData->pMem += 2;
  156. }
  157. }
  158. }
  159. DWORD GetInstructionLengthFromAddress(PVOID paddr)
  160. {
  161. PULONG pOffset = 0;
  162. int G_mode_32;
  163. int mode_32; /* local addressing mode indicator */
  164. int opsize_32; /* operand size flag */
  165. int opcode; /* current opcode */
  166. int olen = 2; /* operand length */
  167. int alen = 2; /* address length */
  168. int end = FALSE; /* end of instruction flag */
  169. int mrm = FALSE; /* indicator that modrm is generated*/
  170. unsigned char *action; /* action for operand interpretation*/
  171. long tmp; /* temporary storage field */
  172. int indx; /* temporary index */
  173. int action2; /* secondary action */
  174. int instlen; /* instruction length */
  175. int segOvr = 0; /* segment override opcode */
  176. unsigned char *membuf; /* current instruction buffer */
  177. char *pEAlabel = ""; /* optional label for operand */
  178. char RepPrefixBuffer[32]; /* rep prefix buffer */
  179. char *pchRepPrefixBuf = RepPrefixBuffer; /* pointer to prefix buffer */
  180. char OpcodeBuffer[8]; /* opcode buffer */
  181. char *pchOpcodeBuf = OpcodeBuffer; /* pointer to opcode buffer */
  182. char OperandBuffer[MAX_SYMNAME_SIZE + 20]; /* operand buffer */
  183. char *pchOperandBuf = OperandBuffer; /* pointer to operand buffer */
  184. char ModrmBuffer[MAX_SYMNAME_SIZE + 20]; /* modRM buffer */
  185. char *pchModrmBuf = ModrmBuffer; /* pointer to modRM buffer */
  186. char EABuffer[42]; /* effective address buffer */
  187. char *pchEABuf = EABuffer; /* pointer to EA buffer */
  188. unsigned char BOPaction;
  189. int subcode; /* bop subcode */
  190. DECODEDATA decodeData;
  191. decodeData.fMovX = FALSE;
  192. decodeData.fMmRegEa = FALSE;
  193. decodeData.EAsize[0] = decodeData.EAsize[1] = 0; // no effective address
  194. decodeData.pchEAseg[0] = dszDS_;
  195. decodeData.pchEAseg[1] = dszES_;
  196. G_mode_32 = 1;
  197. mode_32 = opsize_32 = (G_mode_32 == 1); /* local addressing mode */
  198. olen = alen = (1 + mode_32) << 1; // set operand/address lengths
  199. // 2 for 16-bit and 4 for 32-bit
  200. #if MULTIMODE
  201. if (paddr->type & (ADDR_V86 | ADDR_16)) {
  202. mode_32 = opsize_32 = 0;
  203. olen = alen = 2;
  204. }
  205. #endif
  206. membuf = (unsigned char *)paddr;
  207. decodeData.pMem = membuf; /* point to begin of instruction */
  208. opcode = *(decodeData.pMem)++; /* get opcode */
  209. if ( opcode == 0xc4 && *(decodeData.pMem) == 0xC4 ) {
  210. (decodeData.pMem)++;
  211. action = &BOPaction;
  212. BOPaction = IB | END;
  213. subcode = *(decodeData.pMem);
  214. if ( subcode == 0x50 || subcode == 0x52 || subcode == 0x53 || subcode == 0x54 || subcode == 0x57 || subcode == 0x58 || subcode == 0x58 ) {
  215. BOPaction = IW | END;
  216. }
  217. } else {
  218. action = actiontbl + distbl[opcode].opr; /* get operand action */
  219. }
  220. /***** loop through all operand actions *****/
  221. do {
  222. action2 = (*action) & 0xc0;
  223. switch((*action++) & 0x3f) {
  224. case ALT: /* alter the opcode if 32-bit */
  225. if (opsize_32) {
  226. indx = *action++;
  227. pchOpcodeBuf = &OpcodeBuffer[indx];
  228. if (indx == 0)
  229. ;
  230. else {
  231. *pchOpcodeBuf++ = 'd';
  232. if (indx == 1)
  233. *pchOpcodeBuf++ = 'q';
  234. }
  235. }
  236. break;
  237. case STROP:
  238. // compute size of operands in indx
  239. // also if dword operands, change fifth
  240. // opcode letter from 'w' to 'd'.
  241. if (opcode & 1) {
  242. if (opsize_32) {
  243. indx = 4;
  244. OpcodeBuffer[4] = 'd';
  245. }
  246. else
  247. indx = 2;
  248. }
  249. else
  250. indx = 1;
  251. if (*action & 1) {
  252. }
  253. if (*action++ & 2) {
  254. }
  255. break;
  256. case CHR: /* insert a character */
  257. *pchOperandBuf++ = *action++;
  258. break;
  259. case CREG: /* set debug, test or control reg */
  260. if ((opcode - SECTAB_OFFSET_2)&0x04) //remove bias from opcode
  261. *pchOperandBuf++ = 't';
  262. else if ((opcode - SECTAB_OFFSET_2) & 0x01)
  263. *pchOperandBuf++ = 'd';
  264. else
  265. *pchOperandBuf++ = 'c';
  266. *pchOperandBuf++ = 'r';
  267. *pchOperandBuf++ = (char)('0' + decodeData.ttt);
  268. break;
  269. case SREG2: /* segment register */
  270. // Handle special case for fs/gs (OPC0F adds SECTAB_OFFSET_5
  271. // to these codes)
  272. if (opcode > 0x7e)
  273. decodeData.ttt = BIT53((opcode-SECTAB_OFFSET_5));
  274. else
  275. decodeData.ttt = BIT53(opcode); // set value to fall through
  276. case SREG3: /* segment register */
  277. *pchOperandBuf++ = sregtab[decodeData.ttt]; // reg is part of modrm
  278. *pchOperandBuf++ = 's';
  279. break;
  280. case BRSTR: /* get index to register string */
  281. decodeData.ttt = *action++; /* from action table */
  282. goto BREGlabel;
  283. case BOREG: /* byte register (in opcode) */
  284. decodeData.ttt = BIT20(opcode); /* register is part of opcode */
  285. goto BREGlabel;
  286. case ALSTR:
  287. decodeData.ttt = 0; /* point to AL register */
  288. BREGlabel:
  289. case BREG: /* general register */
  290. *pchOperandBuf++ = regtab[decodeData.ttt * 2];
  291. *pchOperandBuf++ = regtab[decodeData.ttt * 2 + 1];
  292. break;
  293. case WRSTR: /* get index to register string */
  294. decodeData.ttt = *action++; /* from action table */
  295. goto WREGlabel;
  296. case VOREG: /* register is part of opcode */
  297. decodeData.ttt = BIT20(opcode);
  298. goto VREGlabel;
  299. case AXSTR:
  300. decodeData.ttt = 0; /* point to eAX register */
  301. VREGlabel:
  302. case VREG: /* general register */
  303. if (opsize_32) /* test for 32bit mode */
  304. *pchOperandBuf++ = 'e';
  305. WREGlabel:
  306. case WREG: /* register is word size */
  307. *pchOperandBuf++ = regtab[decodeData.ttt * 2 + 16];
  308. *pchOperandBuf++ = regtab[decodeData.ttt * 2 + 17];
  309. break;
  310. case MMWREG:
  311. *pchOperandBuf++ = 'm';
  312. *pchOperandBuf++ = 'm';
  313. *pchOperandBuf++ = decodeData.ttt + '0';
  314. break;
  315. case IST_ST:
  316. *(pchOperandBuf - 5) += (char)decodeData.rm;
  317. break;
  318. case ST_IST:
  319. ;
  320. case IST:
  321. ;
  322. *(pchOperandBuf - 2) += (char)decodeData.rm;
  323. break;
  324. case xBYTE: /* set instruction to byte only */
  325. decodeData.EAsize[0] = 1;
  326. break;
  327. case VAR:
  328. if (opsize_32)
  329. goto DWORDlabel;
  330. case xWORD:
  331. decodeData.EAsize[0] = 2;
  332. break;
  333. case EDWORD:
  334. opsize_32 = 1; // for control reg move, use eRegs
  335. case xDWORD:
  336. DWORDlabel:
  337. decodeData.EAsize[0] = 4;
  338. break;
  339. case MMQWORD:
  340. decodeData.fMmRegEa = TRUE;
  341. case QWORD:
  342. decodeData.EAsize[0] = 8;
  343. break;
  344. case TBYTE:
  345. decodeData.EAsize[0] = 10;
  346. break;
  347. case FARPTR:
  348. if (opsize_32) {
  349. decodeData.EAsize[0] = 6;
  350. }
  351. else {
  352. decodeData.EAsize[0] = 4;
  353. }
  354. break;
  355. case LMODRM: // output modRM data type
  356. if (decodeData.mod != 3)
  357. ;
  358. else
  359. decodeData.EAsize[0] = 0;
  360. case MODRM: /* output modrm string */
  361. if (segOvr) /* in case of segment override */
  362. 0;
  363. break;
  364. case ADDRP: /* address pointer */
  365. decodeData.pMem += olen + 2;
  366. break;
  367. case REL8: /* relative address 8-bit */
  368. if (opcode == 0xe3 && mode_32) {
  369. pchOpcodeBuf = OpcodeBuffer;
  370. }
  371. tmp = (long)*(char *)(decodeData.pMem)++; /* get the 8-bit rel offset */
  372. goto DoRelDispl;
  373. case REL16: /* relative address 16-/32-bit */
  374. tmp = 0;
  375. if (mode_32)
  376. memmove(&tmp,decodeData.pMem,sizeof(long));
  377. else
  378. memmove(&tmp,decodeData.pMem,sizeof(short));
  379. decodeData.pMem += alen; /* skip over offset */
  380. DoRelDispl:
  381. // tmp += *pOffset + (decodeData.pMem - membuf); /* calculate address */
  382. // address
  383. break;
  384. case UBYTE: // unsigned byte for int/in/out
  385. decodeData.pMem++;
  386. break;
  387. case IB: /* operand is immediate byte */
  388. if ((opcode & ~1) == 0xd4) { // postop for AAD/AAM is 0x0a
  389. if (*(decodeData.pMem)++ != 0x0a) // test post-opcode byte
  390. 0;
  391. break;
  392. }
  393. olen = 1; /* set operand length */
  394. goto DoImmed;
  395. case IW: /* operand is immediate word */
  396. olen = 2; /* set operand length */
  397. case IV: /* operand is word or dword */
  398. DoImmed:
  399. decodeData.pMem += olen;
  400. break;
  401. case OFFS: /* operand is offset */
  402. decodeData.EAsize[0] = (opcode & 1) ? olen : 1;
  403. if (segOvr) /* in case of segment override */
  404. 0;
  405. decodeData.pMem += alen;
  406. break;
  407. case GROUP: /* operand is of group 1,2,4,6 or 8 */
  408. /* output opcode symbol */
  409. action++;
  410. break;
  411. case GROUPT: /* operand is of group 3,5 or 7 */
  412. indx = *action; /* get indx into group from action */
  413. goto doGroupT;
  414. case EGROUPT: /* x87 ESC (D8-DF) group index */
  415. indx = BIT20(opcode) * 2; /* get group index from opcode */
  416. if (decodeData.mod == 3) { /* some operand variations exists */
  417. /* for x87 and mod == 3 */
  418. ++indx; /* take the next group table entry */
  419. if (indx == 3) { /* for x87 ESC==D9 and mod==3 */
  420. if (decodeData.ttt > 3) { /* for those D9 instructions */
  421. indx = 12 + decodeData.ttt; /* offset index to table by 12 */
  422. decodeData.ttt = decodeData.rm; /* set secondary index to rm */
  423. }
  424. }
  425. else if (indx == 7) { /* for x87 ESC==DB and mod==3 */
  426. if (decodeData.ttt == 4) { /* if ttt==4 */
  427. decodeData.ttt = decodeData.rm; /* set secondary group table index */
  428. } else if ((decodeData.ttt<4)||(decodeData.ttt>4 && decodeData.ttt<7)) {
  429. // adjust for pentium pro opcodes
  430. indx = 24; /* offset index to table by 24*/
  431. }
  432. }
  433. }
  434. doGroupT:
  435. /* handle group with different types of operands */
  436. action = actiontbl + groupt[indx][decodeData.ttt].opr;
  437. /* get new action */
  438. break;
  439. //
  440. // The secondary opcode table has been compressed in the
  441. // original design. Hence while disassembling the 0F sequence,
  442. // opcode needs to be displaced by an appropriate amount depending
  443. // on the number of "filled" entries in the secondary table.
  444. // These displacements are used throughout the code.
  445. //
  446. case OPC0F: /* secondary opcode table (opcode 0F) */
  447. opcode = *(decodeData.pMem)++; /* get real opcode */
  448. decodeData.fMovX = (BOOL)(opcode == 0xBF || opcode == 0xB7);
  449. if (opcode < 12) /* for the first 12 opcodes */
  450. opcode += SECTAB_OFFSET_1; // point to begin of sec op tab
  451. else if (opcode > 0x1f && opcode < 0x27)
  452. opcode += SECTAB_OFFSET_2; // adjust for undefined opcodes
  453. else if (opcode > 0x2f && opcode < 0x34)
  454. opcode += SECTAB_OFFSET_3; // adjust for undefined opcodes
  455. else if (opcode > 0x3f && opcode < 0x50)
  456. opcode += SECTAB_OFFSET_4; // adjust for undefined opcodes
  457. else if (opcode > 0x5f && opcode < 0xff)
  458. opcode += SECTAB_OFFSET_5; // adjust for undefined opcodes
  459. else
  460. opcode = SECTAB_OFFSET_UNDEF; // all non-existing opcodes
  461. goto getNxtByte1;
  462. case ADR_OVR: /* address override */
  463. mode_32 = !G_mode_32; /* override addressing mode */
  464. alen = (mode_32 + 1) << 1; /* toggle address length */
  465. goto getNxtByte;
  466. case OPR_OVR: /* operand size override */
  467. opsize_32 = !G_mode_32; /* override operand size */
  468. olen = (opsize_32 + 1) << 1; /* toggle operand length */
  469. goto getNxtByte;
  470. case SEG_OVR: /* handle segment override */
  471. segOvr = opcode; /* save segment override opcode */
  472. pchOpcodeBuf = OpcodeBuffer; // restart the opcode string
  473. goto getNxtByte;
  474. case REP: /* handle rep/lock prefixes */
  475. if (pchRepPrefixBuf != RepPrefixBuffer)
  476. *pchRepPrefixBuf++ = ' ';
  477. pchOpcodeBuf = OpcodeBuffer;
  478. getNxtByte:
  479. opcode = *(decodeData.pMem)++; /* next byte is opcode */
  480. getNxtByte1:
  481. action = actiontbl + distbl[opcode].opr;
  482. default: /* opcode has no operand */
  483. break;
  484. }
  485. switch (action2) { /* secondary action */
  486. case MRM: /* generate modrm for later use */
  487. if (!mrm) { /* ignore if it has been generated */
  488. DIdoModrm(&pchModrmBuf, segOvr, &decodeData);
  489. mrm = TRUE; /* remember its generation */
  490. }
  491. break;
  492. case COM: /* insert a comma after operand */
  493. break;
  494. case END: /* end of instruction */
  495. end = TRUE;
  496. break;
  497. }
  498. } while (!end); /* loop til end of instruction */
  499. instlen = (decodeData.pMem) - membuf;
  500. return instlen;
  501. }