⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 disasm.cpp

📁 Pvdasm.v1.04b反汇编程序的源代码.供研究反汇编技术的朋友参考
💻 CPP
📖 第 1 页 / 共 4 页
字号:
 
/*
     8888888b.                  888     888 d8b                        
     888   Y88b                 888     888 Y8P                        
     888    888                 888     888                            
     888   d88P 888d888  .d88b. Y88b   d88P 888  .d88b.  888  888  888 
     8888888P"  888P"   d88""88b Y88b d88P  888 d8P  Y8b 888  888  888 
     888        888     888  888  Y88o88P   888 88888888 888  888  888 
     888        888     Y88..88P   Y888P    888 Y8b.     Y88b 888 d88P 
     888        888      "Y88P"     Y8P     888  "Y8888   "Y8888888P"  


                        Dissasembler Engine Core
                        ~~~~~~~~~~~~~~~~~~~~~~~~

 Written by Bengaly (R) 2003-2005.
 As a part of the Proview (a.k.a PVDasm).
 Permission is granted to make and distribute verbatim copies of this
 Program provided the copyright notice and this permission notice are
 Preserved on all copies.

 File: Disasm.cpp (main)

 Disassembler Core Version: 1.04b
*/  
 
#include "Disasm.h"
#define BYTES_TO_DECODE 16

const char *Regs[3][9] = {
    {"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"},
    {"ax", "cx", "dx", "bx", "sp", "bp", "si", "di"},
    {"eax","ecx","edx","ebx","esp","ebp","esi","edi"} 
};

const char *RegSize[4] = {"Qword","Dword","Word","Byte"};
const char *Segs[8]    = {"ES","CS","SS","DS","FS","GS","SEG?","SEG?"};

void Decode(DISASSEMBLY *Disasm,char *Opcode,DWORD *Index)
{
	/*
	  This function is the Main decoding rutine.
	  The function gets 3 params:
	  1. DISASSEMBLY struct pointer
	  2. Opcode pointer, point to the linear address to decode
	  3. Index pointer, this is the distance from the beginning<>end of the linear

	  The function First searches for Prefixes + Repeated prefixes,
	  This is the first step to do in any disasm engine.
	  Prefixes determine behavior of instruction and the way they
	  Are decoded.
	  Once prefies has been found, we changes params (such as default r/m size, Lock..)

	  The function than searched for the byte to be decoded, the actual
	  Menemonic referenced in CPU form (Opcode),
	  I have not used big table - time prob -, although it is highly recomended! (hopefully in future)
    */

	// intializations
    DWORD dwMem=0,dwOp=0;
    int  i=*Index,RegRepeat=0,LockRepeat=0,SegRepeat=0,RepRepeat=0,AddrRepeat=0; // Repeated Prefixes    
	int  RM=REG32,SEG=SEG_DS,ADDRM=REG32;       // default modes	
	int PrefixesSize=0,PrefixesRSize=0;         // PrefixesSize = all Prefixes(no rep), PrefixesRsize (with Rep Prefix)
    WORD wMem=0,wOp=0;    
    bool RegPrefix=0,LockPrefix=0,SegPrefix=0,RepPrefix=0,AddrPrefix=0;  // default size of Prefixes
    BYTE Bit_D=0, Bit_W=0; // bit d/w for R/M
	char menemonic[256]="";
    char RSize[10]="Dword";                     // default size of menemonic
    BYTE Op=(BYTE)Opcode[i];                    // current opcode
    


    //=======================================================
    //               Decoding Prefixes                     //
    //=======================================================

    // we first assume there is prefix !
	// if we skip this, our decoding might be currupted

	while( // check only RegPreifix/LockProfix/SegPrefixes/RepPrefix/AddrPerfix
		   (Op==0x66) || (Op==0x0F0)|| (Op==0x2E) || (Op==0x36) ||
		   (Op==0x3E) || (Op==0x26) || (Op==0x64) || (Op==0x65) || 
		   (Op==0xF2) || (Op==0xF3) || (Op==0x67)
		 ) 
	{
		switch(Op)
		{
			case 0x66: // reg prefix, change default size, dword->word
			{                   
				RM=REG16; // 66 prefix, change default size
				RegPrefix=1; 
				BYTE temp;
				wsprintf(RSize,"%s",RegSize[2]); // change default size of menemonic to 'Word'
				//LockPrefix=0;
				lstrcat(Disasm->Opcode,"66:");
				i++;
				++(*Index);
				Op=(BYTE)Opcode[i];
				temp=(BYTE)Opcode[i+1];
				RegRepeat++;
				if(RegRepeat>1) 
				{
					strcpy(Disasm->Opcode,"66:");
					strcpy(Disasm->Remarks,"Prefix DataSize:");
					Disasm->OpcodeSize=1;
					Disasm->PrefixSize=0;
					(*Index)-=RegRepeat;
					return;
				}
			}
			break;

			case 0x67: // Addr prefix, change default Reg size, (EDI->DI) and more!
			{
				ADDRM=REG16; // 67 prefix, change default size, in this case: Memory Reg Size
				AddrPrefix=1; 
				BYTE temp;
				lstrcat(Disasm->Opcode,"67:");
				i++;
				++(*Index);
				Op=(BYTE)Opcode[i];
				temp=(BYTE)Opcode[i+1];
				AddrRepeat++;
				if(AddrRepeat>1) 
				{
					strcpy(Disasm->Opcode,"67:");
					strcpy(Disasm->Remarks,"Prefix AddrSize:");
					Disasm->OpcodeSize=1;
					Disasm->PrefixSize=0;
					(*Index)-=AddrRepeat;
					return;
				}
			}
			break;

			case 0x0F0: // LockPrefix, Add bus lock menemonic opcode in front of every menemonic
			{
				//BYTE temp;
				LockPrefix=1;
				//RegPrefix=0; 
				lstrcat(Disasm->Opcode,"F0:");
				strcpy(Disasm->Assembly,"lock ");
				i++;
				++(*Index);
				Op=(BYTE)Opcode[i];
				//temp=(BYTE)Opcode[i+1];
				LockRepeat++;
				if(LockRepeat>1) 
				{
					strcpy(Disasm->Assembly,"");
					strcpy(Disasm->Opcode,"F0:");
					strcpy(Disasm->Remarks,"Prefix LOCK:");
					Disasm->OpcodeSize=1;
					Disasm->PrefixSize=0;
					(*Index)-=LockRepeat;
					return;
				}
			}
			break;

			case 0xF2: case 0xF3: // RepPrefix (only string instruction!!)
			{
                BYTE NextOp=(BYTE)Opcode[i+1];              // Next followed opcode
                BYTE NextOp2=(BYTE)Opcode[i+2];
				RepPrefix=1;
				wsprintf(menemonic,"%02X:",Op);
				lstrcat(Disasm->Opcode,menemonic);
				switch(Op)
				{
					case 0xF2:wsprintf(menemonic,"repne ");break;
					case 0xF3:wsprintf(menemonic,"repe ");break;
				}
				lstrcat(Disasm->Assembly,menemonic);
				i++;
				++(*Index);
				Op=(BYTE)Opcode[i];
				RepRepeat++;
				// REPE/REPNE Prefixes affect only string operations:
				// MOVS/LODS/SCAS/CMPS/STOS/CMPSS.CMPPS..etc (NewSet Instructions)
				if(!( 
                      (Op>=0xA4 && Op<=0xA7) || 
                      (Op>=0xAA && Op<=0xAF) || 
                      (NextOp==0x0F && NextOp2==0x2A) ||
                      (NextOp==0x0F && NextOp2==0x10) ||
                      (NextOp==0x0F && NextOp2==0x11) ||
                      (NextOp==0x0F && NextOp2==0x2C) ||
                      (NextOp==0x0F && NextOp2==0x2D) ||
                      (NextOp==0x0F && NextOp2==0x51) ||
                      (NextOp==0x0F && NextOp2==0x52) ||
                      (NextOp==0x0F && NextOp2==0x53) ||
                      (NextOp==0x0F && NextOp2==0x58) ||
                      (NextOp==0x0F && NextOp2==0x59) ||
                      (NextOp==0x0F && NextOp2==0x5C) ||
                      (NextOp==0x0F && NextOp2==0x5D) ||
                      (NextOp==0x0F && NextOp2==0x5E) ||
                      (NextOp==0x0F && NextOp2==0x5F) ||
                      (NextOp==0x0F && NextOp2==0xC2) 
                    )
                  )
				{
					strcpy(Disasm->Assembly,"");
					strcpy(Disasm->Remarks,"Prefix REP:");
					Disasm->OpcodeSize=1;
					Disasm->PrefixSize=0;
					(*Index)-=RepRepeat;
					return;
				}
					
			}
			break;

			case 0x2E: case 0x36: // Segment Prefixes
			case 0x3E: case 0x26: // Segment Prefixes
			case 0x64: case 0x65: // Segment Prefixes
			{
				BYTE temp;
				switch(Op)
				{
					// Change Default Segment
					case 0x2E: SEG = SEG_CS; break; // Segment CS
					case 0x36: SEG = SEG_SS; break; // Segment SS
					case 0x3E: SEG = SEG_DS; break; // Segment DS
					case 0x26: SEG = SEG_ES; break; // Segment ES
					case 0x64: SEG = SEG_FS; break; // Segment FS
					case 0x65: SEG = SEG_GS; break; // Segment GS
				}

				SegPrefix=1;
				wsprintf(menemonic,"%02X:",Op);
				lstrcat(Disasm->Opcode,menemonic);
				i++;
				++(*Index);
				Op=(BYTE)Opcode[i];
				temp=(BYTE)Opcode[i-2];
				SegRepeat++;

				// Check if SegPrefix is repeating
				if(SegRepeat>1) 
				{                    
					BYTE opc=(BYTE)Opcode[i-1];

					if(  temp==0x2E || temp==0x36 ||
					     temp==0x3E || temp==0x26 ||
                         temp==0x64 || temp==0x65 ||
                         temp==0x66 || temp==0xF0 ||
                         temp==0x67                        
					  )
					{
						// Check if last byte was an seg prefix and show it
						if(temp==0x66 || temp==0xF0 || temp==0x67)
                        {
                           opc=(BYTE)Opcode[i-3];
                           SegRepeat++;
                        }
                        else
                           opc=(BYTE)Opcode[i-2];

						switch(opc)
						{
							// Change Segment, accurding to last segPrefix (if repeated)
							case 0x2E: SEG = SEG_CS; break; // Segment CS
							case 0x36: SEG = SEG_SS; break; // Segment SS
							case 0x3E: SEG = SEG_DS; break; // Segment DS
							case 0x26: SEG = SEG_ES; break; // Segment ES
							case 0x64: SEG = SEG_FS; break; // Segment FS
							case 0x65: SEG = SEG_GS; break; // Segment GS
						}
					

                        strcpy(Disasm->Assembly,"");
                        wsprintf(menemonic,"%02X:",opc);
                        strcpy(Disasm->Opcode,menemonic);
                        wsprintf(menemonic,"Prefix %s:",Segs[SEG]);
                        strcpy(Disasm->Remarks,menemonic);
                        Disasm->OpcodeSize=0;
                        Disasm->PrefixSize=1;
                        (*Index)-=SegRepeat;
                    }
					return;
				}
			}
			break;
			
		    default:
			{
				// reset prefixes/repeats to default
				LockRepeat=0;
				RegRepeat=0;
				SegRepeat=0;
				RegPrefix=0;
				LockPrefix=0;
				SegPrefix=0;
				strcpy(RSize,RegSize[1]); // Default size
			}
			break;
		}
	}

    
	//=============================================
	//        Main Decoding starts here!         //
	//=============================================

	// Calculate Prefixes Sizes
	PrefixesSize  = RegPrefix+LockPrefix+SegPrefix+AddrPrefix; // No RepPrefix
	PrefixesRSize = PrefixesSize+RepPrefix; // Special Case (Rep Prefix is being used -> String menemonics only)

    switch(Op) // Find & Decode Big Set Opcodes
    {
		case 0x00: case 0x01: case 0x02: case 0x03: // ADD  XX/XXX, XX/XXX
		case 0x08: case 0x09: case 0x0A: case 0x0B: // OR   XX/XXX, XX/XXX
		case 0x10: case 0x11: case 0x12: case 0x13: // ADC  XX/XXX, XX/XXX 
		case 0x18: case 0x19: case 0x1A: case 0x1B: // SBB  XX/XXX, XX/XXX 
		case 0x20: case 0x21: case 0x22: case 0x23: // AND  XX/XXX, XX/XXX 
		case 0x28: case 0x29: case 0x2A: case 0x2B: // SUB  XX/XXX, XX/XXX 
		case 0x30: case 0x31: case 0x32: case 0x33: // XOR  XX/XXX, XX/XXX 
		case 0x38: case 0x39: case 0x3A: case 0x3B: // CMP  XX/XXX, XX/XXX 
        case 0x88: case 0x89: case 0x8A: case 0x8B: // MOV  XX/XXX, XX/XXX 
        case 0x8C: case 0x8E:                       // MOV  XX/XXX, XX/XXX
		case 0x62: case 0x63:                       // BOUND / ARPL XX/XXX, XX/XXX
        case 0x69:                                  // IMUL RM,IIM32 (DWORD)
        case 0x6B:                                  // IMUL <reg>,<RM>
		case 0x80: case 0x81: case 0x82: case 0x83: // MIXED Instructions
		case 0x84: case 0x85:                       // TEST
		case 0x86: case 0x87:                       // XCHG
        case 0x8D:                                  // LEA 
        case 0x8F:                                  // POP
        case 0xC0: case 0xC1:                       // MIXED Instructions
        case 0xC4: case 0xC5:                       // LES / LDS REG,MEM
        case 0xC6: case 0xC7:                       // MOV [MEM],IIM8/16/32
        case 0xD0: case 0xD1: case 0xD2: case 0xD3: // MIXED Bitwise Instructions
        case 0xD8: case 0xD9: case 0xDA: case 0xDB: // FPU Instructions
        case 0xDC: case 0xDD: case 0xDE: case 0xDF: // FPU Instructions
        case 0xF6: case 0xF7: case 0xFE: case 0xFF: // MIX Instructions
        {
			if(((BYTE)Opcode[i+1] & 0xC0)==0xC0)   // Check Opcode Range
			{
				char mene[10]="";
				
				GetInstruction(Op,mene); // Get instruction from Opcode Byte
				Bit_D=(Op&0x02)>>1;      // Get bit d (direction)
				Bit_W=(Op&0x01);         // Get bit w (full/partial reg size)
				
				// Check Special Cases for alone Opcodes
				switch(Op)
				{
                    case 0x63:{Bit_D=0;Bit_W=1;}               break;
                    case 0x62:{Bit_D=1;Bit_W=1;}               break;
                    case 0x86:{Bit_D=0;Bit_W=0;}               break;
                    case 0x87:{Bit_D=0;Bit_W=1;}               break;
                    case 0x80: case 0x82: { Bit_D=0;Bit_W=0; } break;
                    case 0x81: case 0x83: { Bit_D=0;Bit_W=1; } break;
                    case 0x8C:{ Bit_D=0;Bit_W=0;}              break;
                    case 0x8E:{ Bit_D=1;Bit_W=0;}              break;
                    case 0xC4: case 0xC5: { Bit_D=1;Bit_W=1; } break;
				}

				Mod_11_RM(Bit_D,Bit_W,&Opcode,&Disasm,mene,RegPrefix,Op,&Index); // Decode with bits
				Disasm->PrefixSize=PrefixesSize; // PrefixSize (if prefix present)				
				break;
			}
			
			// operand doesn't have byte(s) extension in addressing mode
			if((BYTE)Opcode[i+1]>=0x00 && (BYTE)Opcode[i+1]<=0xBF)
			{
				char mene[10]="";
				GetInstruction(Op,mene); // Get instruction from Opcode Byte
				Bit_D=(Op&0x02)>>1;      // Get bit d (direction)
				Bit_W=(Op&0x01);         // Get bit w (full/partial reg size)
				Mod_RM_SIB(&Disasm,&Opcode,i,AddrPrefix,SEG,&Index,Bit_D,Bit_W,mene,Op,RegPrefix,SegPrefix,AddrPrefix);
				Disasm->PrefixSize=PrefixesSize;
				break;
			}	  				
		}
		break;

		case 0x04:case 0x0C:case 0x14: // INSTRUCTION AL,XX
		case 0x1C:case 0x24:case 0x2C: // INSTRUCTION AL,XX
        case 0x34:case 0x3C:case 0xA8: // INSTRUCTION AL,XX
		case 0xE4:
        {
			char mene[10]="";
			GetInstruction(Op,mene); // Get instruction for a specified Byte
            wsprintf(menemonic,"%s al, %02X",mene,(BYTE)Opcode[i+1]);
            lstrcat(Disasm->Assembly,menemonic);
            strcpy(Disasm->Remarks,"");
            wsprintf(menemonic,"%02X%02X",Op,(BYTE)*(Opcode+i+1));
            lstrcat(Disasm->Opcode,menemonic);
            Disasm->OpcodeSize=2;
			Disasm->PrefixSize=PrefixesSize;
            ++(*Index);
        }
        break;

        case 0x05:case 0x0D:case 0x15: // INSTRUCTION EAX/AX,XXXXXXXX
        case 0x1D:case 0x25:case 0x2D: // INSTRUCTION EAX/AX,XXXXXXXX
		case 0x35:case 0x3D:case 0xA9: // INSTRUCTION EAX/AX,XXXXXXXX
        {
			char mene[10]="";
			GetInstruction(Op,mene); // Get instruction for a specified Byte

			if(RegPrefix==0) // no prefix
			{   
				// read 4 bytes into EAX
				SwapDword((BYTE*)(Opcode+i+1),&dwOp,&dwMem);
                wsprintf(menemonic,"%s %s, %08X",mene,Regs[REG32][0],dwMem);
				lstrcat(Disasm->Assembly,menemonic);
				wsprintf(menemonic,"%02X %08X",Op,dwOp);
				lstrcat(Disasm->Opcode,menemonic);
				Disasm->OpcodeSize=5;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -