📄 disassemble.c
字号:
#include "disassemble.h"
const char *RepeatPrefixes[] = {"lock", "rep", "repe", "repz", "repne", "repnz"};
const char *AddressPrefixes[] = {"qword", "fword", "dword", "word", "byte"};
const char *SegmentRegisters[] = {"es", "cs", "ss", "ds", "fs", "gs"};
const char *Register32[] = {"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"};
const char *Register16[] = {"ax", "cx", "dx", "bx", "sp", "bp", "si", "di"};
const char *Register8[] = {"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"};
const char *Address16[] = {"bx+si", "bx+di", "bp+si", "bp+di", "si", "di", "bp", "bx"};
const char *ArithmeticMnemonic[] = {"add", "or", "adc", "sbb", "and", "sub", "xor", "cmp" };
const char *BCDAdjustMnemonic[] = {"daa", "das", "aaa", "aas", "aam", "aad"};
const char *JxxxMnemonic[] = {"jo", "jb", "jz", "jbe", "js", "jp", "jl", "jle"};
const char *JnxxMnemonic[] = {"jno", "jnb", "jnz", "ja", "jns", "jnp", "jge", "jg"};
const char *StrMnemonic[] = {"", "", "movs", "cmps", "", "stos", "lods", "scas"};
const char *LogicalShiftMnemonic[] = {"rol", "ror", "rcl", "rcr", "shl", "shr", "sal", "sar"};
const char *LoopMnemonic[] = {"loopnz", "loopz", "loop"};
const char *LogicalArithmeticMnemonic[] = {"test", "???", "not", "neg", "mul", "imul", "div", "idiv"};
const char *FlagMnemonic[] = {"clc", "stc", "cli", "sti", "cld", "std"};
const char *FFOpcodeMnemonic[] = {"inc", "dec", "call", "call", "jmp", "jmp", "push"};
const char *SetxxxMnemonic[] = {"seto", "setb", "sete", "setbe", "sets", "setpe", "setl", "setle"};
const char *SetnxxMnemonic[] = {"setno", "setnb", "setne", "seta", "setns", "setpo", "setge", "setg"};
const char *BTMnemonic[] = {"bt", "bts", "btr", "btc"};
unsigned char *Disassemble(unsigned int LinearAddress, unsigned char *Code, PINSTRUCTION Instruction, char *InstructionStr)
{
char prefix[MAX_OPERAND_LEN] = "";
char mnemonic[MAX_MNEMONIC_LEN] = "";
char operand1[MAX_OPERAND_LEN] = "";
char operand2[MAX_OPERAND_LEN] = "";
char operand3[MAX_OPERAND_LEN] = "";
unsigned char *currentCode;
char prefixFlag;
currentCode = Code;
prefixFlag = 0;
/* initialize Instrction structure */
Instruction->RepeatPrefix = -1;
Instruction->SegmentPrefix = -1;
Instruction->OperandPrefix = -1;
Instruction->AddressPrefix = -1;
Instruction->Opcode = -1;
Instruction->ModRM = -1;
Instruction->SIB = -1;
Instruction->Displacement = -1;
Instruction->Immediate = -1;
Instruction->dFlag = Instruction->wFlag = Instruction->sFlag = -1;
Instruction->LinearAddress = LinearAddress;
/* check PREFIXES and save the values, note that prefixes in the same group can only appear once */
/* and the values assigned to xxxxPrefix in Instruction structure are the indexes of the names */
/* in corresponding name tables */
while(*currentCode == 0xF0 || *currentCode == 0xF2 || *currentCode == 0xF3 ||
*currentCode == 0x2E || *currentCode == 0x36 || *currentCode == 0x3E ||
*currentCode == 0x26 || *currentCode == 0x64 || *currentCode == 0x65 ||
*currentCode == 0x66 || *currentCode == 0x67)
{
switch(*currentCode)
{
/* group1: lock and repeat prefixes */
case 0xF0 :
{
if(prefixFlag)
{
strcpy(InstructionStr, "prefix lock:");
currentCode++;
return currentCode;
}
else
{
/* rescan */
if(Instruction->RepeatPrefix >= 0)
{
currentCode = Code;
prefixFlag = 1;
}
else
{
Instruction->RepeatPrefix = 0;
currentCode++;
}
}
break;
}
case 0xF2 :
{
if(prefixFlag)
{
strcpy(InstructionStr, "prefix repnz:");
currentCode++;
return currentCode;
}
else
{
/* rescan */
if(Instruction->RepeatPrefix >= 0)
{
currentCode = Code;
prefixFlag = 1;
}
else
{
Instruction->RepeatPrefix = 5;
currentCode++;
}
}
break;
}
case 0xF3 :
{
if(prefixFlag)
{
strcpy(InstructionStr, "prefix rep:");
currentCode++;
return currentCode;
}
else
{
/* rescan */
if(Instruction->RepeatPrefix >= 0)
{
currentCode = Code;
prefixFlag = 1;
}
else
{
Instruction->RepeatPrefix = 1;
currentCode++;
}
}
break;
}
/* group2: segment override prefixes */
case 0x2E :
{
if(prefixFlag)
{
strcpy(InstructionStr, "prefix cs:");
currentCode++;
return currentCode;
}
else
{
/* rescan */
if(Instruction->SegmentPrefix >= 0)
{
currentCode = Code;
prefixFlag = 1;
}
else
{
Instruction->SegmentPrefix = 1;
currentCode++;
}
}
break;
}
case 0x36 :
{
if(prefixFlag)
{
strcpy(InstructionStr, "prefix ss:");
currentCode++;
return currentCode;
}
else
{
/* rescan */
if(Instruction->SegmentPrefix >= 0)
{
currentCode = Code;
prefixFlag = 1;
}
else
{
Instruction->SegmentPrefix = 2;
currentCode++;
}
}
break;
}
case 0x3E :
{
if(prefixFlag)
{
strcpy(InstructionStr, "prefix ds:");
currentCode++;
return currentCode;
}
else
{
/* rescan */
if(Instruction->SegmentPrefix >= 0)
{
currentCode = Code;
prefixFlag = 1;
}
else
{
Instruction->SegmentPrefix = 3;
currentCode++;
}
}
break;
}
case 0x26 :
{
if(prefixFlag)
{
strcpy(InstructionStr, "prefix es:");
currentCode++;
return currentCode;
}
else
{
/* rescan */
if(Instruction->SegmentPrefix >= 0)
{
currentCode = Code;
prefixFlag = 1;
}
else
{
Instruction->SegmentPrefix = 0;
currentCode++;
}
}
break;
}
case 0x64 :
{
if(prefixFlag)
{
strcpy(InstructionStr, "prefix fs:");
currentCode++;
return currentCode;
}
else
{
/* rescan */
if(Instruction->SegmentPrefix >= 0)
{
currentCode = Code;
prefixFlag = 1;
}
else
{
Instruction->SegmentPrefix = 4;
currentCode++;
}
}
break;
}
case 0x65 :
{
if(prefixFlag)
{
strcpy(InstructionStr, "prefix gs:");
currentCode++;
return currentCode;
}
else
{
/* rescan */
if(Instruction->SegmentPrefix >= 0)
{
currentCode = Code;
prefixFlag = 1;
}
else
{
Instruction->SegmentPrefix = 5;
currentCode++;
}
}
break;
}
/* group3: Operand-size override prefixes */
case 0x66 :
{
if(prefixFlag)
{
strcpy(InstructionStr, "prefix datasize:");
currentCode++;
return currentCode;
}
else
{
/* rescan */
if(Instruction->OperandPrefix >= 0)
{
currentCode = Code;
prefixFlag = 1;
}
else
{
Instruction->OperandPrefix = 0;
currentCode++;
}
}
break;
}
/* group4: Address-size override prefixes */
case 0x67 :
{
if(prefixFlag)
{
strcpy(InstructionStr, "prefix addrsize:");
currentCode++;
return currentCode;
}
else
{
/* rescan */
if(Instruction->AddressPrefix >= 0)
{
currentCode = Code;
prefixFlag = 1;
}
else
{
Instruction->AddressPrefix = 0;
currentCode++;
}
}
break;
}
}
}
/* CODE map */
switch(*currentCode)
{
/* Arithmetic operations */
case 0x00: case 0x01: case 0x02: case 0x03:
case 0x08: case 0x09: case 0x0A: case 0x0B:
case 0x10: case 0x11: case 0x12: case 0x13:
case 0x18: case 0x19: case 0x1A: case 0x1B:
case 0x20: case 0x21: case 0x22: case 0x23:
case 0x28: case 0x29: case 0x2A: case 0x2B:
case 0x30: case 0x31: case 0x32: case 0x33:
case 0x38: case 0x39: case 0x3A: case 0x3B:
{
Instruction->Opcode = *currentCode;
Instruction->dFlag = (*currentCode >> 1) & 1;
Instruction->wFlag = (*currentCode) & 1;
sprintf(mnemonic, ArithmeticMnemonic[(*currentCode >> 3) & 0x1F]);
currentCode++;
currentCode = ParseRegModRM(currentCode, Instruction, operand1, operand2);
break;
}
case 0x04: case 0x05: case 0x0C: case 0x0D:
case 0x14: case 0x15: case 0x1C: case 0x1D:
case 0x24: case 0x25: case 0x2C: case 0x2D:
case 0x34: case 0x35: case 0x3C: case 0x3D:
{
Instruction->Opcode = *currentCode;
Instruction->wFlag = (*currentCode & 1);
Instruction->sFlag = ! Instruction->wFlag;
sprintf(mnemonic, ArithmeticMnemonic[(*currentCode >> 3) & 0x1F]);
sprintf(operand1, "%s", Instruction->wFlag ? (Instruction->OperandPrefix >= 0 ? "ax" : "eax")
: "al");
currentCode++;
currentCode = ParseImmediate(currentCode, Instruction, operand2);
break;
}
case 0x80: case 0x81: case 0x82: case 0x83:
{
Instruction->Opcode = *currentCode;
Instruction->wFlag = (*currentCode & 1);
Instruction->sFlag = (*currentCode >> 1) & 1;
/* special cases */
if(*currentCode == 0x80)
{
Instruction->sFlag = 1;
}
sprintf(mnemonic, ArithmeticMnemonic[(*(currentCode + 1) >> 3) & 7]);
currentCode++;
currentCode = ParseModRM(currentCode, Instruction, operand1);
currentCode = ParseImmediate(currentCode, Instruction, operand2);
/* special cases */
if(Instruction->Opcode == 0x83)
{
sprintf(operand2, "%X%X", (Instruction->Immediate >> 7 & 1) ? (Instruction->OperandPrefix >= 0 ? 0xFF: 0xFFFFFF) : 0x0, Instruction->Immediate);
}
break;
}
/* push pop operations */
case 0x06: case 0x07 : case 0x0E: case 0x16: case 0x17: case 0x1E : case 0x1F:
{
Instruction->Opcode = *currentCode;
sprintf(mnemonic, "%s", *currentCode & 1 ? "pop" : "push");
sprintf(operand1, "%s", SegmentRegisters[(*currentCode >> 3) & 3]);
currentCode++;
break;
}
case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57:
case 0x58: case 0x59: case 0x5A: case 0x5B: case 0x5C: case 0x5D: case 0x5E: case 0x5F:
{
Instruction->Opcode = *currentCode;
sprintf(mnemonic, "%s", (*currentCode >> 3) & 1 ? "pop" : "push");
sprintf(operand1, "%s", Instruction->OperandPrefix >= 0 ? Register16[*currentCode & 7] : Register32[*currentCode & 7]);
currentCode++;
break;
}
case 0x60: case 0x61: case 0x9C: case 0x9D:
{
Instruction->Opcode = *currentCode;
sprintf(mnemonic, "%s%c%c", (*currentCode & 1) ? "pop" : "push",
(*currentCode >> 7) & 1 ? 'f' : 'a', Instruction->OperandPrefix >= 0 ? 'w' : 'd');
currentCode++;
break;
}
case 0x68: case 0x6A:
{
Instruction->Opcode = *currentCode;
Instruction->sFlag = (*currentCode >> 1) & 1;
sprintf(mnemonic, "%s", "push");
currentCode++;
currentCode = ParseImmediate(currentCode, Instruction, operand1);
break;
}
case 0x8F:
{
Instruction->Opcode = *currentCode;
Instruction->wFlag = (*currentCode) & 1;
sprintf(mnemonic, "%s", "pop");
currentCode++;
currentCode = ParseModRM(currentCode, Instruction, operand1);
break;
}
case 0x27: case 0x2F: case 0x37: case 0x3F:
{
Instruction->Opcode = *currentCode;
sprintf(mnemonic, "%s", BCDAdjustMnemonic[(*currentCode >> 3) & 3]);
currentCode++;
break;
}
/* inc and dec */
case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47:
case 0x48: case 0x49: case 0x4A: case 0x4B: case 0x4C: case 0x4D: case 0x4E: case 0x4F:
{
Instruction->Opcode = *currentCode;
sprintf(mnemonic, "%s", (*currentCode >> 3) & 1 ? "dec" : "inc");
sprintf(operand1, "%s", Instruction->OperandPrefix >= 0 ? Register16[*currentCode & 7] : Register32[*currentCode & 7]);
currentCode++;
break;
}
/* bound */
case 0x62:
{
Instruction->Opcode = *currentCode;
Instruction->wFlag = *currentCode & 1;
Instruction->sFlag = (*currentCode >> 1) & 1;
sprintf(mnemonic, "%s", "bound");
sprintf(operand1, "%s", Instruction->OperandPrefix >= 0 ? Register16[(*(currentCode + 1) >> 3) & 7] :
Register32[(*(currentCode + 1) >> 3) & 7]);
currentCode++;
currentCode = ParseModRM(currentCode, Instruction, operand2);
/* special case, the size of memory address must be twice the size of register */
sprintf(operand3, "%s%s", Instruction->OperandPrefix >= 0 ? "dword " : "qword ",
strstr(operand2, "ptr"));
sprintf(operand2, "%s", operand3);
*operand3 = '\0';
break;
}
/* arpl */
case 0x63:
{
Instruction->Opcode = *currentCode;
/* special case, the operand size of arpl must be 16-bits */
Instruction->OperandPrefix = 0;
Instruction->wFlag = 1;
Instruction->dFlag = 0;
sprintf(mnemonic, "%s", "arpl");
currentCode++;
currentCode = ParseRegModRM(currentCode, Instruction, operand1, operand2);
break;
}
/* imul */
case 0x69: case 0x6B:
{
Instruction->Opcode = *currentCode;
Instruction->wFlag = *currentCode & 1;
Instruction->sFlag = (*currentCode >> 1) & 1;
Instruction->dFlag = (*currentCode >> 1) & 1;
sprintf(mnemonic, "%s", "imul");
currentCode++;
currentCode = ParseRegModRM(currentCode, Instruction, operand1, operand2);
currentCode = ParseImmediate(currentCode, Instruction, operand3);
break;
}
/* ins and outs */
case 0x6C: case 0x6D: case 0x6E: case 0x6F:
{
Instruction->Opcode = *currentCode;
Instruction->wFlag = *currentCode & 1;
Instruction->dFlag = (*currentCode >> 1) & 1;
sprintf(prefix, "%s", Instruction->RepeatPrefix > 0 ? RepeatPrefixes[Instruction->RepeatPrefix] : "");
sprintf(mnemonic, "%s%c", Instruction->dFlag ? "outs" : "ins", Instruction->wFlag ?
(Instruction->OperandPrefix >= 0 ? 'w' : 'd') : 'b');
currentCode++;
break;
}
/* jmp instructions j(n)xx */
case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77:
case 0x78: case 0x79: case 0x7A: case 0x7B: case 0x7C: case 0x7D: case 0x7E: case 0x7F:
{
Instruction->Opcode = *currentCode;
sprintf(mnemonic, "%s", *currentCode & 1 ? JnxxMnemonic[(*currentCode >> 1) & 7] : JxxxMnemonic[(*currentCode >> 1) & 7]);
currentCode++;
sprintf(operand1, "short %X", Instruction->LinearAddress + *((char*)currentCode) + currentCode - Code + 1);
currentCode++;
break;
}
/* test */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -