home *** CD-ROM | disk | FTP | other *** search
/ Windows Graphics Programming / Feng_Yuan_Win32_GDI_DirectX.iso / Samples / Chapt_04 / Patcher / DisAsm.cpp next >
Encoding:
C/C++ Source or Header  |  2000-05-11  |  6.8 KB  |  329 lines

  1. //-----------------------------------------------------------------------------------//
  2. //              Windows Graphics Programming: Win32 GDI and DirectDraw               //
  3. //                             ISBN  0-13-086985-6                                   //
  4. //                                                                                   //
  5. //  Written            by  Yuan, Feng                             www.fengyuan.com   //
  6. //  Copyright (c) 2000 by  Hewlett-Packard Company                www.hp.com         //
  7. //  Published          by  Prentice Hall PTR, Prentice-Hall, Inc. www.phptr.com      //
  8. //                                                                                   //
  9. //  FileName   : disasm.cpp                                                             //
  10. //  Description: Intel machine code parser                                            //
  11. //  Version    : 1.00.000, May 31, 2000                                              //
  12. //-----------------------------------------------------------------------------------//
  13.  
  14. #define STRICT
  15. #define WIN32_LEAN_AND_MEAN
  16.  
  17. #include <windows.h>
  18. #include <assert.h>
  19.  
  20. #include "DisAsm.h"
  21. #include "OpCode.h"
  22.  
  23. KDisAsm::KDisAsm()
  24. {
  25.  
  26. }
  27.  
  28. KDisAsm::~KDisAsm()
  29. {
  30.  
  31. }
  32.  
  33.  
  34. #define case4(a, b, c, d) case a: case b: case c: case d
  35.  
  36.  
  37. int KDisAsm::OperandLen(const OpCode * map, unsigned opcode, int opndsize, int & modrm)
  38. {
  39.     int datalen = 0;
  40.  
  41.     for (int i=0; i<3; i++) 
  42.         if (map[opcode].opnd[i] != 0)
  43.         {
  44.             unsigned data = map[opcode].opnd[i];
  45.  
  46.             assert ( (data>_before_operand) && (data<_after_operand) );
  47.  
  48.             switch ( data )
  49.             {
  50.                 case 1:
  51.                 case _DX:
  52. //                case _eA:
  53.                     
  54.                 case4(_AL, _BL, _CL, _DL):    
  55.                 case4(_AH, _BH, _CH, _DH):
  56.                 case4(_EAX,_EBX,_ECX,_EDX):
  57.                 case4(_ESP,_EBP,_ESI,_EDI):
  58.                 case4(_eAX,_eBX,_eCX,_eDX):
  59.  
  60.                 case4(_eSP,_eBP,_eSI,_eDI):
  61.                 case4(_DS, _CS, _SS, _ES):
  62.                 case _FS:
  63.                 case _GS:
  64.  
  65.                 case _Xv:
  66.                 case _Yv:
  67.                 case _Yb:
  68.                 case _Xb:
  69.                 case _Fv:
  70.                 case _M :
  71.                     break;
  72.  
  73.                 case _Mp:
  74.                 case _Ap: datalen += 2 + opndsize; break;
  75.                 
  76.                 case _Av: datalen += opndsize; break;
  77.     
  78.                 case _Ep: datalen += 2 + opndsize; 
  79.                           modrm = 1; break;
  80.                     
  81.                 case _Cd:
  82.                 case _Dd:
  83.                 case _Dx:
  84.                 case _Ed:
  85.                 case _Ev:
  86.                 case _Eb:
  87.                 case _Ew:
  88.                 case _Eq:
  89.                 case _Gb:
  90.                 case _Gv:
  91.                 case _Gw: 
  92.                 case _Pd:
  93.                 case _Pq:
  94.                 case _Qd:
  95.                 case _Qq:
  96.                 case _Rd:
  97.                 case _Rw:
  98.                 case _Sw:
  99.                     modrm = 1; break; // modR/M
  100.                     break;
  101.     
  102.                 case _Ob:
  103.                 case _Ib: datalen ++;   break;
  104.  
  105.                 case _Jb: MessageBox(NULL, m_funcname, "Relative Instructions", MB_OK);
  106.                           m_error = true;
  107.                           datalen ++;   break;
  108.  
  109.                 case _Iw: datalen += 2; break;
  110.     
  111.                 case _Ov:
  112.                 case _Iv: datalen += opndsize; break;
  113.  
  114.                 case _Jv: MessageBox(NULL, m_funcname, "Relative Instructions", MB_OK);
  115.                           m_error = true;
  116.                           datalen += opndsize; break;
  117.  
  118.                 case _Ms: datalen = 6;              break;
  119.                 case _Ma: datalen = opndsize * 2; break;
  120.  
  121.                 case _BMq:                    
  122.                 default :
  123.                     assert(false);
  124.             }
  125.         }
  126.  
  127.     return datalen;
  128. }
  129.  
  130.  
  131. int KDisAsm::Length(const unsigned char * code, const char * funcname)
  132. {
  133.     m_error    = false;
  134.     m_funcname = funcname;
  135.  
  136.     int addr32 = true;
  137.     int opnd32 = true;
  138.     int len    = 0;
  139.  
  140.     unsigned b  = code[len++];
  141.     unsigned op = OpCodeMap[b].opcode;
  142.  
  143.     // instruction prefix
  144.     if ( (op==_LOCK) || (op==_REPNE) || (op==_REP) )
  145.     {
  146.         b  = code[len++];
  147.         op = OpCodeMap[b].opcode;
  148.     }
  149.  
  150.     // address prefix
  151.     if ( op==_ADDRSIZE )
  152.     {
  153.         addr32 = ! addr32;
  154.         
  155.         b  = code[len++];
  156.         op = OpCodeMap[b].opcode;
  157.     }
  158.  
  159.     // operand prefix
  160.     if ( op==_OPNDSIZE )
  161.     {
  162.         opnd32 = ! opnd32;
  163.         
  164.         b  = code[len++];
  165.         op = OpCodeMap[b].opcode;
  166.     }
  167.  
  168.     // segment override
  169.     if ( op == _SEG )
  170.     {
  171.         b  = code[len++];
  172.         op = OpCodeMap[b].opcode;
  173.     }
  174.  
  175.     const OpCode * Map = OpCodeMap;
  176.  
  177.     if ( op == _ESCAPE_0F )
  178.     {
  179.         b   = code[len++];
  180.         Map = OpCodeMap_0F;
  181.         op  = Map[b].opcode;
  182.     }
  183.  
  184.     int               hasmodrm = 0;
  185.     unsigned char  modrm    = code[len];
  186.  
  187.     if ( (op>_before_instruction) && (op<_after_instruction) )
  188.     {
  189.         len += OperandLen(Map, b, 2 + 2 * opnd32, hasmodrm);
  190.     }
  191.     else 
  192.     {
  193.         len += OperandLen(Map, b, 2 + 2 * opnd32, hasmodrm);
  194.  
  195.         switch ( op )
  196.         {
  197.             case _Grp1: 
  198.                 hasmodrm = 1; 
  199.                 len+= OperandLen(OpCodeMap_Grp1, (code[len] >> 3) & 7, 2 + 2 * opnd32, hasmodrm);
  200.                 break;
  201.  
  202.             case _Grp2: 
  203.                 hasmodrm = 1; 
  204.                 len+= OperandLen(OpCodeMap_Grp2, (code[len] >> 3) & 7, 2 + 2 * opnd32, hasmodrm);
  205.                 break;
  206.  
  207.             case _Grp3b: 
  208.                 hasmodrm = 1; 
  209.                 len+= OperandLen(OpCodeMap_Grp3b, (code[len] >> 3) & 7, 2 + 2 * opnd32, hasmodrm);
  210.                 break;
  211.  
  212.             case _Grp3v: 
  213.                 hasmodrm = 1; 
  214.                 len+= OperandLen(OpCodeMap_Grp3v, (code[len] >> 3) & 7, 2 + 2 * opnd32, hasmodrm);
  215.                 break;
  216.  
  217.             case _Grp4: 
  218.                 hasmodrm = 1; 
  219.                   len+= OperandLen(OpCodeMap_Grp4, (code[len] >> 3) & 7, 2 + 2 * opnd32, hasmodrm);
  220.                 break;
  221.  
  222.             case _Grp5: 
  223.                 hasmodrm = 1; 
  224.                   len+= OperandLen(OpCodeMap_Grp5, (code[len] >> 3) & 7, 2 + 2 * opnd32, hasmodrm);
  225.                 break;
  226.  
  227.             case _Grp6: 
  228.                 hasmodrm = 1; 
  229.                 len+= OperandLen(OpCodeMap_Grp6, (code[len] >> 3) & 7, 2 + 2 * opnd32, hasmodrm);
  230.                 break;
  231.  
  232.             case _Grp7: 
  233.                 hasmodrm = 1; 
  234.                 len+= OperandLen(OpCodeMap_Grp7, (code[len] >> 3) & 7, 2 + 2 * opnd32, hasmodrm);
  235.                 break;
  236.  
  237.             case _Grp8: 
  238.                 hasmodrm = 1; 
  239.                 len+= OperandLen(OpCodeMap_Grp8, (code[len] >> 3) & 7, 2 + 2 * opnd32, hasmodrm);
  240.                 break;
  241.  
  242.             case _Grp9: 
  243.                 hasmodrm = 1; 
  244.                 len+= OperandLen(OpCodeMap_Grp9, (code[len] >> 3) & 7, 2 + 2 * opnd32, hasmodrm);
  245.                 break;
  246.  
  247.             case _GrpA: 
  248.                 hasmodrm = 1; 
  249.                 len+= OperandLen(OpCodeMap_GrpA, (code[len] >> 3) & 7, 2 + 2 * opnd32, hasmodrm);
  250.                 break;
  251.  
  252.             default:
  253.                 assert(false);
  254.         }
  255.     }
  256.  
  257.     if ( hasmodrm )
  258.     {
  259.         int mod = (modrm >> 6) & 3;
  260.         int r_m = modrm & 7;
  261.  
  262.         if ( addr32 )
  263.         {
  264.             switch ( mod )
  265.             {
  266.                 case 0:
  267.                     if (r_m==4) len ++;        // sib
  268.                     if (r_m==5) len+=4;    // disp32
  269.                     break;
  270.  
  271.                 case 1:
  272.                     len++;                    // disp8
  273.                     if (r_m==4) len++;        // sib
  274.                     break;
  275.  
  276.                 case 2:
  277.                     len+=4;                    // disp32
  278.                     if (r_m==4) len++;        // sib
  279.             }
  280.         }
  281.         else
  282.         {
  283.             switch ( mod )
  284.             {
  285.                 case 0: 
  286.                     if (r_m==6) len += 2;    // disp16
  287.                     break;
  288.  
  289.                 case 1:
  290.                     len += 1;                // disp8
  291.                     break;
  292.  
  293.                 case 2:
  294.                     len += 2;                // disp16
  295.                     break;
  296.             }
  297.         }
  298.     }
  299.  
  300.     if ( m_error )
  301.         return 0;
  302.  
  303.     return len + hasmodrm;
  304. }
  305.  
  306.  
  307. KDisAsm    dis;
  308.  
  309.  
  310. int First5(const unsigned char * pProc, const char * funcname)
  311. {
  312.     if ( pProc==NULL )
  313.         return 0;
  314.  
  315.     int total = 0;
  316.     while ( total < 5 )
  317.     {
  318.         int len = dis.Length(pProc, funcname);
  319.  
  320.         if ( len==0 )
  321.             return 0;
  322.  
  323.         pProc += len;
  324.         total += len;
  325.     }
  326.  
  327.     return total;
  328. }
  329.