?? disasm.cpp
字號:
#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;
Disasm->PrefixSize=PrefixesSize;
(*Index)+=4;
}
else if(RegPrefix==1) // RegPrefix is being used
{
// read 2 bytes into AX (REG16)
SwapWord((BYTE*)(Opcode+i+1),&wOp,&wMem);
wsprintf(menemonic,"%s %s, %04X",mene,Regs[REG16][0],wMem);
lstrcat(Disasm->Assembly,menemonic);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -