📄 disasm.c
字号:
if(!isdigit(str[strlen(str)-2]) || str[strlen(str)-2] > '7')
return 0;
return 1;
}
return 0;
};
int strIsBase10Int(const char* str)
{
char *p;
if(strlen(str))
{
strtoul(str,&p,10);
if(*p == 0)
return 1;
};
return 0;
};
int DecodeSingleOperand(const char * pLoadAddress, unsigned char *pStart, DefaultOperationSizeAttrib DSize, int iOpIndex, IA32InstructionDecode *pIA32Decode)
{
char strOperand[16];
char cAddressingMethod;
char *strOperandType;
char *strOutput;
unsigned char ModRM;
unsigned int uiOperandSize = 0;
unsigned int uiAddressSize;
unsigned char ucI8;
unsigned short usI16;
unsigned int uiI32;
unsigned int uiTemp;
char strSegOverride[10];
unsigned char ucSegOverride;
char strOpSize[20];
ucSegOverride = GetSegmentOverride(pIA32Decode);
GetSegmentOverrideStr(ucSegOverride,strSegOverride,sizeof(strSegOverride));
if(strlen(strSegOverride))
strcat(strSegOverride,":");
if(!GetOutputBuffer(iOpIndex,&strOutput,pIA32Decode))
return 0;
GetMemoryOperandSizeStr(strOutput,strOpSize,DSize,pIA32Decode);
if(strlen(strOpSize))
strcat(strOpSize," ");
strcpy(strOperand,strOutput);
if(!strlen(strOutput)||isupperstr(strOperand))
return 1;
if(strIsBase10Int(strOutput))
return 1;
/* terminate here if strOperand is an FP register */
if(strIsFPRegister(strOperand))
return 1;
cAddressingMethod = strOperand[0];
strOperandType = strOperand + 1;
if(strlen(strOperandType))
{
uiOperandSize = GetOperandTypeSize(strOperandType);
if(uiOperandSize & 0xFF000000)
{
/* we depend on the operand-size attribute */
if(DSize == OpSize32)
{
if(IA32InstructionPrefixExists(0x66,pIA32Decode))
/* use 16-bit operand-size */
uiOperandSize = uiOperandSize & 0x000000FF;
else
uiOperandSize = (uiOperandSize & 0x0000FF00) >> 8;
}
else
{ /* Default operand-size is 16-bit */
if(IA32InstructionPrefixExists(0x66,pIA32Decode))
/* use 16-bit operand-size */
uiOperandSize = (uiOperandSize & 0x0000FF00) >> 8;
else
uiOperandSize = uiOperandSize & 0x000000FF;
};
};
};
if(DSize == OpSize32)
{
if(IA32InstructionPrefixExists(0x67,pIA32Decode))
/* use 16-bit address-size */
uiAddressSize = 16;
else
uiAddressSize = 32;
}
else
{ /* Default address-size is 16-bit */
if(!IA32InstructionPrefixExists(0x67,pIA32Decode))
/* use 16-bit operand-size */
uiAddressSize = 16;
else
uiAddressSize = 32;
};
if(cAddressingMethod == 'e')
{
if(IsExplicitRegisterOperand(strOperand))
return DecodeExplicitGPRegister(DSize,iOpIndex,pIA32Decode);
else
return 0;
};
switch(cAddressingMethod)
{
case 'A':
case 'O':
/* Direct address - the instruction has no ModRM nor SIB bytes */
if(pIA32Decode->SIA32InstructionHelper.boolModRMExists)
return 0;
CopyMemory( &pIA32Decode->SIA32RawInstruction.URawDisplacement.cByteRawDisplacement,
pStart + pIA32Decode->SIA32InstructionHelper.cbRawPrefixes
+ pIA32Decode->SIA32InstructionHelper.cbRawOpcode,
uiAddressSize/8);
pIA32Decode->SIA32InstructionHelper.cbRawDisplacement = (unsigned char)(uiAddressSize/8);
if(uiOperandSize == 6)
{
/*
* In cases where we deal with 48-bit operand types, documentation is not clear
* about location of the extra two bytes representing the segment part, i.e. where
* do the two bytes fit in the IA32 general instruction format as outlined in
* "IA-32 Software Developer's manual volume 2A: instruction set reference",
* chapter 2, figure 2-1???
* So I just assume the two bytes immediately follow the 32-bit displacement, ooh!
* For representation of the disassembled code - this case will be treated as a
* special case
*/
CopyMemory( pIA32Decode->SIA32RawInstruction.URawImmediate.ca2ByteRawImmediate,
pStart + pIA32Decode->SIA32InstructionHelper.cbRawPrefixes
+ pIA32Decode->SIA32InstructionHelper.cbRawOpcode
+ pIA32Decode->SIA32InstructionHelper.boolModRMExists
+ pIA32Decode->SIA32InstructionHelper.boolSIBExists
+ pIA32Decode->SIA32InstructionHelper.cbRawDisplacement,
2);
pIA32Decode->SIA32InstructionHelper.cbRawImmediate += 2;
sprintf(strOutput,"0x%04X:[0x%08X]",
*(unsigned short*)pIA32Decode->SIA32RawInstruction.URawImmediate.ca2ByteRawImmediate,
*(unsigned int*)pIA32Decode->SIA32RawInstruction.URawDisplacement.ca2ByteRawDisplacement);
return 1;
};
if(!strlen(strSegOverride))
strcpy(strSegOverride,"ds:");
switch(uiAddressSize)
{
case 16:
sprintf(strOutput,"%s%s[0x%04X]",strOpSize,strSegOverride,
*((unsigned short*)pIA32Decode->SIA32RawInstruction.URawDisplacement.ca2ByteRawDisplacement));
break;
case 32:
sprintf(strOutput,"%s%s[0x%08X]",strOpSize,strSegOverride,
*((unsigned int*)pIA32Decode->SIA32RawInstruction.URawDisplacement.ca4ByteRawDisplacement));
break;
default:
return 0;
}
return 1;
case 'E':
case 'Q':
case 'W':
/* if the addressing method begins with one of above characters then it is R/M
* we need to determine the actual case. We certainly know that the instruction
* does have the ModRM byte
*/
if(!pIA32Decode->SIA32InstructionHelper.boolModRMExists)
{
ModRM = pStart[pIA32Decode->SIA32InstructionHelper.cbRawPrefixes + pIA32Decode->SIA32InstructionHelper.cbRawOpcode];
pIA32Decode->SIA32RawInstruction.ModRM = ModRM;
pIA32Decode->SIA32InstructionHelper.boolModRMExists = 1;
}
else
ModRM = pIA32Decode->SIA32RawInstruction.ModRM;
if((ModRM & 0xC0) == 0xC0)
/* we are dealing with a register operand here */
return DecodeSingleRegisterOperand(DSize,iOpIndex,pIA32Decode);
else
/* we are dealing with a memory operand */
return DecodeMemoryOperand(pStart,DSize,iOpIndex,pIA32Decode);
case 'C':
case 'D':
case 'G':
case 'P':
case 'R':
case 'S':
case 'T':
case 'V':
/* definitely registers here */
if(!pIA32Decode->SIA32InstructionHelper.boolModRMExists)
{
ModRM = pStart[pIA32Decode->SIA32InstructionHelper.cbRawPrefixes + pIA32Decode->SIA32InstructionHelper.cbRawOpcode];
pIA32Decode->SIA32RawInstruction.ModRM = ModRM;
pIA32Decode->SIA32InstructionHelper.boolModRMExists = 1;
};
return DecodeSingleRegisterOperand(DSize,iOpIndex,pIA32Decode);
case 'M':
return DecodeMemoryOperand(pStart,DSize,iOpIndex,pIA32Decode);
case 'I':
/* immediate */
CopyMemory(&pIA32Decode->SIA32RawInstruction.URawImmediate.cByteRawImmediate,
pStart +
pIA32Decode->SIA32InstructionHelper.cbRawPrefixes +
pIA32Decode->SIA32InstructionHelper.cbRawOpcode +
pIA32Decode->SIA32InstructionHelper.boolModRMExists +
pIA32Decode->SIA32InstructionHelper.boolSIBExists +
pIA32Decode->SIA32InstructionHelper.cbRawDisplacement,
uiOperandSize);
pIA32Decode->SIA32InstructionHelper.cbRawImmediate += (unsigned char)uiOperandSize;
switch(uiOperandSize)
{
case 1:
ucI8 = pIA32Decode->SIA32RawInstruction.URawImmediate.cByteRawImmediate;
sprintf(strOutput,"0x%02X",ucI8);
return 1;
case 2:
usI16 = *((unsigned short*)pIA32Decode->SIA32RawInstruction.URawImmediate.ca2ByteRawImmediate);
sprintf(strOutput,"0x%04X",usI16);
return 1;
case 4:
uiI32 = *((unsigned int*)pIA32Decode->SIA32RawInstruction.URawImmediate.ca4ByteRawImmediate);
sprintf(strOutput,"0x%08X",uiI32);
return 1;
default:
return 0;
};
case 'J':
/* relative offset in immediate that needs to be added to the instruction pointer */
CopyMemory(&pIA32Decode->SIA32RawInstruction.URawImmediate.cByteRawImmediate,
pStart +
pIA32Decode->SIA32InstructionHelper.cbRawPrefixes +
pIA32Decode->SIA32InstructionHelper.cbRawOpcode +
pIA32Decode->SIA32InstructionHelper.boolModRMExists +
pIA32Decode->SIA32InstructionHelper.boolSIBExists +
pIA32Decode->SIA32InstructionHelper.cbRawDisplacement,
uiOperandSize);
pIA32Decode->SIA32InstructionHelper.cbRawImmediate += (unsigned char)uiOperandSize;
uiTemp = (unsigned int)(pLoadAddress + GetInstructionLength(pIA32Decode));
switch(uiOperandSize)
{
case 1:
ucI8 = pIA32Decode->SIA32RawInstruction.URawImmediate.cByteRawImmediate;
sprintf(strOutput,"0x%02X",(char)ucI8 + uiTemp);
return 1;
case 2:
usI16 = *((unsigned short*)pIA32Decode->SIA32RawInstruction.URawImmediate.ca2ByteRawImmediate);
sprintf(strOutput,"0x%04X",(short)usI16 + uiTemp);
return 1;
case 4:
uiI32 = *((unsigned int*)pIA32Decode->SIA32RawInstruction.URawImmediate.ca4ByteRawImmediate);
sprintf(strOutput,"0x%08X",(int)uiI32 + uiTemp);
return 1;
default:
return 0;
};
case 'X':
if(uiAddressSize == 16)
sprintf(strOutput,"%s[si]",strOpSize);
else
sprintf(strOutput,"%s[esi]",strOpSize);
return 1;
case 'Y':
if(uiAddressSize == 16)
sprintf(strOutput,"%s[di]",strOpSize);
else
sprintf(strOutput,"%s[edi]",strOpSize);
return 1;
default:
return 0;
}
};
int DecodeOperands(const char * pLoadAddress, unsigned char *pStart,DefaultOperationSizeAttrib DSize, IA32InstructionDecode *pIA32Decode)
{
if(strlen(pIA32Decode->SIA32InstructionDescription.strOperandA))
if(!DecodeSingleOperand(pLoadAddress,pStart,DSize,1,pIA32Decode))
return 0;
if(strlen(pIA32Decode->SIA32InstructionDescription.strOperandB))
if(!DecodeSingleOperand(pLoadAddress,pStart,DSize,2,pIA32Decode))
return 0;
if(strlen(pIA32Decode->SIA32InstructionDescription.strOperandC))
if(!DecodeSingleOperand(pLoadAddress,pStart,DSize,3,pIA32Decode))
return 0;
if(IsExplicitRegisterOperand(pIA32Decode->SIA32InstructionDescription.strOperandA))
strlwr(pIA32Decode->SIA32InstructionDescription.strOperandA);
if(IsExplicitRegisterOperand(pIA32Decode->SIA32InstructionDescription.strOperandB))
strlwr(pIA32Decode->SIA32InstructionDescription.strOperandB);
if(IsExplicitRegisterOperand(pIA32Decode->SIA32InstructionDescription.strOperandC))
strlwr(pIA32Decode->SIA32InstructionDescription.strOperandC);
return 1;
};
void PrintInstruction(const char*pLoadAddress, IA32InstructionDecode *pIA32Decode)
{
int i;
char strBuffer[80];
char strRemainder[80];
ZeroMemory(strBuffer,sizeof(strBuffer));
/* first print instruction address, and then raw bytes as they are in memory */
printf("\n %08X: ",pLoadAddress);
for(i = 0; i < pIA32Decode->SIA32InstructionHelper.cbRawPrefixes; i++)
sprintf(strBuffer + strlen(strBuffer),"%02X ",pIA32Decode->SIA32RawInstruction.caRawPrefixes[i]);
for(i = 0; i < pIA32Decode->SIA32InstructionHelper.cbRawOpcode; i++)
sprintf(strBuffer + strlen(strBuffer),"%02X ",pIA32Decode->SIA32RawInstruction.URawOpcode.ca2ByteRawOpcode[i]);
if(pIA32Decode->SIA32InstructionHelper.boolModRMExists)
sprintf(strBuffer + strlen(strBuffer),"%02X ",pIA32Decode->SIA32RawInstruction.ModRM);
if(pIA32Decode->SIA32InstructionHelper.boolSIBExists)
sprintf(strBuffer + strlen(strBuffer),"%02X ",pIA32Decode->SIA32RawInstruction.SIB);
for(i = 0; i < pIA32Decode->SIA32InstructionHelper.cbRawDisplacement; i++)
sprintf(strBuffer + strlen(strBuffer),"%02X ",pIA32Decode->SIA32RawInstruction.URawDisplacement.ca2ByteRawDisplacement[i]);
for(i = 0; i < pIA32Decode->SIA32InstructionHelper.cbRawImmediate; i++)
sprintf(strBuffer + strlen(strBuffer),"%02X ",pIA32Decode->SIA32RawInstruction.URawImmediate.ca2ByteRawImmediate[i]);
ZeroMemory(strRemainder,sizeof(strRemainder));
i = _snprintf(strRemainder,17,"%-17s",strBuffer);
printf("%s",strRemainder);
if(i < 0)
strcpy(strRemainder,strBuffer + strlen(strRemainder) + 1);
else
ZeroMemory(strRemainder,sizeof(strRemainder));
/* Now print the description, taking into account use of prefix */
if(strlen(pIA32Decode->SIA32InstructionDescription.strPrefix))
{
i = strlen(pIA32Decode->SIA32InstructionDescription.strPrefix - 1);
if(!isspace(pIA32Decode->SIA32InstructionDescription.strPrefix[i]))
strcat(pIA32Decode->SIA32InstructionDescription.strPrefix," ");
}
sprintf(strBuffer,"%s%s",pIA32Decode->SIA32InstructionDescription.strPrefix,
pIA32Decode->SIA32InstructionDescription.strOpcode);
printf(" %-12s",strBuffer);
/* There can never be operand A without operand B, nor operand B without C */
if(strlen(pIA32Decode->SIA32InstructionDescription.strOperandA))
{
printf("%s",pIA32Decode->SIA32InstructionDescription.strOperandA);
if(strlen(pIA32Decode->SIA32InstructionDescription.strOperandB))
{
printf(",%s",pIA32Decode->SIA32InstructionDescription.strOperandB);
if(strlen(pIA32Decode->SIA32InstructionDescription.strOperandC))
printf(",%s",pIA32Decode->SIA32InstructionDescription.strOperandC);
}
}
if(strlen(strRemainder))
printf("\n %-s",strRemainder);
};
void Disassemble(const char*pLoadAddress,DefaultOperationSizeAttrib DSize,unsigned char *pStart, unsigned char *pEnd)
{
IA32InstructionDecode IA32Decode;
int iRet = 1;
while(pStart < pEnd)
{
#ifdef _DEBUG
if(pLoadAddress == (char*)0x0438cca)
Sleep(0);
#endif
ZeroMemory(&IA32Decode,sizeof(IA32Decode));
iRet = FetchOpcode(pLoadAddress,pStart,&IA32Decode,DSize);
if(iRet == 0)
return;
iRet = DecodeOperands(pLoadAddress,pStart,DSize,&IA32Decode);
if((iRet == 0)||!strcmpi(IA32Decode.SIA32InstructionDescription.strOpcode,"???"))
{
/* the first byte can be either a prefix or the opcode, let's deal with
* each case individually - cheating where necessary
*/
if(IA32Decode.SIA32InstructionHelper.cbRawPrefixes)
{
IA32Decode.SIA32RawInstruction.URawOpcode.cByteRawOpcode =
IA32Decode.SIA32RawInstruction.caRawPrefixes[0];
}
ZeroMemory(&IA32Decode.SIA32RawInstruction.URawOpcode.cByteRawOpcode + 1,
sizeof(IA32Decode) - (
sizeof(IA32Decode.SIA32RawInstruction.caRawPrefixes)
+ sizeof(IA32Decode.SIA32RawInstruction.URawOpcode.cByteRawOpcode)));
IA32Decode.SIA32InstructionDescription.strOpcode[0] = 0;
IA32Decode.SIA32InstructionHelper.cbRawOpcode = 1;
};
if(iRet)
iRet = GetInstructionLength(&IA32Decode);
else
iRet = 1;
PrintInstruction(pLoadAddress,&IA32Decode);
pStart += iRet;
pLoadAddress += iRet;
}
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -