:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / apps / utils / pice / module / disassembler.c
1 /*++
2
3 Copyright (c) 2000-2001 Goran Devic                                                   
4 Modified (c) 2001 Klaus P. Gerlicher
5
6 Module Name:
7
8     disassembler.c
9
10 Abstract:
11
12     line disassembler
13
14 Environment:
15
16     LINUX 2.2.X
17     Kernel mode only
18
19 Author: 
20
21     Goran Devic                                                   
22
23 Revision History:
24
25   17-Mar-2000:  Original                                        (Goran Devic)                                             
26   26-Apr-2000:  Major rewrite, added coprocessor instructions   (Goran Devic)
27   04-Nov-2000:  Modified for LinIce                             (Goran Devic)                                    
28   05-Jan-2001:  Modified for pICE                               (Klaus P. Gerlicher)
29
30
31 Copyright notice:
32
33   This file may be distributed under the terms of the GNU Public License.
34
35 --*/
36
37 /*******************************************************************************
38 *   Include Files                                                             *
39 ******************************************************************************/
40 #include "remods.h"
41 #include "precomp.h"
42
43 #include "disassemblerdata.h"           // Include its own data
44
45 /******************************************************************************
46 *
47 *   This structure is used to pass parameters and options to the
48 *   line disassembler.
49 *
50 ******************************************************************************/
51 typedef struct
52 {
53     ULONG dwFlags;              // Generic flags (described below)
54     USHORT wSel;                  // Selector to use to fetch code
55     UCHAR *bpTarget;             // Target pointer to disassemble
56     UCHAR *szDisasm;             // String where to put ascii result
57     UCHAR Codes[20];             // Buffer where to store code UCHARs
58
59     UCHAR bAsciiLen;             // Length of the ascii result
60     UCHAR bInstrLen;             // Instruction lenght in UCHARs
61
62     int nDisplacement;          // Scanner: possible constant displacement
63     int nScanEnum;              // Scanner: specific flags SCAN_*
64
65 } TDisassembler;
66
67 // dwFlags contains a set of boolean flags with the following functionality
68
69 #define DIS_DATA32          0x0001  // Data size 16/32 bits (0/1)
70 #define   DIS_GETDATASIZE(flags) ((flags)&DIS_DATA32)
71 #define DIS_ADDRESS32       0x0002  // Address size 16/32 bits (0/1)
72 #define   DIS_GETADDRSIZE(flags) (((flags)&DIS_ADDRESS32)?1:0)
73
74 #define DIS_SEGOVERRIDE     0x0004  // Default segment has been overriden
75
76 #define DIS_REP             0x0100  // Return: REP prefix found (followed by..)
77 #define DIS_REPNE           0x0200  // Return: REPNE prefix found
78 #define   DIS_GETREPENUM(flags)  (((flags)>>8)&3)
79 #define DIS_ILLEGALOP       0x8000  // Return: illegal opcode
80
81
82 /******************************************************************************
83 *                                                                             *
84 *   Global Variables                                                          *
85 *                                                                             *
86 ******************************************************************************/
87
88
89 /******************************************************************************
90 *                                                                             *
91 *   External functions (optional)                                             *
92 *                                                                             *
93 ******************************************************************************/
94
95 /******************************************************************************
96 *                                                                             *
97 *   Local Defines, Variables and Macros                                       *
98 *                                                                             *
99 ******************************************************************************/
100 UCHAR GetUCHAR(ULONG addr)
101 {
102     if(IsAddressValid(addr))
103         return *(PUCHAR)addr;
104     else
105         return 0x82; // INVALID OPCODE
106 }
107
108 static UCHAR GetNextUCHAR(USHORT sel, UCHAR *offset, UCHAR *pCode)
109 {
110     pCode[0] = GetUCHAR((ULONG) offset + 0) & 0xFF;
111
112     return( pCode[0] );
113 }    
114
115 static USHORT GetNextUSHORT(USHORT sel, UCHAR *offset, UCHAR *pCode)
116 {
117     pCode[0] = GetUCHAR((ULONG) offset + 0) & 0xFF;
118     pCode[1] = GetUCHAR((ULONG) offset + 1) & 0xFF;
119
120     return( *(USHORT *) pCode );
121 }    
122
123 static ULONG GetNextULONG(USHORT sel, UCHAR *offset, UCHAR *pCode)
124 {
125     pCode[0] = GetUCHAR((ULONG) offset + 0) & 0xFF;
126     pCode[1] = GetUCHAR((ULONG) offset + 1) & 0xFF;
127     pCode[2] = GetUCHAR((ULONG) offset + 2) & 0xFF;
128     pCode[3] = GetUCHAR((ULONG) offset + 3) & 0xFF;
129
130     return( *(ULONG *) pCode );
131 }    
132
133
134 #define NEXTUCHAR    GetNextUCHAR( pDis->wSel, bpTarget, bpCode); bpCode += 1; bpTarget += 1; bInstrLen += 1
135
136 #define NEXTUSHORT    GetNextUSHORT( pDis->wSel, bpTarget, bpCode); bpCode += 2; bpTarget += 2; bInstrLen += 2
137
138 #define NEXTULONG   GetNextULONG(pDis->wSel, bpTarget, bpCode); bpCode += 4; bpTarget += 4; bInstrLen += 4
139
140
141 /******************************************************************************
142 *                                                                             *
143 *   Functions                                                                 *
144 *                                                                             *
145 ******************************************************************************/
146
147 /******************************************************************************
148 *                                                                             *
149 *   UCHAR Disassembler( TDisassembler *pDis );                                 *
150 *                                                                             *
151 *******************************************************************************
152 *
153 *   This is a generic Intel line disassembler.
154 *
155 *   Where:
156 *       TDisassembler:
157 *           bpTarget is the address of instruction to disassemble
158 *           szDisasm is the address of the buffer to print a line into
159 *           dwFlags contains the default operand and address bits
160 *           pCode is the address to store code UCHARs (up to 16)
161 *
162 *   Disassembled instruction is stored as an ASCIIZ string pointed by
163 *   szDisasm pointer (from the pDis structure).
164 *
165 *   Returns:
166 *       TDisassembler:
167 *           *szDisasm contains the disassembled instruction string
168 *           bAsciiLen is set to the length of the printed string
169 *           bInstrLen is set to instruction length in UCHARs
170 *           dwFlags - has operand and address size flags adjusted
171 *                   - DIS_ILLEGALOP set if that was illegal instruction
172 *       UCHAR - instruction length in UCHARs
173 *
174 ******************************************************************************/
175 UCHAR Disassembler( TDisassembler *pDis )
176 {
177     TOpcodeData *p;             // Pointer to a current instruction record
178     UCHAR   *bpTarget;           // Pointer to the target code to be disassembled
179     UCHAR   *bpCode;             // Pointer to code UCHARs
180     ULONG   arg;                // Argument counter
181     char   *sPtr;               // Message selection pointer
182     int     nPos;               // Printing position in the output string
183     UCHAR   *pArg;               // Pointer to record where instruction arguments are
184     ULONG   dwULONG;            // Temporary ULONG storage
185     USHORT    wUSHORT;              // Temporary USHORT storage
186     UCHAR    bUCHAR;              // Temporary UCHAR storage
187     UCHAR    bInstrLen;          // Current instruction lenght in UCHARs
188     UCHAR    bOpcode;            // Current opcode that is being disassembled
189     UCHAR    bSegOverride;       // 0 default segment. >0, segment index
190     UCHAR    bMod=0;             // Mod field of the instruction
191     UCHAR    bReg=0;             // Register field of the instruction
192     UCHAR    bRm=0;                // R/M field of the instruction
193     UCHAR    bW;                 // Width bit for the register selection
194
195     UCHAR    bSib;               // S-I-B UCHAR for the instruction
196     UCHAR    bSs;                // SS field of the s-i-b UCHAR
197     UCHAR    bIndex;             // Index field of the s-i-b UCHAR
198     UCHAR    bBase;              // Base field of the s-i-b UCHAR
199     LPSTR    pSymbolName;        // used to symbolic name of value
200
201     bInstrLen = 0;              // Reset instruction lenght to zero
202     bSegOverride = 0;           // Set default segment (no override)
203     nPos = 0;                   // Reset printing position
204     sPtr = NULL;                // Points to no message by default
205     bpTarget = pDis->bpTarget;  // Set internal pointer to a target address
206     bpCode = pDis->Codes;       // Set internal pointer to code UCHARs
207
208     do
209     {
210         bOpcode = NEXTUCHAR;     // Get the first opcode UCHAR from the target address
211         p = &Op1[bOpcode];      // Get the address of the instruction record
212
213         if( p->flags & DIS_SPECIAL )
214         {
215             // Opcode is one of the special ones, so do what needs to be done there
216
217             switch( p->name )
218             {
219                 case _EscD8:
220                 case _EscD9:
221                 case _EscDA:
222                 case _EscDB:
223                 case _EscDC:
224                 case _EscDD:
225                 case _EscDE:
226                 case _EscDF:        // Coprocessor escape: UCHARs D8 - DF
227                     bOpcode = NEXTUCHAR;             // Get the modRM UCHAR of the instruction
228
229                     if( bOpcode < 0xC0 )
230                     {
231                         // Opcodes 00-BF use Coproc1 table
232
233                         bReg = (bOpcode >> 3) & 7;
234                         p = &Coproc1[ p->name - _EscD8 ][ bReg ];
235
236                         goto StartInstructionParseMODRM;
237                     }
238                     // Opcodes C0-FF use Coproc2 table
239
240                     p = &Coproc2[ p->name - _EscD8 ][ bOpcode - 0xC0 ];
241
242                 goto StartInstructionNoMODRM;
243
244                 case _S_ES:         // Segment override
245                 case _S_CS:
246                 case _S_SS:
247                 case _S_DS:
248                 case _S_FS:
249                 case _S_GS:
250                     bSegOverride = p->name - _S_ES + 1;
251                 continue;
252
253                 case _OPSIZ:        // Operand size override - toggle
254                     pDis->dwFlags ^= DIS_DATA32;
255                 continue;
256
257                 case _ADSIZ:        // Address size override - toggle
258                     pDis->dwFlags ^= DIS_ADDRESS32;
259                 continue;
260
261                 case _REPNE:        // REPNE/REPNZ prefix
262                     pDis->dwFlags |= DIS_REPNE;
263                 continue;
264
265                 case _REP:          // REP/REPE/REPZ prefix
266                     pDis->dwFlags |= DIS_REP;
267                 continue;
268
269                 case _2BESC:        // 2 UCHAR escape code 0x0F
270                     bOpcode = NEXTUCHAR;             // Get the second UCHAR of the instruction
271                     p = &Op2[bOpcode];              // Get the address of the instruction record
272
273                     if( !(p->flags & DIS_SPECIAL) ) goto StartInstruction;
274                     if( p->name < _GRP6 ) goto IllegalOpcode;
275
276                 case _GRP1a:        // Additional groups of instructions
277                 case _GRP1b:
278                 case _GRP1c:
279                 case _GRP2a:
280                 case _GRP2b:
281                 case _GRP2c:
282                 case _GRP2d:
283                 case _GRP2e:
284                 case _GRP2f:
285                 case _GRP3a:
286                 case _GRP3b:
287                 case _GRP4:
288                 case _GRP5:
289                 case _GRP6:
290                 case _GRP7:
291                 case _GRP8:
292                 case _GRP9:
293
294                     bOpcode = NEXTUCHAR;             // Get the Mod R/M UCHAR whose...
295                                                     // bits 3,4,5 select instruction
296
297                     bReg = (bOpcode >> 3) & 7;
298                     p = &Groups[p->name - _GRP1a][ bReg ];
299
300                     if( !(p->flags & DIS_SPECIAL) ) goto StartInstructionParseMODRM;
301
302                 case _NDEF :        // Not defined or illegal opcode
303                     goto IllegalOpcode;
304
305                 default :;          // Should not happen
306             }
307         }
308         else
309             goto StartInstruction;
310     }
311     while( bInstrLen < 15 );
312
313 IllegalOpcode:
314
315     nPos += PICE_sprintf( pDis->szDisasm+nPos, "invalid");
316     pDis->dwFlags |= DIS_ILLEGALOP;
317
318     goto DisEnd;
319
320 StartInstruction:
321
322     // If this instruction needs additional Mod R/M UCHAR, fetch it
323
324     if( p->flags & DIS_MODRM )
325     {
326         // Get the next UCHAR (modR/M bit field)
327         bOpcode = NEXTUCHAR;
328
329         bReg = (bOpcode >> 3) & 7;
330
331 StartInstructionParseMODRM:
332
333         // Parse that UCHAR and get mod, reg and rm fields
334         bMod = bOpcode >> 6;
335         bRm  = bOpcode & 7;
336     }
337
338 StartInstructionNoMODRM:
339
340     // Print the possible repeat prefix followed by the instruction
341
342     if( p->flags & DIS_COPROC )
343         nPos += PICE_sprintf( pDis->szDisasm+nPos, "%-6s ", sCoprocNames[ p->name ]);
344     else
345         nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s%-6s ",
346                 sRep[DIS_GETREPENUM(pDis->dwFlags)],
347                 sNames[ p->name + (DIS_GETNAMEFLAG(p->flags) & DIS_GETDATASIZE(pDis->dwFlags)) ] );
348
349     // Do instruction argument processing, up to 3 times
350
351     pArg = &p->dest;
352
353     for( arg=p->args; arg!=0; arg--, pArg++, arg? nPos += PICE_sprintf( pDis->szDisasm+nPos,", ") : 0 )
354     {
355         switch( *pArg )
356         {
357              case _Eb :                                         // modR/M used - bW = 0
358                 bW = 0;
359                 goto _E;
360
361              case _Ev :                                         // modR/M used - bW = 1
362                 bW = 1;
363                 goto _E;
364
365              case _Ew :                                         // always USHORT size
366                 pDis->dwFlags &= ~DIS_DATA32;
367                 bW = 1;
368                 goto _E;
369
370              case _Ms :                                         // fword ptr (sgdt,sidt,lgdt,lidt)
371                 sPtr = sFwordPtr;
372                 goto _E1;
373
374              case _Mq :                                         // qword ptr (cmpxchg8b)
375                 sPtr = sQwordPtr;
376                 goto _E1;
377
378              case _Mp :                                         // 32 or 48 bit pointer (les,lds,lfs,lss,lgs)
379              case _Ep :                                         // Always a memory pointer (call, jmp)
380                 if( pDis->dwFlags & DIS_DATA32 )
381                     sPtr = sFwordPtr;
382                 else
383                     sPtr = sDwordPtr;
384                 goto _E1;
385
386              _E:
387                  // Do registers first so that the rest may be done together
388                  if( bMod == 3 )
389                  {
390                       // Registers depending on the w field and data size
391                       nPos+=PICE_sprintf(pDis->szDisasm+nPos, "%s", sRegs1[DIS_GETDATASIZE(pDis->dwFlags)][bW][bRm] );
392
393                       break;
394                  }
395
396                  if( bW==0 )
397                      sPtr = sBytePtr;
398                  else
399                      if( pDis->dwFlags & DIS_DATA32 )
400                          sPtr = sDwordPtr;
401                      else
402                          sPtr = sWordPtr;
403
404              case _M  :                                         // Pure memory pointer (lea,invlpg,floats)
405                 if( bMod == 3 ) goto IllegalOpcode;
406
407              _E1:
408
409                  if( sPtr )
410                      nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s", sPtr );
411
412              case _Ma :                                         // Used by bound instruction, skip the pointer info
413
414                  // Print the segment if it is overriden
415                  //
416                  nPos += PICE_sprintf( pDis->szDisasm+nPos,"%s", sSegOverride[ bSegOverride ] );
417
418                  //
419                  // Special case when sib UCHAR is present in 32 address encoding
420                  //
421                  if( (bRm==4) && (pDis->dwFlags & DIS_ADDRESS32) )
422                  {
423                       //
424                       // Get the s-i-b UCHAR and parse it
425                       //
426                       bSib = NEXTUCHAR;
427
428                       bSs = bSib >> 6;
429                       bIndex = (bSib >> 3) & 7;
430                       bBase = bSib & 7;
431
432                       // Special case for base=5 && mod==0 -> fetch 32 bit offset
433                       if( (bBase==5) && (bMod==0) )
434                       {
435                           dwULONG = NEXTULONG;
436                           if(ScanExportsByAddress(&pSymbolName,dwULONG))
437                           {
438                               nPos += PICE_sprintf( pDis->szDisasm+nPos,"[%s", pSymbolName );
439                           }
440                           else
441                           {
442                               nPos += PICE_sprintf( pDis->szDisasm+nPos,"[%08X", (unsigned int) dwULONG );
443                           }
444                       }
445                       else
446                           nPos += PICE_sprintf( pDis->szDisasm+nPos,"[%s", sGenReg16_32[ 1 ][ bBase ] );
447
448                       // Scaled index, no index if bIndex is 4
449                       if( bIndex != 4 )
450                           nPos += PICE_sprintf( pDis->szDisasm+nPos,"+%s%s", sScale[ bSs ], sGenReg16_32[ 1 ][ bIndex ] );
451                       else
452                           if(bSs != 0)
453                               nPos += PICE_sprintf( pDis->szDisasm+nPos,"<INVALID MODE>" );
454
455                       // Offset 8 bit or 32 bit
456                       if( bMod == 1 )
457                       {
458                           bUCHAR = NEXTUCHAR;
459                           if( (signed char)bUCHAR < 0 )
460                                  nPos += PICE_sprintf( pDis->szDisasm+nPos,"-%02X", 0-(signed char)bUCHAR );
461                           else
462                                  nPos += PICE_sprintf( pDis->szDisasm+nPos,"+%02X", bUCHAR );
463                       }
464
465                       if( bMod == 2 )
466                       {
467                           dwULONG = NEXTULONG;
468                           nPos += PICE_sprintf( pDis->szDisasm+nPos,"+%08X", (unsigned int) dwULONG );
469                       }
470
471                       // Wrap up the instruction
472                       nPos += PICE_sprintf( pDis->szDisasm+nPos,"]" );
473                       break;
474                  }
475
476                  //
477                  // 16 or 32 address bit cases with mod zero, one or two
478                  //
479                  // Special cases when r/m is 5 and mod is 0, immediate d16 or d32
480                  if( bMod==0 && ((bRm==6 && !(pDis->dwFlags & DIS_ADDRESS32)) || (bRm==5 && (pDis->dwFlags & DIS_ADDRESS32))) )
481                  {
482                       if( pDis->dwFlags & DIS_ADDRESS32 )
483                       {
484                           dwULONG = NEXTULONG;
485                           if(ScanExportsByAddress(&pSymbolName,dwULONG))
486                               nPos += PICE_sprintf( pDis->szDisasm+nPos,"[%s]", pSymbolName );
487                           else
488                               nPos += PICE_sprintf( pDis->szDisasm+nPos,"[%08X]", (unsigned int) dwULONG );
489                       }
490                       else
491                       {
492                           wUSHORT = NEXTUSHORT;
493                           nPos += PICE_sprintf( pDis->szDisasm+nPos,"[%04X]", wUSHORT );
494                       }
495
496                       break;
497                  }
498
499                  // Print the start of the line
500                  nPos += PICE_sprintf( pDis->szDisasm+nPos,"[%s", sAdr1[DIS_GETADDRSIZE(pDis->dwFlags)][ bRm ] );
501
502                  // Offset (8 or 16) or (8 or 32) bit - 16, 32 bits are unsigned
503                  if( bMod==1 )
504                  {
505                       bUCHAR = NEXTUCHAR;
506                       if( (signed char)bUCHAR < 0 )
507                              nPos += PICE_sprintf( pDis->szDisasm+nPos,"-%02X", 0-(signed char)bUCHAR );
508                       else
509                              nPos += PICE_sprintf( pDis->szDisasm+nPos,"+%02X", bUCHAR );
510                  }
511
512                  if( bMod==2 )
513                  {
514                       if( pDis->dwFlags & DIS_ADDRESS32 )
515                       {
516                           dwULONG = NEXTULONG;
517                           nPos += PICE_sprintf( pDis->szDisasm+nPos,"+%08X", (unsigned int) dwULONG );
518                       }
519                       else
520                       {
521                           wUSHORT = NEXTUSHORT;
522                           nPos += PICE_sprintf( pDis->szDisasm+nPos,"+%04X", wUSHORT );
523                       }
524                  }
525
526                  // Wrap up the instruction
527                  nPos += PICE_sprintf( pDis->szDisasm+nPos,"]" );
528
529              break;
530
531              case _Gb :                                         // general, UCHAR register
532                  nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s", sRegs1[0][0][ bReg ] );
533              break;
534
535              case _Gv :                                         // general, (d)USHORT register
536                  nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s", sGenReg16_32[DIS_GETDATASIZE(pDis->dwFlags)][ bReg ] );
537              break;
538
539              case _Yb :                                         // ES:(E)DI pointer
540              case _Yv :
541                  nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s%s", sSegOverrideDefaultES[ bSegOverride ], sYptr[DIS_GETADDRSIZE(pDis->dwFlags)] );
542              break;
543
544              case _Xb :                                         // DS:(E)SI pointer
545              case _Xv :
546                  nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s%s", sSegOverrideDefaultDS[ bSegOverride ], sXptr[DIS_GETADDRSIZE(pDis->dwFlags)] );
547              break;
548
549              case _Rd :                                         // general register double USHORT
550                  nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s", sGenReg16_32[ 1 ][ bRm ] );
551              break;
552
553              case _Rw :                                         // register USHORT
554                  nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s", sGenReg16_32[ 0 ][ bMod ] );
555              break;
556
557              case _Sw :                                         // segment register
558                  nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s", sSeg[ bReg ] );
559              break;
560
561              case _Cd :                                         // control register
562                  nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s", sControl[ bReg ] );
563              break;
564
565              case _Dd :                                         // debug register
566                  nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s", sDebug[ bReg ] );
567              break;
568
569              case _Td :                                         // test register
570                  nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s", sTest[ bReg ] );
571              break;
572
573
574              case _Jb :                                         // immediate UCHAR, relative offset
575                  bUCHAR = NEXTUCHAR;
576                  nPos += PICE_sprintf( pDis->szDisasm+nPos, "short %08X", (unsigned int)(pDis->bpTarget + (signed char)bUCHAR + bInstrLen) );
577              break;
578
579              case _Jv :                                         // immediate USHORT or ULONG, relative offset
580                  if( pDis->dwFlags & DIS_DATA32 )
581                  {
582                       dwULONG = NEXTULONG;
583                       if(ScanExportsByAddress(&pSymbolName,(unsigned int)(pDis->bpTarget + (signed long)dwULONG + bInstrLen)))
584                         nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s", pSymbolName );
585                       else
586                         nPos += PICE_sprintf( pDis->szDisasm+nPos, "%08X", (unsigned int)(pDis->bpTarget + (signed long)dwULONG + bInstrLen) );
587                  }
588                  else
589                  {
590                      wUSHORT = NEXTUSHORT;
591                      if(ScanExportsByAddress(&pSymbolName,(unsigned int)(pDis->bpTarget + (signed short)wUSHORT + bInstrLen)))
592                         nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s", pSymbolName );
593                      else
594                         nPos += PICE_sprintf( pDis->szDisasm+nPos, "%08X", (unsigned int)(pDis->bpTarget + (signed short)wUSHORT + bInstrLen) );
595                  }
596              break;
597
598              case _O  :                                         // Simple USHORT or ULONG offset
599                   if( pDis->dwFlags & DIS_ADDRESS32 )           // depending on the address size
600                   {
601                       dwULONG = NEXTULONG;
602                       nPos += PICE_sprintf( pDis->szDisasm+nPos,"%s[%08X]", sSegOverride[ bSegOverride ], (unsigned int) dwULONG );
603                   }
604                   else
605                   {
606                       wUSHORT = NEXTUSHORT;
607                       nPos += PICE_sprintf( pDis->szDisasm+nPos,"%s[%04X]", sSegOverride[ bSegOverride ], wUSHORT );
608                   }
609              break;
610
611              case _Ib :                                         // immediate UCHAR
612                  bUCHAR = NEXTUCHAR;
613                  nPos += PICE_sprintf( pDis->szDisasm+nPos,"%02X", bUCHAR );
614              break;
615
616              case _Iv :                                         // immediate USHORT or ULONG
617                  if( pDis->dwFlags & DIS_DATA32 )
618                  {
619                       dwULONG = NEXTULONG;
620                       nPos += PICE_sprintf( pDis->szDisasm+nPos, "%08X", (unsigned int) dwULONG );
621                  }
622                  else
623                  {
624                      wUSHORT = NEXTUSHORT;
625                      nPos += PICE_sprintf( pDis->szDisasm+nPos, "%04X", wUSHORT );
626                  }
627              break;
628
629              case _Iw :                                         // Immediate USHORT
630                  wUSHORT = NEXTUSHORT;
631                  nPos += PICE_sprintf( pDis->szDisasm+nPos, "%04X", wUSHORT );
632              break;
633
634              case _Ap :                                         // 32 bit or 48 bit pointer (call far, jump far)
635                  if( pDis->dwFlags & DIS_DATA32 )
636                  {
637                       dwULONG = NEXTULONG;
638                       wUSHORT = NEXTUSHORT;
639                       nPos += PICE_sprintf( pDis->szDisasm+nPos, "%04X:%08X", wUSHORT, (unsigned int) dwULONG );
640                  }
641                  else
642                  {
643                      dwULONG = NEXTULONG;
644                      nPos += PICE_sprintf( pDis->szDisasm+nPos, "%08X", (unsigned int) dwULONG );
645                  }
646              break;
647
648              case _1 :                                          // numerical 1
649                  nPos += PICE_sprintf( pDis->szDisasm+nPos,"1" );
650              break;
651
652              case _3 :                                          // numerical 3
653                  nPos += PICE_sprintf( pDis->szDisasm+nPos,"3" );
654              break;
655
656                                                                 // Hard coded registers
657              case _DX: case _AL: case _AH: case _BL: case _BH: case _CL: case _CH:
658              case _DL: case _DH: case _CS: case _DS: case _ES: case _SS: case _FS:
659              case _GS:
660                  nPos += PICE_sprintf( pDis->szDisasm+nPos,"%s", sRegs2[ *pArg - _DX ] );
661              break;
662
663              case _eAX: case _eBX: case _eCX: case _eDX:
664              case _eSP: case _eBP: case _eSI: case _eDI:
665                  nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s", sGenReg16_32[DIS_GETDATASIZE(pDis->dwFlags)][ *pArg - _eAX ]);
666              break;
667
668              case _ST:                                          // Coprocessor ST
669                 nPos += PICE_sprintf( pDis->szDisasm+nPos,"%s", sST[9] );
670              break;
671
672             case _ST0:                                         // Coprocessor ST(0) - ST(7)
673             case _ST1:
674             case _ST2:
675             case _ST3:
676             case _ST4:
677             case _ST5:
678             case _ST6:
679             case _ST7:
680                nPos += PICE_sprintf( pDis->szDisasm+nPos,"%s", sST[ *pArg - _ST0 ] );
681             break;
682
683             case _AX:                                           // Coprocessor AX
684                 nPos += PICE_sprintf( pDis->szDisasm+nPos,"%s", sGenReg16_32[0][0] );
685             break;
686         }
687     }
688
689 DisEnd:
690
691     // Set the returning values and return with the bInstrLen field
692
693     pDis->bAsciiLen = (UCHAR) nPos;
694     pDis->bInstrLen = bInstrLen;
695
696     return bInstrLen;
697 }
698
699 /******************************************************************************
700 *                                                                             *
701 *   BOOLEAN Disasm(PULONG pOffset,PUCHAR pchDst)                              *
702 *                                                                             *
703 *   entry point for disassembly from other modules                            *
704 ******************************************************************************/
705 BOOLEAN Disasm(PULONG pOffset,PUCHAR pchDst)
706 {
707     TDisassembler dis;
708  
709     dis.dwFlags  = DIS_DATA32 | DIS_ADDRESS32;
710     dis.bpTarget = (UCHAR*)*pOffset;
711     dis.szDisasm = pchDst;
712     dis.wSel = CurrentCS;
713
714     *pOffset += (ULONG)Disassembler( &dis);
715     return TRUE;
716 }