Annotation of mstools/samples/sdktools/image/drwatson/i386/disasm.c, revision 1.1

1.1     ! root        1: /*++
        !             2: 
        !             3: Copyright (c) 1993  Microsoft Corporation
        !             4: 
        !             5: Module Name:
        !             6: 
        !             7:     disasm.c
        !             8: 
        !             9: Abstract:
        !            10: 
        !            11:     This file provides support disassembly ( x86 ).
        !            12: 
        !            13: Author:
        !            14: 
        !            15:     Gerd Immeyer       19-Oct-1989
        !            16:     Wesley Witt (wesw) 1-May-1993    ( ported from ntsd to drwatson)
        !            17: 
        !            18: Environment:
        !            19: 
        !            20:     User Mode
        !            21: 
        !            22: --*/
        !            23: 
        !            24: #include <windows.h>
        !            25: #include <stddef.h>
        !            26: #include <string.h>
        !            27: #include "regs.h"
        !            28: #include "disasm.h"
        !            29: #include "drwatson.h"
        !            30: #include "proto.h"
        !            31: 
        !            32: /*****                     macros and defines                          *****/
        !            33: 
        !            34: #define BIT20(b) (b & 0x07)
        !            35: #define BIT53(b) (b >> 3 & 0x07)
        !            36: #define BIT76(b) (b >> 6 & 0x03)
        !            37: #define MAXL     16
        !            38: #define MAXOPLEN 10
        !            39: 
        !            40: #define OBOFFSET 26
        !            41: #define OBOPERAND 34
        !            42: #define OBLINEEND 77
        !            43: 
        !            44: /*****                     static tables and variables                 *****/
        !            45: 
        !            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: 
        !            57: static char *mrmtb32[] = { "eax",       /* modRM string table (32-bit) */
        !            58:                            "ecx",
        !            59:                            "edx",
        !            60:                            "ebx",
        !            61:                            "esp",
        !            62:                            "ebp",
        !            63:                            "esi",
        !            64:                            "edi"
        !            65:                          };
        !            66: 
        !            67: static char seg16[8]   = { REGDS,  REGDS,  REGSS,  REGSS,
        !            68:                            REGDS,  REGDS,  REGSS,  REGDS };
        !            69: static char reg16[8]   = { REGEBX, REGEBX, REGEBP, REGEBP,
        !            70:                            REGESI, REGEDI, REGEBP, REGEBX };
        !            71: static char reg16_2[4] = { REGESI, REGEDI, REGESI, REGEDI };
        !            72: 
        !            73: static char seg32[8]   = { REGDS,  REGDS,  REGDS,  REGDS,
        !            74:                            REGSS,  REGSS,  REGDS,  REGDS };
        !            75: static char reg32[8]   = { REGEAX, REGECX, REGEDX, REGEBX,
        !            76:                            REGESP, REGEBP, REGESI, REGEDI };
        !            77: 
        !            78: static char sregtab[] = "ecsdfg";  // first letter of ES, CS, SS, DS, FS, GS
        !            79: 
        !            80: char    hexdigit[] = { '0', '1', '2', '3', '4', '5', '6', '7',
        !            81:                        '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
        !            82: 
        !            83: static int              mod;            /* mod of mod/rm byte */
        !            84: static int              rm;             /* rm of mod/rm byte */
        !            85: static int              ttt;            /* return reg value (of mod/rm) */
        !            86: static unsigned char    *pMem;          /* current position in instruction */
        !            87: static int              mode_32;        /* local addressing mode indicator */
        !            88: static int              opsize_32;      /* operand size flag */
        !            89: 
        !            90: ULONG                   EAaddr[2];      //  offset of effective address
        !            91: static int              EAsize[2];      //  size of effective address item
        !            92: static char             *pchEAseg[2];   //  normal segment for operand
        !            93: 
        !            94: int                     G_mode_32 = 1;  /* global address mode indicator */
        !            95: 
        !            96: static BOOLEAN          fMovX;          // indicates a MOVSX or MOVZX
        !            97: 
        !            98: //      internal function definitions
        !            99: 
        !           100: BOOLEAN disasm(PDEBUGPACKET, PULONG, PUCHAR, BOOLEAN);
        !           101: void DIdoModrm(PDEBUGPACKET dp,char **, int, BOOLEAN);
        !           102: 
        !           103: void OutputHexString(char **, char *, int);
        !           104: void OutputHexValue(char **, char *, int, int);
        !           105: void OutputHexCode(char **, char *, int);
        !           106: void OutputString(char **, char *);
        !           107: void OutputSymbol(PDEBUGPACKET, char **, char *, int, int);
        !           108: 
        !           109: void GetNextOffset(PDEBUGPACKET, PULONG, BOOLEAN);
        !           110: void OutputHexAddr(PUCHAR *, ULONG);
        !           111: USHORT GetSegRegValue(PDEBUGPACKET,int);
        !           112: 
        !           113: /**** disasm - disassemble an 80x86/80x87 instruction
        !           114: *
        !           115: *  Input:
        !           116: *       pOffset = pointer to offset to start disassembly
        !           117: *       fEAout = if set, include EA (effective address)
        !           118: *
        !           119: *  Output:
        !           120: *       pOffset = pointer to offset of next instruction
        !           121: *       pchDst = pointer to result string
        !           122: *
        !           123: ***************************************************************************/
        !           124: 
        !           125: BOOLEAN
        !           126: disasm( PDEBUGPACKET dp, PULONG pOffset, PUCHAR pchDst, BOOLEAN fEAout )
        !           127: {
        !           128:     int     opcode;                     /* current opcode */
        !           129:     int     olen = 2;                   /* operand length */
        !           130:     int     alen = 2;                   /* address length */
        !           131:     int     end = FALSE;                /* end of instruction flag */
        !           132:     int     mrm = FALSE;                /* indicator that modrm is generated*/
        !           133:     unsigned char *action;              /* action for operand interpretation*/
        !           134:     long    tmp;                        /* temporary storage field */
        !           135:     int     indx;                       /* temporary index */
        !           136:     int     action2;                    /* secondary action */
        !           137:     int     instlen;                    /* instruction length */
        !           138:     int     cBytes;                     //  bytes read into instr buffer
        !           139:     int     segOvr = 0;                 /* segment override opcode */
        !           140:     char    membuf[MAXL];               /* current instruction buffer */
        !           141:     char    *pEAlabel = "";             //  optional label for operand
        !           142: 
        !           143:     char    *pchResultBuf = pchDst;     //  working copy of pchDst pointer
        !           144:     char    RepPrefixBuffer[32];        //  rep prefix buffer
        !           145:     char    *pchRepPrefixBuf = RepPrefixBuffer; //  pointer to prefix buffer
        !           146:     char    OpcodeBuffer[8];            //  opcode buffer
        !           147:     char    *pchOpcodeBuf = OpcodeBuffer; //  pointer to opcode buffer
        !           148:     char    OperandBuffer[80];          //  operand buffer
        !           149:     char    *pchOperandBuf = OperandBuffer; //  pointer to operand buffer
        !           150:     char    ModrmBuffer[80];            //  modRM buffer
        !           151:     char    *pchModrmBuf = ModrmBuffer; //  pointer to modRM buffer
        !           152:     char    EABuffer[42];               //  effective address buffer
        !           153:     char    *pchEABuf = EABuffer;       //  pointer to EA buffer
        !           154: 
        !           155:     int     obOpcode = OBOFFSET;
        !           156:     int     obOpcodeMin;
        !           157:     int     obOpcodeMax;
        !           158: 
        !           159:     int     obOperand = OBOPERAND;
        !           160:     int     obOperandMin;
        !           161:     int     obOperandMax;
        !           162: 
        !           163:     int     cbOpcode;
        !           164:     int     cbOperand;
        !           165:     int     cbOffset;
        !           166:     int     cbEAddr;
        !           167: 
        !           168:     int     fTwoLines = FALSE;
        !           169: 
        !           170:     fMovX = FALSE;
        !           171:     EAsize[0] = EAsize[1] = 0;          //  no effective address
        !           172:     pchEAseg[0] = dszDS_;
        !           173:     pchEAseg[1] = dszES_;
        !           174: 
        !           175:     mode_32 = opsize_32 = (G_mode_32 == 1); /* local addressing mode */
        !           176:     olen = alen = (1 + mode_32) << 1;   //  set operand/address lengths
        !           177:                                         //  2 for 16-bit and 4 for 32-bit
        !           178: 
        !           179:     OutputHexAddr(&pchResultBuf, *pOffset);
        !           180: 
        !           181:     *pchResultBuf++ = ' ';
        !           182: 
        !           183:     ReadProcessMemory( dp->hProcess,
        !           184:                        (LPVOID)*pOffset,
        !           185:                        (LPVOID)membuf,
        !           186:                        MAXL,
        !           187:                        &cBytes
        !           188:                      );
        !           189: 
        !           190:                                         /* move full inst to local buffer */
        !           191:     pMem = membuf;                      /* point to begin of instruction */
        !           192:     opcode = *pMem++;                   /* get opcode */
        !           193:     OutputString(&pchOpcodeBuf, distbl[opcode].instruct);
        !           194:     action = actiontbl + distbl[opcode].opr; /* get operand action */
        !           195: 
        !           196: /*****          loop through all operand actions               *****/
        !           197: 
        !           198:     do {
        !           199:         action2 = (*action) & 0xc0;
        !           200:         switch((*action++) & 0x3f) {
        !           201:             case ALT:                   /* alter the opcode if 32-bit */
        !           202:                 if (opsize_32) {
        !           203:                     indx = *action++;
        !           204:                     pchOpcodeBuf = &OpcodeBuffer[indx];
        !           205:                     if (indx == 0)
        !           206:                         OutputString(&pchOpcodeBuf, dszCWDE);
        !           207:                     else {
        !           208:                         *pchOpcodeBuf++ = 'd';
        !           209:                         if (indx == 1)
        !           210:                             *pchOpcodeBuf++ = 'q';
        !           211:                         }
        !           212:                     }
        !           213:                 break;
        !           214: 
        !           215:             case STROP:
        !           216:                 //  compute size of operands in indx
        !           217:                 //  also if dword operands, change fifth
        !           218:                 //  opcode letter from 'w' to 'd'.
        !           219: 
        !           220:                 if (opcode & 1) {
        !           221:                     if (opsize_32) {
        !           222:                         indx = 4;
        !           223:                         OpcodeBuffer[4] = 'd';
        !           224:                         }
        !           225:                     else
        !           226:                         indx = 2;
        !           227:                     }
        !           228:                 else
        !           229:                     indx = 1;
        !           230: 
        !           231:                 if (*action & 1) {
        !           232:                     if (fEAout) {
        !           233:                         EAaddr[0] = GetRegValue(dp, REGESI);
        !           234:                         EAsize[0] = indx;
        !           235:                         }
        !           236:                     }
        !           237:                 if (*action++ & 2) {
        !           238:                     if (fEAout) {
        !           239:                         EAaddr[1] = GetRegValue(dp, REGEDI);
        !           240:                         EAsize[1] = indx;
        !           241:                         }
        !           242:                     }
        !           243:                 break;
        !           244: 
        !           245:             case CHR:                   /* insert a character */
        !           246:                 *pchOperandBuf++ = *action++;
        !           247:                 break;
        !           248: 
        !           249:             case CREG:                  /* set debug, test or control reg */
        !           250:                 if ((opcode - 231) & 0x04)      //  remove bias from opcode
        !           251:                     *pchOperandBuf++ = 't';
        !           252:                 else if ((opcode - 231) & 0x01)
        !           253:                     *pchOperandBuf++ = 'd';
        !           254:                 else
        !           255:                     *pchOperandBuf++ = 'c';
        !           256:                 *pchOperandBuf++ = 'r';
        !           257:                 *pchOperandBuf++ = (char)('0' + ttt);
        !           258:                 break;
        !           259: 
        !           260:             case SREG2:                 /* segment register */
        !           261:                 ttt = BIT53(opcode);    //  set value to fall through
        !           262: 
        !           263:             case SREG3:                 /* segment register */
        !           264:                 *pchOperandBuf++ = sregtab[ttt];  // reg is part of modrm
        !           265:                 *pchOperandBuf++ = 's';
        !           266:                 break;
        !           267: 
        !           268:             case BRSTR:                 /* get index to register string */
        !           269:                 ttt = *action++;        /*    from action table */
        !           270:                 goto BREGlabel;
        !           271: 
        !           272:             case BOREG:                 /* byte register (in opcode) */
        !           273:                 ttt = BIT20(opcode);    /* register is part of opcode */
        !           274:                 goto BREGlabel;
        !           275: 
        !           276:             case ALSTR:
        !           277:                 ttt = 0;                /* point to AL register */
        !           278: BREGlabel:
        !           279:             case BREG:                  /* general register */
        !           280:                 *pchOperandBuf++ = regtab[ttt * 2];
        !           281:                 *pchOperandBuf++ = regtab[ttt * 2 + 1];
        !           282:                 break;
        !           283: 
        !           284:             case WRSTR:                 /* get index to register string */
        !           285:                 ttt = *action++;        /*    from action table */
        !           286:                 goto WREGlabel;
        !           287: 
        !           288:             case VOREG:                 /* register is part of opcode */
        !           289:                 ttt = BIT20(opcode);
        !           290:                 goto VREGlabel;
        !           291: 
        !           292:             case AXSTR:
        !           293:                 ttt = 0;                /* point to eAX register */
        !           294: VREGlabel:
        !           295:             case VREG:                  /* general register */
        !           296:                 if (opsize_32)          /* test for 32bit mode */
        !           297:                     *pchOperandBuf++ = 'e';
        !           298: WREGlabel:
        !           299:             case WREG:                  /* register is word size */
        !           300:                 *pchOperandBuf++ = regtab[ttt * 2 + 16];
        !           301:                 *pchOperandBuf++ = regtab[ttt * 2 + 17];
        !           302:                 break;
        !           303: 
        !           304:             case IST_ST:
        !           305:                 OutputString(&pchOperandBuf, "st(0),st");
        !           306:                 *(pchOperandBuf - 5) += rm;
        !           307:                 break;
        !           308: 
        !           309:             case ST_IST:
        !           310:                 OutputString(&pchOperandBuf, "st,");
        !           311:             case IST:
        !           312:                 OutputString(&pchOperandBuf, "st(0)");
        !           313:                 *(pchOperandBuf - 2) += rm;
        !           314:                 break;
        !           315: 
        !           316:             case xBYTE:                 /* set instruction to byte only */
        !           317:                 EAsize[0] = 1;
        !           318:                 pEAlabel = "byte ptr ";
        !           319:                 break;
        !           320: 
        !           321:             case VAR:
        !           322:                 if (opsize_32)
        !           323:                     goto DWORDlabel;
        !           324: 
        !           325:             case xWORD:
        !           326:                 EAsize[0] = 2;
        !           327:                 pEAlabel = "word ptr ";
        !           328:                 break;
        !           329: 
        !           330:             case EDWORD:
        !           331:                 opsize_32 = 1;    //  for control reg move, use eRegs
        !           332:             case xDWORD:
        !           333: DWORDlabel:
        !           334:                 EAsize[0] = 4;
        !           335:                 pEAlabel = "dword ptr ";
        !           336:                 break;
        !           337: 
        !           338:             case QWORD:
        !           339:                 EAsize[0] = 8;
        !           340:                 pEAlabel = "qword ptr ";
        !           341:                 break;
        !           342: 
        !           343:             case TTBYTE:
        !           344:                 EAsize[0] = 10;
        !           345:                 pEAlabel = "tbyte ptr ";
        !           346:                 break;
        !           347: 
        !           348:             case FARPTR:
        !           349:                 if (opsize_32) {
        !           350:                     EAsize[0] = 6;
        !           351:                     pEAlabel = "fword ptr ";
        !           352:                     }
        !           353:                 else {
        !           354:                     EAsize[0] = 4;
        !           355:                     pEAlabel = "dword ptr ";
        !           356:                     }
        !           357:                 break;
        !           358: 
        !           359:             case LMODRM:                //  output modRM data type
        !           360:                 if (mod != 3)
        !           361:                     OutputString(&pchOperandBuf, pEAlabel);
        !           362:                 else
        !           363:                     EAsize[0] = 0;
        !           364: 
        !           365:             case MODRM:                 /* output modrm string */
        !           366:                 if (segOvr)             /* in case of segment override */
        !           367:                     OutputString(&pchOperandBuf, distbl[segOvr].instruct);
        !           368:                 *pchModrmBuf = '\0';
        !           369:                 OutputString(&pchOperandBuf, ModrmBuffer);
        !           370:                 break;
        !           371: 
        !           372:             case ADDRP:                 /* address pointer */
        !           373:                 OutputHexString(&pchOperandBuf, pMem + olen, 2); // segment
        !           374:                 *pchOperandBuf++ = ':';
        !           375:                 OutputSymbol(dp, &pchOperandBuf, pMem, olen, segOvr);
        !           376:                 pMem += olen + 2;
        !           377:                 break;
        !           378: 
        !           379:             case REL8:                  /* relative address 8-bit */
        !           380:                 if (opcode == 0xe3 && mode_32) {
        !           381:                     pchOpcodeBuf = OpcodeBuffer;
        !           382:                     OutputString(&pchOpcodeBuf, dszJECXZ);
        !           383:                     }
        !           384:                 tmp = (long)*(char *)pMem++; /* get the 8-bit rel offset */
        !           385:                 goto DoRelDispl;
        !           386: 
        !           387:             case REL16:                 /* relative address 16-/32-bit */
        !           388:                 tmp = 0;
        !           389:                 memmove(&tmp,pMem,sizeof(long));
        !           390:                 pMem += alen;           /* skip over offset */
        !           391: DoRelDispl:
        !           392:                 tmp += *pOffset + (pMem - membuf); /* calculate address */
        !           393:                 OutputSymbol(dp, &pchOperandBuf, (char *) &tmp, alen, segOvr);
        !           394:                                                    // address
        !           395:                 break;
        !           396: 
        !           397:             case UBYTE:                 //  unsigned byte for int/in/out
        !           398:                 OutputHexString(&pchOperandBuf, pMem, 1);  //  ubyte
        !           399:                 pMem++;
        !           400:                 break;
        !           401: 
        !           402:             case IB:                    /* operand is immediate byte */
        !           403:                 if ((opcode & ~1) == 0xd4) {  // postop for AAD/AAM is 0x0a
        !           404:                     if (*pMem++ != 0x0a) // test post-opcode byte
        !           405:                         OutputString(&pchOperandBuf, dszRESERVED);
        !           406:                     break;
        !           407:                     }
        !           408:                 olen = 1;               /* set operand length */
        !           409:                 goto DoImmed;
        !           410: 
        !           411:             case IW:                    /* operand is immediate word */
        !           412:                 olen = 2;               /* set operand length */
        !           413: 
        !           414:             case IV:                    /* operand is word or dword */
        !           415: DoImmed:
        !           416:                 OutputHexValue(&pchOperandBuf, pMem, olen, FALSE);
        !           417:                 pMem += olen;
        !           418:                 break;
        !           419: 
        !           420:             case OFFS:                  /* operand is offset */
        !           421:                 EAsize[0] = (opcode & 1) ? olen : 1;
        !           422: 
        !           423:                 if (segOvr)             /* in case of segment override */
        !           424:                     OutputString(&pchOperandBuf, distbl[segOvr].instruct);
        !           425: 
        !           426:                 *pchOperandBuf++ = '[';
        !           427:                 OutputSymbol(dp,&pchOperandBuf, pMem, alen, segOvr);  //  offset
        !           428:                 pMem += alen;
        !           429:                 *pchOperandBuf++ = ']';
        !           430:                 break;
        !           431: 
        !           432:             case GROUP:                 /* operand is of group 1,2,4,6 or 8 */
        !           433:                                         /* output opcode symbol */
        !           434:                 OutputString(&pchOpcodeBuf, group[*action++][ttt]);
        !           435:                 break;
        !           436: 
        !           437:             case GROUPT:                /* operand is of group 3,5 or 7 */
        !           438:                 indx = *action;         /* get indx into group from action */
        !           439:                 goto doGroupT;
        !           440: 
        !           441:             case EGROUPT:               /* x87 ESC (D8-DF) group index */
        !           442:                 indx = BIT20(opcode) * 2; /* get group index from opcode */
        !           443:                 if (mod == 3) {         /* some operand variations exists */
        !           444:                                         /*   for x87 and mod == 3 */
        !           445:                     ++indx;             /* take the next group table entry */
        !           446:                     if (indx == 3) {    /* for x87 ESC==D9 and mod==3 */
        !           447:                         if (ttt > 3) {  /* for those D9 instructions */
        !           448:                             indx = 12 + ttt; /* offset index to table by 12 */
        !           449:                             ttt = rm;   /* set secondary index to rm */
        !           450:                             }
        !           451:                         }
        !           452:                     else if (indx == 7) { /* for x87 ESC==DB and mod==3 */
        !           453:                         if (ttt == 4)   /* only valid if ttt==4 */
        !           454:                             ttt = rm;   /* set secondary group table index */
        !           455:                         else
        !           456:                             ttt = 7;    /* no an x87 instruction */
        !           457:                         }
        !           458:                     }
        !           459: doGroupT:
        !           460:                 /* handle group with different types of operands */
        !           461: 
        !           462:                 OutputString(&pchOpcodeBuf, groupt[indx][ttt].instruct);
        !           463:                 action = actiontbl + groupt[indx][ttt].opr;
        !           464:                                                         /* get new action */
        !           465:                 break;
        !           466: 
        !           467:             case OPC0F:                 /* secondary opcode table (opcode 0F) */
        !           468:                 opcode = *pMem++;       /* get real opcode */
        !           469:                 fMovX  = (BOOLEAN)(opcode == 0xBF || opcode == 0xB7);
        !           470:                 if (opcode < 7) /* for the first 7 opcodes */
        !           471:                     opcode += 256;      /* point begin of secondary opcode tab. */
        !           472:                 else if (opcode > 0x1f && opcode < 0x27)
        !           473:                     opcode += 231;      /* adjust for non-existing opcodes */
        !           474:                 else if (opcode > 0x2f && opcode < 0x33)
        !           475:                     opcode += 222;      /* adjust for non-existing opcodes */
        !           476:                 else if (opcode > 0x7e && opcode < 0xd0)
        !           477:                     opcode += 148;      /* adjust for non-existing opcodes */
        !           478:                 else
        !           479:                     opcode = 260;       /* all non-existing opcodes */
        !           480:                 goto getNxtByte1;
        !           481: 
        !           482:             case ADR_OVR:               /* address override */
        !           483:                 mode_32 = !G_mode_32;   /* override addressing mode */
        !           484:                 alen = (mode_32 + 1) << 1; /* toggle address length */
        !           485:                 goto getNxtByte;
        !           486: 
        !           487:             case OPR_OVR:               /* operand size override */
        !           488:                 opsize_32 = !G_mode_32; /* override operand size */
        !           489:                 olen = (opsize_32 + 1) << 1; /* toggle operand length */
        !           490:                 goto getNxtByte;
        !           491: 
        !           492:             case SEG_OVR:               /* handle segment override */
        !           493:                 segOvr = opcode;        /* save segment override opcode */
        !           494:                 pchOpcodeBuf = OpcodeBuffer;  // restart the opcode string
        !           495:                 goto getNxtByte;
        !           496: 
        !           497:             case REP:                   /* handle rep/lock prefixes */
        !           498:                 *pchOpcodeBuf = '\0';
        !           499:                 if (pchRepPrefixBuf != RepPrefixBuffer)
        !           500:                     *pchRepPrefixBuf++ = ' ';
        !           501:                 OutputString(&pchRepPrefixBuf, OpcodeBuffer);
        !           502:                 pchOpcodeBuf = OpcodeBuffer;
        !           503: getNxtByte:
        !           504:                 opcode = *pMem++;        /* next byte is opcode */
        !           505: getNxtByte1:
        !           506:                 action = actiontbl + distbl[opcode].opr;
        !           507:                 OutputString(&pchOpcodeBuf, distbl[opcode].instruct);
        !           508: 
        !           509:             default:                    /* opcode has no operand */
        !           510:                 break;
        !           511:             }
        !           512:         switch (action2) {              /* secondary action */
        !           513:             case MRM:                   /* generate modrm for later use */
        !           514:                 if (!mrm) {             /* ignore if it has been generated */
        !           515:                     DIdoModrm(dp, &pchModrmBuf, segOvr, fEAout);
        !           516:                                         /* generate modrm */
        !           517:                     mrm = TRUE;         /* remember its generation */
        !           518:                     }
        !           519:                 break;
        !           520: 
        !           521:             case COM:                   /* insert a comma after operand */
        !           522:                 *pchOperandBuf++ = ',';
        !           523:                 break;
        !           524: 
        !           525:             case END:                   /* end of instruction */
        !           526:                 end = TRUE;
        !           527:                 break;
        !           528:             }
        !           529:  } while (!end);                        /* loop til end of instruction */
        !           530: 
        !           531: /*****       prepare disassembled instruction for output              *****/
        !           532: 
        !           533:     instlen = pMem - membuf;
        !           534: 
        !           535:     if (instlen < cBytes)
        !           536:         cBytes = instlen;
        !           537: 
        !           538:     OutputHexCode(&pchResultBuf, membuf, cBytes);
        !           539: 
        !           540:     if (instlen > cBytes) {
        !           541:         *pchResultBuf++ = '?';
        !           542:         *pchResultBuf++ = '?';
        !           543:         (*pOffset)++;                   //  point past unread byte
        !           544:         }
        !           545: 
        !           546:     *pOffset += instlen;                /* set instruction length */
        !           547: 
        !           548:     if (instlen > cBytes) {
        !           549:         do
        !           550:             *pchResultBuf++ = ' ';
        !           551:         while (pchResultBuf < pchDst + OBOFFSET);
        !           552:         OutputString(&pchResultBuf, "???");
        !           553:         *pchResultBuf++ = '\0';
        !           554:         return FALSE;
        !           555:         }
        !           556: 
        !           557:     //  if fEAout is set, build each EA with trailing space in EABuf
        !           558:     //  point back over final trailing space if buffer nonnull
        !           559: 
        !           560:     if (fEAout) {
        !           561: 
        !           562:         for (indx = 0; indx < 2; indx++)
        !           563:             if (EAsize[indx]) {
        !           564:                 OutputString(&pchEABuf, segOvr ? distbl[segOvr].instruct
        !           565:                                                : pchEAseg[indx]);
        !           566:                 OutputHexAddr(&pchEABuf, EAaddr[indx]);
        !           567:                 *pchEABuf++ = '=';
        !           568: 
        !           569:                 ReadProcessMemory( dp->hProcess,
        !           570:                                    (LPVOID)EAaddr[indx],
        !           571:                                    (LPVOID)membuf,
        !           572:                                    EAsize[indx],
        !           573:                                    &tmp
        !           574:                                  );
        !           575: 
        !           576:                 if (tmp == EAsize[indx])
        !           577:                     OutputHexString(&pchEABuf, (char *)membuf,
        !           578:                                                EAsize[indx]);
        !           579:                 else
        !           580:                     while (EAsize[indx]--) {
        !           581:                         *pchEABuf++ = '?';
        !           582:                         *pchEABuf++ = '?';
        !           583:                         }
        !           584:                 *pchEABuf++ = ' ';
        !           585:                 }
        !           586:         if (pchEABuf != EABuffer)
        !           587:             pchEABuf--;
        !           588:         }
        !           589: 
        !           590:     //  compute lengths of component strings.
        !           591:     //  if the rep string is nonnull,
        !           592:     //      add the opcode string length to the operand
        !           593:     //      make the rep string the opcode string
        !           594: 
        !           595:     cbOffset = pchResultBuf - pchDst;
        !           596:     cbOperand = pchOperandBuf - OperandBuffer;
        !           597:     cbOpcode = pchOpcodeBuf - OpcodeBuffer;
        !           598:     if (pchRepPrefixBuf != RepPrefixBuffer) {
        !           599:         cbOperand += cbOpcode + (cbOperand != 0);
        !           600:         cbOpcode = pchRepPrefixBuf - RepPrefixBuffer;
        !           601:         }
        !           602:     cbEAddr = pchEABuf - EABuffer;
        !           603: 
        !           604:     //  for really long strings, where the opcode and operand
        !           605:     //      will not fit on a 77-character line, make two lines
        !           606:     //      with the opcode on offset 0 on the second line with
        !           607:     //      the operand following after one space
        !           608: 
        !           609:     if (cbOpcode + cbOperand > OBLINEEND - 1) {
        !           610:         fTwoLines = TRUE;
        !           611:         obOpcode = 0;
        !           612:         obOperand = cbOpcode + 1;
        !           613:         }
        !           614:     else {
        !           615: 
        !           616:         //  compute the minimum and maximum offset values for
        !           617:         //      opcode and operand strings.
        !           618:         //  if strings are nonnull, add extra for separating space
        !           619: 
        !           620:         obOpcodeMin = cbOffset + 1;
        !           621:         obOperandMin = obOpcodeMin + cbOpcode + 1;
        !           622:         obOperandMax = OBLINEEND - cbEAddr - (cbEAddr != 0) - cbOperand;
        !           623:         obOpcodeMax = obOperandMax - (cbOperand != 0) - cbOpcode;
        !           624: 
        !           625:         //  if minimum offset is more than the maximum, the strings
        !           626:         //      will not fit on one line.  recompute the min/max
        !           627:         //      values with no offset and EA strings.
        !           628: 
        !           629:         if (obOpcodeMin > obOpcodeMax) {
        !           630:             fTwoLines = TRUE;
        !           631:             obOpcodeMin = 0;
        !           632:             obOperandMin = cbOpcode + 1;
        !           633:             obOperandMax = OBLINEEND - cbOperand;
        !           634:             obOpcodeMax = obOperandMax - (cbOperand != 0) - cbOpcode;
        !           635:             }
        !           636: 
        !           637:         //  compute the opcode and operand offsets.  set offset as
        !           638:         //      close to the default values as possible.
        !           639: 
        !           640:         if (obOpcodeMin > OBOFFSET)
        !           641:             obOpcode = obOpcodeMin;
        !           642:         else if (obOpcodeMax < OBOFFSET)
        !           643:             obOpcode = obOpcodeMax;
        !           644: 
        !           645:         obOperandMin = obOpcode + cbOpcode + 1;
        !           646: 
        !           647:         if (obOperandMin > OBOPERAND)
        !           648:             obOperand = obOperandMin;
        !           649:         else if (obOperandMax < OBOPERAND)
        !           650:             obOperand = obOperandMax;
        !           651:         }
        !           652: 
        !           653:     //  build the resultant string with the offsets computed
        !           654: 
        !           655:     //  if two lines are to be output,
        !           656:     //      append the EAddr string
        !           657:     //      output a new line and reset the pointer
        !           658: 
        !           659:     if (fTwoLines) {
        !           660:         if (pchEABuf != EABuffer) {
        !           661:             do
        !           662:                 *pchResultBuf++ = ' ';
        !           663:             while (pchResultBuf < pchDst + OBLINEEND - cbEAddr);
        !           664:             *pchEABuf = '\0';
        !           665:             OutputString(&pchResultBuf, EABuffer);
        !           666:             }
        !           667:         pchDst = pchResultBuf;
        !           668:         }
        !           669: 
        !           670:     //  output rep, opcode, and operand strings
        !           671: 
        !           672:     do
        !           673:         *pchResultBuf++ = ' ';
        !           674:     while (pchResultBuf < pchDst + obOpcode);
        !           675: 
        !           676:     if (pchRepPrefixBuf != RepPrefixBuffer) {
        !           677:         *pchRepPrefixBuf = '\0';
        !           678:         OutputString(&pchResultBuf, RepPrefixBuffer);
        !           679:         do
        !           680:             *pchResultBuf++ = ' ';
        !           681:         while (pchResultBuf < pchDst + obOperand);
        !           682:         }
        !           683: 
        !           684:     *pchOpcodeBuf = '\0';
        !           685:     OutputString(&pchResultBuf, OpcodeBuffer);
        !           686: 
        !           687:     if (pchOperandBuf != OperandBuffer) {
        !           688:         do
        !           689:             *pchResultBuf++ = ' ';
        !           690:         while (pchResultBuf < pchDst + obOperand);
        !           691:         *pchOperandBuf = '\0';
        !           692:         OutputString(&pchResultBuf, OperandBuffer);
        !           693:         }
        !           694: 
        !           695:     //  if one line is to be output, append the EAddr string
        !           696: 
        !           697:     if (!fTwoLines && pchEABuf != EABuffer) {
        !           698:         *pchEABuf = '\0';
        !           699:         do
        !           700:             *pchResultBuf++ = ' ';
        !           701:         while (pchResultBuf < pchDst + OBLINEEND - cbEAddr);
        !           702:         OutputString(&pchResultBuf, EABuffer);
        !           703:         }
        !           704: 
        !           705:     *pchResultBuf = '\0';
        !           706:     return TRUE;
        !           707: }
        !           708: 
        !           709: /*...........................internal function..............................*/
        !           710: /*                                                                          */
        !           711: /*                       generate a mod/rm string                           */
        !           712: /*                                                                          */
        !           713: 
        !           714: void
        !           715: DIdoModrm (PDEBUGPACKET dp, char **ppchBuf, int segOvr, BOOLEAN fEAout)
        !           716: {
        !           717:     int     mrm;                        /* modrm byte */
        !           718:     char    *src;                       /* source string */
        !           719:     int     sib;
        !           720:     int     ss;
        !           721:     int     ind;
        !           722:     int     oldrm;
        !           723: 
        !           724:     mrm = *pMem++;                      /* get the mrm byte from instruction */
        !           725:     mod = BIT76(mrm);                   /* get mod */
        !           726:     ttt = BIT53(mrm);                   /* get reg - used outside routine */
        !           727:     rm  = BIT20(mrm);                   /* get rm */
        !           728: 
        !           729:     if (mod == 3) {                     /* register only mode */
        !           730:         src = &regtab[rm * 2];          /* point to 16-bit register */
        !           731:         if (EAsize[0] > 1) {
        !           732:             src += 16;                  /* point to 16-bit register */
        !           733:             if (opsize_32 && !fMovX)
        !           734:                 *(*ppchBuf)++ = 'e';    /* make it a 32-bit register */
        !           735:             }
        !           736:         *(*ppchBuf)++ = *src++;         /* copy register name */
        !           737:         *(*ppchBuf)++ = *src;
        !           738:         EAsize[0] = 0;                  //  no EA value to output
        !           739:         return;
        !           740:         }
        !           741: 
        !           742:     if (mode_32) {                      /* 32-bit addressing mode */
        !           743:         oldrm = rm;
        !           744:         if (rm == 4) {                  /* rm == 4 implies sib byte */
        !           745:             sib = *pMem++;              /* get s_i_b byte */
        !           746:             rm = BIT20(sib);            /* return base */
        !           747:             }
        !           748: 
        !           749:         *(*ppchBuf)++ = '[';
        !           750:         if (mod == 0 && rm == 5) {
        !           751:             OutputSymbol(dp,ppchBuf, pMem, 4, segOvr); // offset
        !           752:             pMem += 4;
        !           753:             }
        !           754:         else {
        !           755:             if (fEAout) {
        !           756:                 if (segOvr) {
        !           757:                     EAaddr[0] = GetRegValue(dp, reg32[rm]);
        !           758:                     pchEAseg[0] = distbl[segOvr].instruct;
        !           759:                     }
        !           760:                 else if (reg32[rm] == REGEBP || reg32[rm] == REGESP) {
        !           761:                     EAaddr[0] = GetRegValue(dp, reg32[rm]);
        !           762:                     pchEAseg[0] = dszSS_;
        !           763:                     }
        !           764:                 else
        !           765:                     EAaddr[0] = GetRegValue(dp, reg32[rm]);
        !           766:                 }
        !           767:             OutputString(ppchBuf, mrmtb32[rm]);
        !           768:             }
        !           769: 
        !           770:         if (oldrm == 4) {               //  finish processing sib
        !           771:             ind = BIT53(sib);
        !           772:             if (ind != 4) {
        !           773:                 *(*ppchBuf)++ = '+';
        !           774:                 OutputString(ppchBuf, mrmtb32[ind]);
        !           775:                 ss = 1 << BIT76(sib);
        !           776:                 if (ss != 1) {
        !           777:                     *(*ppchBuf)++ = '*';
        !           778:                     *(*ppchBuf)++ = (char)(ss + '0');
        !           779:                     }
        !           780:                 if (fEAout)
        !           781:                     EAaddr[0] = GetRegValue(dp, reg32[ind]);
        !           782:                 }
        !           783:             }
        !           784:         }
        !           785:     else {                              //  16-bit addressing mode
        !           786:         *(*ppchBuf)++ = '[';
        !           787:         if (mod == 0 && rm == 6) {
        !           788:             OutputSymbol(dp,ppchBuf, pMem, 2, segOvr);   // 16-bit offset
        !           789:             pMem += 2;
        !           790:             }
        !           791:         else {
        !           792:             if (fEAout) {
        !           793:                 if (segOvr) {
        !           794:                     EAaddr[0] = GetRegValue(dp, reg16[rm]);
        !           795:                     pchEAseg[0] = distbl[segOvr].instruct;
        !           796:                     }
        !           797:                 else if (reg16[rm] == REGEBP) {
        !           798:                     EAaddr[0] = GetRegValue(dp, reg16[rm]);
        !           799:                     pchEAseg[0] = dszSS_;
        !           800:                     }
        !           801:                 else
        !           802:                     EAaddr[0] = GetRegValue(dp, reg16[rm]);
        !           803:                 if (rm < 4)
        !           804:                     EAaddr[0] += GetRegValue(dp, reg16_2[rm]);
        !           805:             }
        !           806:             OutputString(ppchBuf, mrmtb16[rm]);
        !           807:             }
        !           808:         }
        !           809: 
        !           810:     //  output any displacement
        !           811: 
        !           812:     if (mod == 1) {
        !           813:         if (fEAout)
        !           814:             EAaddr[0] += (ULONG)pMem;
        !           815:         OutputHexValue(ppchBuf, pMem, 1, TRUE);
        !           816:         pMem++;
        !           817:         }
        !           818:     else if (mod == 2) {
        !           819:         long tmp = 0;
        !           820:         if (mode_32) {
        !           821:             memmove(&tmp,pMem,sizeof(long));
        !           822:             if (fEAout)
        !           823:                 EAaddr[0] += (ULONG)tmp;
        !           824:             OutputHexValue(ppchBuf, pMem, 4, TRUE);
        !           825:             pMem += 4;
        !           826:             }
        !           827:         else {
        !           828:             memmove(&tmp,pMem,sizeof(short));
        !           829:             if (fEAout)
        !           830:                 EAaddr[0] += tmp;
        !           831:             OutputHexValue(ppchBuf, pMem, 2, TRUE);
        !           832:             pMem += 2;
        !           833:             }
        !           834:         }
        !           835: 
        !           836:     if (!mode_32 && fEAout) {
        !           837:         EAaddr[0] &= 0xffff;
        !           838:         EAaddr[1] &= 0xffff;
        !           839:     }
        !           840: 
        !           841:     *(*ppchBuf)++ = ']';
        !           842: }
        !           843: 
        !           844: /*** OutputHexValue - output hex value
        !           845: *
        !           846: *   Purpose:
        !           847: *       Output the value pointed by *ppchBuf of the specified
        !           848: *       length.  The value is treated as signed and leading
        !           849: *       zeroes are not printed.  The string is prefaced by a
        !           850: *       '+' or '-' sign as appropriate.
        !           851: *
        !           852: *   Input:
        !           853: *       *ppchBuf - pointer to text buffer to fill
        !           854: *       *pchMemBuf - pointer to memory buffer to extract value
        !           855: *       length - length in bytes of value (1, 2, and 4 supported)
        !           856: *       fDisp - set if displacement to output '+'
        !           857: *
        !           858: *   Output:
        !           859: *       *ppchBuf - pointer updated to next text character
        !           860: *
        !           861: *************************************************************************/
        !           862: 
        !           863: void OutputHexValue (char **ppchBuf, char *pchMemBuf, int length, int fDisp)
        !           864: {
        !           865:     long    value;
        !           866:     int     index;
        !           867:     char    digit[8];
        !           868: 
        !           869:     value = 0;
        !           870:     if (length == 1)
        !           871:         value = (long)(*(char *)pchMemBuf);
        !           872:     else if (length == 2)
        !           873:         memmove(&value,pchMemBuf,2);
        !           874:     else
        !           875:         memmove(&value,pchMemBuf,sizeof(long));
        !           876: 
        !           877:     length <<= 1;               //  shift once to get hex length
        !           878: 
        !           879:     if (value != 0 || !fDisp) {
        !           880:         if (fDisp)
        !           881:             if (value < 0 && length == 2) {   //  use neg value for byte
        !           882:                 value = -value;               //    displacement
        !           883:                 *(*ppchBuf)++ = '-';
        !           884:                 }
        !           885:             else
        !           886:                 *(*ppchBuf)++ = '+';
        !           887: 
        !           888:         *(*ppchBuf)++ = '0';
        !           889:         *(*ppchBuf)++ = 'x';
        !           890:         for (index = length - 1; index != -1; index--) {
        !           891:             digit[index] = (char)(value & 0xf);
        !           892:             value >>= 4;
        !           893:             }
        !           894:         index = 0;
        !           895:         while (digit[index] == 0 && index < length - 1)
        !           896:             index++;
        !           897:         while (index < length)
        !           898:             *(*ppchBuf)++ = hexdigit[digit[index++]];
        !           899:         }
        !           900: }
        !           901: 
        !           902: /*** OutputHexString - output hex string
        !           903: *
        !           904: *   Purpose:
        !           905: *       Output the value pointed by *ppchMemBuf of the specified
        !           906: *       length.  The value is treated as unsigned and leading
        !           907: *       zeroes are printed.
        !           908: *
        !           909: *   Input:
        !           910: *       *ppchBuf - pointer to text buffer to fill
        !           911: *       *pchValue - pointer to memory buffer to extract value
        !           912: *       length - length in bytes of value
        !           913: *
        !           914: *   Output:
        !           915: *       *ppchBuf - pointer updated to next text character
        !           916: *       *ppchMemBuf - pointer update to next memory byte
        !           917: *
        !           918: *************************************************************************/
        !           919: 
        !           920: void
        !           921: OutputHexString (char **ppchBuf, char *pchValue, int length)
        !           922: {
        !           923:     unsigned char    chMem;
        !           924: 
        !           925:     pchValue += length;
        !           926:     while (length--) {
        !           927:         chMem = *--pchValue;
        !           928:         *(*ppchBuf)++ = hexdigit[chMem >> 4];
        !           929:         *(*ppchBuf)++ = hexdigit[chMem & 0x0f];
        !           930:         }
        !           931: }
        !           932: 
        !           933: /*** OutputHexCode - output hex code
        !           934: *
        !           935: *   Purpose:
        !           936: *       Output the code pointed by pchMemBuf of the specified
        !           937: *       length.  The value is treated as unsigned and leading
        !           938: *       zeroes are printed.  This differs from OutputHexString
        !           939: *       in that bytes are printed from low to high addresses.
        !           940: *
        !           941: *   Input:
        !           942: *       *ppchBuf - pointer to text buffer to fill
        !           943: *       pchMemBuf - pointer to memory buffer to extract value
        !           944: *       length - length in bytes of value
        !           945: *
        !           946: *   Output:
        !           947: *       *ppchBuf - pointer updated to next text character
        !           948: *
        !           949: *************************************************************************/
        !           950: 
        !           951: void
        !           952: OutputHexCode (char **ppchBuf, char *pchMemBuf, int length)
        !           953: {
        !           954:     unsigned char    chMem;
        !           955: 
        !           956:     while (length--) {
        !           957:         chMem = *pchMemBuf++;
        !           958:         *(*ppchBuf)++ = hexdigit[chMem >> 4];
        !           959:         *(*ppchBuf)++ = hexdigit[chMem & 0x0f];
        !           960:         }
        !           961: }
        !           962: 
        !           963: /*** OutputString - output string
        !           964: *
        !           965: *   Purpose:
        !           966: *       Copy the string into the buffer pointed by *ppBuf.
        !           967: *
        !           968: *   Input:
        !           969: *       *pStr - pointer to string
        !           970: *
        !           971: *   Output:
        !           972: *       *ppBuf points to next character in buffer.
        !           973: *
        !           974: *************************************************************************/
        !           975: 
        !           976: void
        !           977: OutputString (char **ppBuf, char *pStr)
        !           978: {
        !           979:     while (*pStr)
        !           980:         *(*ppBuf)++ = *pStr++;
        !           981: }
        !           982: 
        !           983: /*** OutputSymbol - output symbolic value
        !           984: *
        !           985: *   Purpose:
        !           986: *       Output the value in outvalue into the buffer
        !           987: *       pointed by *pBuf.  Express the value as a
        !           988: *       symbol plus displacment, if possible.
        !           989: *
        !           990: *   Input:
        !           991: *       *ppBuf - pointer to text buffer to fill
        !           992: *       *pValue - pointer to memory buffer to extract value
        !           993: *       length - length in bytes of value
        !           994: *
        !           995: *   Output:
        !           996: *       *ppBuf - pointer updated to next text character
        !           997: *
        !           998: *************************************************************************/
        !           999: 
        !          1000: void
        !          1001: OutputSymbol (PDEBUGPACKET dp, char **ppBuf, char *pValue, int length, int segOvr)
        !          1002: {
        !          1003:     ULONG   displacement;
        !          1004:     ULONG   value;
        !          1005:     PSYMBOL sym;
        !          1006:     char    *szSymName;
        !          1007: 
        !          1008:     value = 0;
        !          1009:     if (length == 1)
        !          1010:         value = (long)(*(char *)pValue);
        !          1011:     else if (length == 2)
        !          1012:         memmove(&value,pValue,sizeof(short));
        !          1013:     else
        !          1014:         memmove(&value,pValue,sizeof(long));
        !          1015: 
        !          1016:     EAaddr[0] = value;
        !          1017: 
        !          1018:     sym = GetSymFromAddrAllContexts( value, &displacement, dp );
        !          1019:     if (sym) {
        !          1020:         szSymName = UnDName( &sym->szName[1] );
        !          1021:         OutputString(ppBuf, szSymName);
        !          1022:         OutputHexValue(ppBuf, (char *)&displacement, length, TRUE);
        !          1023:         *(*ppBuf)++ = ' ';
        !          1024:         *(*ppBuf)++ = '(';
        !          1025:         OutputHexString(ppBuf, pValue, length);
        !          1026:         *(*ppBuf)++ = ')';
        !          1027:         }
        !          1028:     else
        !          1029:         OutputHexString(ppBuf, pValue, length);
        !          1030: }
        !          1031: 
        !          1032: /*** X86GetNextOffset - compute offset for trace or step
        !          1033: *
        !          1034: *   Purpose:
        !          1035: *       From a limited disassembly of the instruction pointed
        !          1036: *       by the FIR register, compute the offset of the next
        !          1037: *       instruction for either a trace or step operation.
        !          1038: *
        !          1039: *   Input:
        !          1040: *       fStep - TRUE if step offset returned - FALSE for trace offset
        !          1041: *
        !          1042: *   Returns:
        !          1043: *       step or trace offset if input is TRUE or FALSE, respectively
        !          1044: *       -1 returned for trace flag to be used
        !          1045: *
        !          1046: *************************************************************************/
        !          1047: 
        !          1048: void
        !          1049: GetNextOffset (PDEBUGPACKET dp, PULONG pcaddr, BOOLEAN fStep)
        !          1050: {
        !          1051:     int     mode_32;
        !          1052:     int     opsize_32;
        !          1053:     int     cBytes;
        !          1054:     char    membuf[MAXL];               //  current instruction buffer
        !          1055:     ULONG   addrReturn;
        !          1056:     USHORT  retAddr[3];                 //  return address buffer
        !          1057:     char    *pMem;
        !          1058:     UCHAR   opcode;
        !          1059:     int     fPrefix = TRUE;
        !          1060:     int     fRepPrefix = FALSE;
        !          1061:     int     ttt;
        !          1062:     int     rm;
        !          1063:     ULONG   instroffset;
        !          1064: 
        !          1065:     //  read instruction stream bytes into membuf and set mode and
        !          1066:     //      opcode size flags
        !          1067: 
        !          1068:     *pcaddr = GetRegValue(dp,REGEIP);
        !          1069:     instroffset = *pcaddr;
        !          1070:     G_mode_32 = TRUE;
        !          1071:     mode_32 = opsize_32 = (G_mode_32 == 1); /* local addressing mode */
        !          1072:     ReadProcessMemory( dp->hProcess,
        !          1073:                        (LPVOID)*pcaddr,
        !          1074:                        (LPVOID)membuf,
        !          1075:                        MAXL,
        !          1076:                        &cBytes
        !          1077:                      );
        !          1078:                                         /* move full inst to local buffer */
        !          1079:     pMem = membuf;                      /* point to begin of instruction */
        !          1080: 
        !          1081:     //  read and process any prefixes first
        !          1082: 
        !          1083:     do {
        !          1084:         opcode = (UCHAR)*pMem++;        /* get opcode */
        !          1085:         if (opcode == 0x66)
        !          1086:             opsize_32 = !G_mode_32;
        !          1087:         else if (opcode == 0x67)
        !          1088:             mode_32 = !G_mode_32;
        !          1089:         else if ((opcode & ~1) == 0xf2)
        !          1090:             fRepPrefix = TRUE;
        !          1091:         else if (opcode != 0xf0 && (opcode & ~0x18) != 0x26
        !          1092:                                 && (opcode & ~1) != 0x64)
        !          1093:             fPrefix = FALSE;
        !          1094:         }
        !          1095:     while (fPrefix);
        !          1096: 
        !          1097:     //  for instructions that alter the TF (trace flag), return the
        !          1098:     //      offset of the next instruction despite the flag of fStep
        !          1099: 
        !          1100:     if (((opcode & ~0x3) == 0x9c))
        !          1101:         //  9c-9f, pushf, popf, sahf, lahf
        !          1102:         ;
        !          1103: 
        !          1104:     else if (opcode == 0xcf) {          //  cf - iret - get RA from stack
        !          1105: 
        !          1106:         addrReturn = GetRegValue(dp, REGESP);
        !          1107:         ReadProcessMemory( dp->hProcess,
        !          1108:                            (LPVOID)addrReturn,
        !          1109:                            (LPVOID)retAddr,
        !          1110:                            sizeof(retAddr),
        !          1111:                            NULL
        !          1112:                          );
        !          1113: 
        !          1114:         *pcaddr = retAddr[2];
        !          1115:         return;
        !          1116:         }
        !          1117: 
        !          1118:     //  repeated string/port instructions
        !          1119: 
        !          1120:     if (opcode == 0xe8)            //  near direct jump
        !          1121:         pMem += (1 + opsize_32) * 2;
        !          1122: 
        !          1123:     else if (opcode == 0x9a)            //  far direct jump
        !          1124:         pMem += (2 + opsize_32) * 2;
        !          1125: 
        !          1126:     else if (opcode == 0xcd ||
        !          1127:              (opcode >= 0xe0 && opcode <= 0xe2)) //  loop / int nn instrs
        !          1128:         pMem++;
        !          1129: 
        !          1130:     else if (opcode == 0xff) {          //  indirect call - compute length
        !          1131:         opcode = *pMem++;               //  get modRM
        !          1132:         ttt = BIT53(opcode);
        !          1133:         if ((ttt & ~1) == 2) {
        !          1134:             mod = BIT76(opcode);
        !          1135:             if (mod != 3) {                     //  nonregister operand
        !          1136:                 rm = BIT20(opcode);
        !          1137:                 if (mode_32) {
        !          1138:                     if (rm == 4)
        !          1139:                         rm = BIT20(*pMem++);    //  get base from SIB
        !          1140:                     if (mod == 0) {
        !          1141:                         if (rm == 5)
        !          1142:                             pMem += 4;          //  long direct address
        !          1143:                         }                       //  else register
        !          1144:                     else if (mod == 1)
        !          1145:                         pMem++;                 //  register with byte offset
        !          1146:                     else
        !          1147:                         pMem += 4;              //  register with long offset
        !          1148:                     }
        !          1149:                 else {                          //  16-bit mode
        !          1150:                     if (mod == 0) {
        !          1151:                         if (rm == 6)
        !          1152:                             pMem += 2;          //  short direct address
        !          1153:                         }
        !          1154:                     else
        !          1155:                         pMem += mod;            //  reg, byte, word offset
        !          1156:                     }
        !          1157:                 }
        !          1158:             }
        !          1159:         else
        !          1160:             instroffset = (ULONG)-1;            //  0xff, but not call
        !          1161:         }
        !          1162: 
        !          1163:     else if (!((fRepPrefix && ((opcode & ~3) == 0x6c ||
        !          1164:                                (opcode & ~3) == 0xa4 ||
        !          1165:                                (opcode & ~1) == 0xaa ||
        !          1166:                                (opcode & ~3) == 0xac)) ||
        !          1167:                                opcode == 0xcc || opcode == 0xce))
        !          1168:         instroffset = (ULONG)-1;                //  not repeated string op
        !          1169:                                                 //  or int 3 / into
        !          1170: 
        !          1171:     //  if not enough bytes were read for instruction parse,
        !          1172:     //      just give up and trace the instruction
        !          1173: 
        !          1174:     if (cBytes < pMem - membuf)
        !          1175:         instroffset = (ULONG)-1;
        !          1176: 
        !          1177:     //  if not tracing, compute the new instruction offset
        !          1178: 
        !          1179:     if (instroffset != (ULONG)-1)
        !          1180:         instroffset += pMem - membuf;
        !          1181: 
        !          1182:     *pcaddr = instroffset;
        !          1183: }
        !          1184: 
        !          1185: void
        !          1186: OutputHexAddr (PUCHAR *ppBuffer, ULONG offset)
        !          1187: {
        !          1188:     OutputHexString(ppBuffer, (char *)&offset, sizeof(ULONG));
        !          1189: }
        !          1190: 
        !          1191: USHORT
        !          1192: GetSegRegValue (PDEBUGPACKET dp, int segOpcode)
        !          1193: {
        !          1194:     ULONG    regnum;
        !          1195: 
        !          1196:     switch (segOpcode) {
        !          1197:         case 0x26:
        !          1198:             regnum = REGES;
        !          1199:             break;
        !          1200:         case 0x2e:
        !          1201:             regnum = REGCS;
        !          1202:             break;
        !          1203:         case 0x36:
        !          1204:             regnum = REGSS;
        !          1205:             break;
        !          1206:         case 0x64:
        !          1207:             regnum = REGFS;
        !          1208:             break;
        !          1209:         case 0x65:
        !          1210:             regnum = REGGS;
        !          1211:             break;
        !          1212:         case 0x3e:
        !          1213:         default:
        !          1214:             regnum = REGDS;
        !          1215:         }
        !          1216: 
        !          1217:     return (USHORT)GetRegValue(dp,regnum);
        !          1218: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.