📄 disasm.cpp
字号:
int i;
if (mode<DISASM_DATA)
return;
index&=0x07;
if (index>=6)
softerror=DAE_BADSEG; // Undefined segment register
sprintf_s(da->vm_name,"%s_%s",da->vm_name,segname[index]);
da->optype[stoperand] = Seg;
if (mode>=DISASM_FILE)
{
da->segreg = index;
i=sprintf(da->result+nresult,"%s",segname[index]);
if (lowercase)
strlwr(da->result+nresult);
nresult+=i;
}
}
// Decode control register addressed in R part of ModRM byte. Operands of
// this type are extremely rare. Contents of control registers are accessible
// only from privilege level 0, so I cannot dump them here.
static void DecodeCR(int index)
{
hasrm=1;
if (mode>=DISASM_FILE)
{
index=(index>>3) & 0x07;
nresult+=sprintf(da->result+nresult,"%s",crname[index]);
if (lowercase)
strlwr(da->result+nresult);
}
}
// Decode debug register addressed in R part of ModRM byte. Operands of
// this type are extremely rare. I can dump only those debug registers
// available in CONTEXT structure.
static void DecodeDR(int index)
{
int i;
hasrm=1;
if (mode>=DISASM_FILE)
{
index=(index>>3) & 0x07;
i=sprintf(da->result+nresult,"%s",drname[index]);
if (lowercase)
strlwr(da->result+nresult);
nresult+=i;
}
}
// Skips 3DNow! operands and extracts command suffix. Returns suffix or -1 if
// suffix lies outside the memory block. This subroutine assumes that cmd still
// points to the beginning of 3DNow! command (i.e. to the sequence of two bytes
// 0F, 0F).
static int Get3dnowsuffix(void)
{
int c,sib;
ulong offset;
if (size<3)
return -1; // Suffix outside the memory block
offset=3;
c=cmd[2] & 0xC7; // Leave only Mod and M fields
// Register in ModM - general-purpose, MMX or 3DNow!
if ((c & 0xC0)==0xC0)
;
// 16-bit addressing mode, SIB byte is never used here.
else if (addrsize==2)
{
if (c==0x06) // Special case of immediate address
offset+=2;
else if ((c & 0xC0)==0x40) // 8-bit signed displacement
offset++;
else if ((c & 0xC0)==0x80) // 16-bit unsigned displacement
offset+=2;
}
// Immediate 32-bit address.
else if (c==0x05) // Special case of immediate address
offset+=4;
// 32-bit address with SIB byte.
else if ((c & 0x07)==0x04)
{ // SIB addresation
if (size<4)
return -1; // Suffix outside the memory block
sib=cmd[3];
offset++;
if (c==0x04 && (sib & 0x07)==0x05)
offset+=4; // Immediate address without base
else if ((c & 0xC0)==0x40) // 8-bit displacement
offset+=1;
else if ((c & 0xC0)==0x80) // 32-bit dislacement
offset+=4;
}
// 32-bit address without SIB byte
else if ((c & 0xC0)==0x40)
offset+=1;
else if ((c & 0xC0)==0x80)
offset+=4;
if (offset>=size)
return -1; // Suffix outside the memory block
return cmd[offset];
}
// Function checks whether 80x86 flags meet condition set in the command.
// Returns 1 if condition is met, 0 if not and -1 in case of error (which is
// not possible).
int Checkcondition(int code,ulong flags)
{
ulong cond,temp;
switch (code & 0x0E)
{
case 0: // If overflow
cond=flags & 0x0800;
break;
case 2: // If below
cond=flags & 0x0001;
break;
case 4: // If equal
cond=flags & 0x0040;
break;
case 6: // If below or equal
cond=flags & 0x0041;
break;
case 8: // If sign
cond=flags & 0x0080;
break;
case 10: // If parity
cond=flags & 0x0004;
break;
case 12: // If less
temp=flags & 0x0880;
cond=(temp==0x0800 || temp==0x0080);
break;
case 14: // If less or equal
temp=flags & 0x0880;
cond=(temp==0x0800 || temp==0x0080 || (flags & 0x0040)!=0);
break;
default:
return -1; // Internal error, not possible!
}
if ((code & 0x01)==0)
return (cond!=0);
else
return (cond==0); // Invert condition
}
//bughoho
int stoperand = 0;
ulong Disasm(char *src,ulong srcsize,ulong srcip,t_disasm *disasm,int disasmmode)
{
int i,j,isprefix,is3dnow,repeated,operand,mnemosize,arg = 0;
ulong u,code;
int lockprefix; // Non-zero if lock prefix present
int repprefix; // REPxxx prefix or 0
int cxsize;
char name[TEXTLEN],*pname;
const t_cmddata *pd,*pdan;
// Prepare disassembler variables and initialize structure disasm.
//初始化结构和变量
datasize=addrsize=4; // 32-bit code and data segments only!
segprefix=SEG_UNDEF;
hasrm=hassib=0; dispsize=immsize=0;
lockprefix=0; repprefix=0;
ndump=0; nresult=0;
cmd=src; size=srcsize; pfixup=NULL;
softerror=0; is3dnow=0;
da=disasm;
da->ip=srcip;
da->comment[0]='\0';
da->cmdtype=C_BAD; da->nprefix=0;
da->memtype=DEC_UNKNOWN; da->indexed=0;
da->jmpconst=0; da->jmptable=0;
da->adrconst=0; da->immconst=0;
da->zeroconst=0;
da->fixupoffset=0; da->fixupsize=0;
da->warnings=0;
da->error=DAE_NOERR;
mode=disasmmode; // No need to use register contents
da->optype[0] = da->optype[1] = da->optype[2] = -1;
da->reg[0] = da->reg[1] = da->reg[2] = -1;
da->segreg = -1;
da->addrreg1 = da->addrreg2 = -1;
da->regsscale = 1;
memset(da->hexcode,0,TEXTLEN);
da->codelen = 0;
da->highbit[0] = da->highbit[1] = da->highbit[2] = false;
// Correct 80x86 command may theoretically contain up to 4 prefixes belonging
// to different prefix groups. This limits maximal possible size of the
// command to MAXCMDSIZE=16 bytes. In order to maintain this limit, if
// Disasm() detects second prefix from the same group, it flushes first
// prefix in the sequence as a pseudocommand.
u=0; repeated=0;
while (size>0)
{
isprefix=1; // Assume that there is some prefix
switch (*cmd)
{
case 0x26:
if (segprefix==SEG_UNDEF)
segprefix=SEG_ES;
else repeated=1;
break;
case 0x2E:
if (segprefix==SEG_UNDEF)
segprefix=SEG_CS;
else repeated=1;
break;
case 0x36:
if (segprefix==SEG_UNDEF)
segprefix=SEG_SS;
else repeated=1;
break;
case 0x3E:
if (segprefix==SEG_UNDEF)
segprefix=SEG_DS;
else repeated=1;
break;
case 0x64:
if (segprefix==SEG_UNDEF)
segprefix=SEG_FS;
else repeated=1;
break;
case 0x65:
if (segprefix==SEG_UNDEF)
segprefix=SEG_GS;
else repeated=1;
break;
case 0x66:
if (datasize==4)
datasize=2;
else repeated=1;
break;
case 0x67:
if (addrsize==4)
addrsize=2;
else repeated=1;
break;
case 0xF0:
if (lockprefix==0)
lockprefix=0xF0;
else repeated=1;
break;
case 0xF2:
if (repprefix==0)
repprefix=0xF2;
else repeated=1;
break;
case 0xF3:
if (repprefix==0)
repprefix=0xF3;
else repeated=1;
break;
default:
isprefix=0;
break;
}
if (isprefix==0 || repeated!=0)
break; // No more prefixes or duplicated prefix
if (mode>=DISASM_FILE)
{
ndump+=sprintf(da->dump+ndump,"%02X:",*cmd);
da->hexcode[da->codelen++] = *cmd;
}
da->nprefix++;
cmd++; srcip++; size--; u++;
}
//bughoho
da->segment = segprefix;//得到段寄存器
// We do have repeated prefix. Flush first prefix from the sequence.
if (repeated)
{
if (mode>=DISASM_FILE)
{
da->dump[3]='\0'; // Leave only first dumped prefix
da->nprefix=1;
switch (cmd[-(long)u])//cmd++ 且 u++;这里是得到cmd[0]
{
case 0x26: pname=(char *)(segname[SEG_ES]);
break;
case 0x2E: pname=(char *)(segname[SEG_CS]);
break;
case 0x36: pname=(char *)(segname[SEG_SS]);
break;
case 0x3E: pname=(char *)(segname[SEG_DS]);
break;
case 0x64: pname=(char *)(segname[SEG_FS]);
break;
case 0x65: pname=(char *)(segname[SEG_GS]);
break;
case 0x66: pname="DATASIZE";
break;
case 0x67: pname="ADDRSIZE";
break;
case 0xF0: pname="LOCK";
break;
case 0xF2: pname="REPNE";
break;
case 0xF3: pname="REPE";
break;
default: pname="?";
break;
}
nresult+=sprintf(da->result+nresult,"PREFIX %s:",pname);
if (lowercase)
strlwr(da->result);
if (extraprefix==0)
strcpy(da->comment,"Superfluous prefix");
}
da->warnings |= DAW_PREFIX;
if (lockprefix)
da->warnings |= DAW_LOCK;
da->cmdtype=C_RARE;
return 1; // Any prefix is 1 byte long
}
// If lock prefix available, display it and forget, because it has no
// influence on decoding of rest of the command.
if (lockprefix!=0)
{
if (mode>=DISASM_FILE)
nresult+=sprintf(da->result+nresult,"LOCK ");
da->warnings |= DAW_LOCK;
}
// Fetch (if available) first 3 bytes of the command, add repeat prefix and
// find command in the command table.
//取得命令的头三个字节
code=0;
if (size>0)
*(((char *)&code)+0)=cmd[0];
if (size>1)
*(((char *)&code)+1)=cmd[1];
if (size>2)
*(((char *)&code)+2)=cmd[2];
if (repprefix!=0) // RER/REPE/REPNE is considered to be
code=(code<<8) | repprefix; // part of command.
if (decodevxd && (code & 0xFFFF)==0x20CD)
pd=&vxdcmd; // Decode VxD call (Win95/98)
else
{
for (pd=cmddata; pd->mask!=0; pd++) //从指令表中搜索
{
if (((code^pd->code) & pd->mask)!=0)
continue;
if (mode>=DISASM_FILE && shortstringcmds && //如果是反汇编模式,并且Use short form of string commands
(pd->arg1==MSO || pd->arg1==MDE || pd->arg2==MSO || pd->arg2==MDE)) //如果寄存器是ESI或EDI
continue; // Search short form of string command
break;
}
}
if ( (pd->type & C_TYPEMASK) == C_NOW) //如果是3DNow指令
{
// 3DNow! commands require additional search.
is3dnow=1;
j=Get3dnowsuffix();
if (j<0)
da->error=DAE_CROSS;
else
{
for( ; pd->mask!=0; pd++)
{
if (((code^pd->code) & pd->mask)!=0)
continue;
if (((uchar *)&(pd->code))[2]==j)
break;
}
}
}
//bughoho
da->is3dnow = is3dnow;//是否是3DNow!指令
if (pd->mask==0) //命令未找到
{ // Command not found
da->cmdtype=C_BAD;
if (size<2)
da->error=DAE_CROSS;
else
da->error=DAE_BADCMD;
}
else//命令经过认证
{ // Command recognized, decode it
da->cmdtype=pd->type;//命令类型(附加信息)
cxsize=datasize; // Default size of ECX used as counter //ECX记数器的默认长度
if (segprefix==SEG_FS || segprefix==SEG_GS || lockprefix!=0)
da->cmdtype|=C_RARE; // These prefixes are rare //出现很少的命令
if (pd->bits==PR)//特权指令
da->warnings|=DAW_PRIV; // Privileged command (ring 0)
else if (pd->bits==WP)//IO命令
da->warnings|=DAW_IO; // I/O command
// Win32 programs usually try to keep stack dword-aligned, so INC ESP
// (44) and DEC ESP (4C) usually don't appear in real code. Also check for
// ADD ESP,imm and SUB ESP,imm (81,C4,imm32; 83,C4,imm8; 81,EC,imm32;
// 83,EC,imm8).
//WIN32程序通常会保持栈的四字节对齐,所以inc esp,dec esp一般不会出现在平常的代码中,
//同样检测add esp,imm 和 sub esp,imm.
if ( cmd[0]==0x44 || cmd[0]==0x4C ||
(size>=3 && (cmd[0]==0x81 || cmd[0]==0x83) &&
(cmd[1]==0xC4 || cmd[1]==0xEC) && (cmd[2] & 0x03)!=0) )
{
da->warnings|=DAW_STACK;//栈警告
da->cmdtype|=C_RARE; //不常出现的指令
}
// Warn also on MOV SEG,... (8E...). Win32 works in flat mode.
//警告 mov seg,xxx 操作,因为Win32工作在平坦模式
if (cmd[0]==0x8E)
da->warnings|=DAW_SEGMENT;
// If opcode is 2-byte, adjust command.
//如果操作码是2字节的则调整命令
if (pd->len==2)
{
if (size==0)
da->error=DAE_CROSS;
else
{
if (mode>=DISASM_FILE)
{
ndump+=sprintf(da->dump+ndump,"%02X",*cmd);
da->hexcode[da->codelen++] = *cmd;
}
cmd++;
srcip++;
size--;
}
}
if (size==0)
da->error=DAE_CROSS;
// Some commands either feature non-standard data size or have bit which
// allowes to select data size.
//一些命令的数据长度不是标准的,可以改变长度大小
if ((pd->bits & WW)!=0 && (*cmd & WW)==0)
datasize=1; // Bit W in command set to 0
else if ((pd->bits & W3)!=0 && (*cmd & W3)==0)
datasize=1; // Another position of bit W
else if ((pd->bits & FF)!=0)
datasize=2; // Forced word (2-byte) size
// Some commands either have mnemonics which depend on data size (8/16 bits
// or 32 bits, like CWD/CDQ), or have several different mnemonics (like
// JNZ/JNE). First case is marked by either '&' (mnemonic depends on
// operand size) or '$' (depends on address size). In the second case,
// there is no special marker and disassembler selects main mnemonic.
if (mode>=DISASM_FILE)
{
if (pd->name[0]=='&')
mnemosize=datasize;
else if (pd->name[0]=='$')
mnemosize=addrsize;
else mnemosize=0;
if (mnemosize!=0)
{
for (i=0,j=1; pd->name[j]!='\0'; j++)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -