📄 disasm.cpp
字号:
/*
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 + -