📄 disasm.cpp
字号:
if (pd->name[j]==':')
{ // Separator between 16/32 mnemonics
if (mnemosize==4)
i=0;
else break;
}
else if (pd->name[j]=='*')
{ // Substitute by 'W', 'D' or none
if (mnemosize==4 && sizesens!=2)
name[i++]='D';
else if (mnemosize!=4 && sizesens!=0)
name[i++]='W';
}
else
name[i++]=pd->name[j];
}
name[i]='\0';
}
else
{
strcpy(name,pd->name);
for (i=0; name[i]!='\0'; i++)
{
if (name[i]==',')
{ // Use main mnemonic
name[i]='\0';
break;
}
}
}
if (repprefix!=0 && tabarguments)
{
for (i=0; name[i]!='\0' && name[i]!=' '; i++)
da->result[nresult++]=name[i];
if (name[i]==' ')
{
da->result[nresult++]=' '; i++;
}
while(nresult<8)
da->result[nresult++]=' ';
for ( ; name[i]!='\0'; i++)
da->result[nresult++]=name[i];
}
else
nresult+=sprintf(da->result+nresult,"%s",name);
if (lowercase)
strlwr(da->result);
sprintf_s(da->vm_name,"V%s",name);
}
// Decode operands (explicit - encoded in command, implicit - present in
// mmemonic or assumed - used or modified by command). Assumed operands
// must stay after all explicit and implicit operands. Up to 3 operands
// are allowed.
for (operand=0; operand<3; operand++)
{
stoperand = operand;
if (da->error)
break; // Error - no sense to continue
//If command contains both source and destination, one usually must not
//decode destination to comment because it will be overwritten on the
//next step. Global addcomment takes care of this. Decoding routines,
//however, may ignore this flag.
if (operand==0 && pd->arg2!=NNN && pd->arg2<PSEUDOOP)
addcomment=0;
else
addcomment=1;
// Get type of next argument.
if (operand==0)
arg=pd->arg1;
else if (operand==1)
arg=pd->arg2;
else
arg=pd->arg3;
if (arg==NNN)
break; //没有更多的操作数了 No more operands
// Arguments with arg>=PSEUDOOP are assumed operands and are not
// displayed in disassembled result, so they require no delimiter.
if ((mode>=DISASM_FILE) && arg<PSEUDOOP)//添加间隔
{
if (operand==0)//如果是命令
{
da->result[nresult++]=' ';
if (tabarguments)
{
while (nresult<8) da->result[nresult++]=' ';
}
}
else//如果是操作数
{
da->result[nresult++]=',';
if (extraspace) da->result[nresult++]=' ';
}
}
// Decode, analyse and comment next operand of the command.
//解码,分析和注释命令的下一个操作数
switch (arg)
{
case REG: // Integer register in Reg field
if (size<2)
da->error=DAE_CROSS;
else
{
DecodeRG(cmd[1]>>3,datasize,REG);
}
hasrm=1;
break;
case RCM: // Integer register in command byte
DecodeRG(cmd[0],datasize,RCM);
break;
case RG4: // Integer 4-byte register in Reg field
if (size<2)
da->error=DAE_CROSS;
else
{
DecodeRG(cmd[1]>>3,4,RG4);
}
hasrm=1;
break;
case RAC: // Accumulator (AL/AX/EAX, implicit)
DecodeRG(REG_EAX,datasize,RAC);
break;
case RAX: // AX (2-byte, implicit)
DecodeRG(REG_EAX,2,RAX);
break;
case RDX: // DX (16-bit implicit port address)
DecodeRG(REG_EDX,2,RDX);
break;
case RCL: // Implicit CL register (for shifts)
DecodeRG(REG_ECX,1,RCL);
break;
case RS0: // Top of FPU stack (ST(0))
DecodeST(0,0);//未解决
break;
case RST: // FPU register (ST(i)) in command byte
DecodeST(cmd[0],0);//未解决
break;
case RMX: // MMX register MMx
if (size<2)
da->error=DAE_CROSS;
else
DecodeMX(cmd[1]>>3);//未解决
hasrm=1;
break;
case R3D: // 3DNow! register MMx
if (size<2)
da->error=DAE_CROSS;
else
DecodeNR(cmd[1]>>3);//未解决
hasrm=1;
break;
case MRG: // Memory/register in ModRM byte
case MRJ: // Memory/reg in ModRM as JUMP target
case MR1: // 1-byte memory/register in ModRM byte
case MR2: // 2-byte memory/register in ModRM byte
case MR4: // 4-byte memory/register in ModRM byte
case MR8: // 8-byte memory/MMX register in ModRM
case MRD: // 8-byte memory/3DNow! register in ModRM
case MMA: // Memory address in ModRM byte for LEA
case MML: // Memory in ModRM byte (for LES)
case MM6: // Memory in ModRm (6-byte descriptor)
case MMB: // Two adjacent memory locations (BOUND)
case MD2: // Memory in ModRM byte (16-bit integer)
case MB2: // Memory in ModRM byte (16-bit binary)
case MD4: // Memory in ModRM byte (32-bit integer)
case MD8: // Memory in ModRM byte (64-bit integer)
case MDA: // Memory in ModRM byte (80-bit BCD)
case MF4: // Memory in ModRM byte (32-bit float)
case MF8: // Memory in ModRM byte (64-bit float)
case MFA: // Memory in ModRM byte (80-bit float)
case MFE: // Memory in ModRM byte (FPU environment)
case MFS: // Memory in ModRM byte (FPU state)
case MFX: // Memory in ModRM byte (ext. FPU state)
DecodeMR(arg);
break;
case MMS: // Memory in ModRM byte (as SEG:OFFS)
DecodeMR(arg);
da->warnings|=DAW_FARADDR;
break;
case RR4: // 4-byte memory/register (register only)
case RR8: // 8-byte MMX register only in ModRM
case RRD: // 8-byte memory/3DNow! (register only)
if ((cmd[1] & 0xC0)!=0xC0)
softerror=DAE_REGISTER;
DecodeMR(arg);
break;
case MSO: // Source in string op's ([ESI])
DecodeSO();
break;
case MDE: // Destination in string op's ([EDI])
DecodeDE();
break;
case MXL: // XLAT operand ([EBX+AL])
DecodeXL();//未解决
break;
case IMM: // Immediate data (8 or 16/32)
case IMU: // Immediate unsigned data (8 or 16/32)
if ((pd->bits & SS)!=0 && (*cmd & 0x02)!=0)
DecodeIM(1,datasize,arg);
else
DecodeIM(datasize,0,arg);
break;
case VXD: // VxD service (32-bit only)
DecodeVX();//未解决
break;
case IMX: // Immediate sign-extendable byte
DecodeIM(1,datasize,arg);
break;
case C01: // Implicit constant 1 (for shifts)
DecodeC1();//未解决
break;
case IMS: // Immediate byte (for shifts)
case IM1: // Immediate byte
DecodeIM(1,0,arg);
break;
case IM2: // Immediate word (ENTER/RET)
DecodeIM(2,0,arg);
if ((da->immconst & 0x03)!=0)
da->warnings|=DAW_STACK;
break;
case IMA: // Immediate absolute near data address
DecodeIA(); //[imm] ok
break;
case JOB: // Immediate byte offset (for jumps)
DecodeRJ(1,srcip+2);//无须解决jmpconst则是
break;
case JOW: // Immediate full offset (for jumps)
DecodeRJ(datasize,srcip+datasize+1);//无须解决jmpconst则是
break;
case JMF: // Immediate absolute far jump/call addr
DecodeJF();//未解决
da->warnings|=DAW_FARADDR;
break;
case SGM: // Segment register in ModRM byte
if (size<2)
da->error=DAE_CROSS;
DecodeSG(cmd[1]>>3);
hasrm=1;
break;
case SCM: // Segment register in command byte
DecodeSG(cmd[0]>>3);
if ((da->cmdtype & C_TYPEMASK)==C_POP)
da->warnings|=DAW_SEGMENT;
break;
case CRX: // Control register CRx
if ((cmd[1] & 0xC0)!=0xC0)
da->error=DAE_REGISTER;
DecodeCR(cmd[1]);//未解决
break;
case DRX: // Debug register DRx
if ((cmd[1] & 0xC0)!=0xC0)
da->error=DAE_REGISTER;
DecodeDR(cmd[1]);//未解决
break;
case PRN: // Near return address (pseudooperand)
break;
case PRF: // Far return address (pseudooperand)
da->warnings|=DAW_FARADDR;
break;
case PAC: // Accumulator (AL/AX/EAX, pseudooperand)
DecodeRG(REG_EAX,datasize,PAC);
break;
case PAH: // AH (in LAHF/SAHF, pseudooperand)
case PFL: // Lower byte of flags (pseudooperand)
break;
case PS0: // Top of FPU stack (pseudooperand)
DecodeST(0,1);//未解决
break;
case PS1: // ST(1) (pseudooperand)
DecodeST(1,1);//未解决
break;
case PCX: // CX/ECX (pseudooperand)
DecodeRG(REG_ECX,cxsize,PCX);
break;
case PDI: // EDI (pseudooperand in MMX extentions)
DecodeRG(REG_EDI,4,PDI);
break;
default:
da->error=DAE_INTERN; // Unknown argument type
break;
}
da->memsize[operand] = datasize;
}
// Check whether command may possibly contain fixups.
if (pfixup!=NULL && da->fixupsize>0)
da->fixupoffset=(int)(pfixup-src);
// Segment prefix and address size prefix are superfluous for command which
// does not access memory. If this the case, mark command as rare to help
// in analysis.
if (da->memtype==DEC_UNKNOWN &&
(segprefix!=SEG_UNDEF || (addrsize!=4 && pd->name[0]!='$'))
)
{
da->warnings|=DAW_PREFIX;
da->cmdtype|=C_RARE;
}
// 16-bit addressing is rare in 32-bit programs. If this is the case,
// mark command as rare to help in analysis.
//16位的寻址在32位程序中是少见的,如果是这种情况,在在命令中加上标志
if (addrsize!=4)
da->cmdtype|=C_RARE;
}
// Suffix of 3DNow! command is accounted best by assuming it immediate byte
// constant.
if (is3dnow)
{
if (immsize!=0)
da->error=DAE_BADCMD;
else immsize=1;
}
// Right or wrong, command decoded. Now dump it.
if (da->error!=0) //如果命令有错误
{ // Hard error in command detected
if (mode>=DISASM_FILE)
nresult=sprintf(da->result,"???");
if (da->error==DAE_BADCMD && (*cmd==0x0F || *cmd==0xFF) && size>0 )
{
if (mode>=DISASM_FILE)
{
ndump+=sprintf(da->dump+ndump,"%02X",*cmd);
da->hexcode[da->codelen++] = *cmd;
}
cmd++;
size--;
}
if (size>0)
{
if (mode>=DISASM_FILE)
{
ndump+=sprintf(da->dump+ndump,"%02X",*cmd);
da->hexcode[da->codelen++] = *cmd;
}
cmd++;
size--;
}
}
else
{ //如果没有错误,dump命令 // No hard error, dump command
if (mode>=DISASM_FILE)
{
ndump+=sprintf(da->dump+ndump,"%02X",*cmd++);
da->hexcode[da->codelen++] = *(cmd-1);
if (hasrm)
{
ndump+=sprintf(da->dump+ndump,"%02X",*cmd++);
da->hexcode[da->codelen++] = *(cmd-1);
}
if (hassib)
{
ndump+=sprintf(da->dump+ndump,"%02X",*cmd++);
da->hexcode[da->codelen++] = *(cmd-1);
}
if (dispsize!=0)
{
da->dump[ndump++]=' ';
for (i=0; i<dispsize; i++)
{
ndump+=sprintf(da->dump+ndump,"%02X",*cmd++);
da->hexcode[da->codelen++] = *(cmd-1);
}
}
if (immsize!=0)
{
da->dump[ndump++]=' ';
for (i=0; i<immsize; i++)
{
ndump+=sprintf(da->dump+ndump,"%02X",*cmd++);
da->hexcode[da->codelen++] = *(cmd-1);
}
}
}
else
cmd+=1+hasrm+hassib+dispsize+immsize;
size-=1+hasrm+hassib+dispsize+immsize;
}
// Check that command is not a dangerous one.
//检查命令是否是危险的
if (mode>=DISASM_DATA)
{
for (pdan=dangerous; pdan->mask!=0; pdan++)
{
if (((code^pdan->code) & pdan->mask)!=0)
continue;
if (pdan->type==C_DANGERLOCK && lockprefix==0)
break; // Command harmless without LOCK prefix
if (iswindowsnt && pdan->type==C_DANGER95)
break; // Command harmless under Windows NT
// Dangerous command!
if (pdan->type==C_DANGER95)
da->warnings|=DAW_DANGER95;
else
da->warnings|=DAW_DANGEROUS;
break;
}
}
if (da->error==0 && softerror!=0)
da->error=softerror; // Error, but still display command
if (mode>=DISASM_FILE)
{
if (da->error!=DAE_NOERR)
{
switch (da->error)
{
case DAE_CROSS:
strcpy(da->comment,"Command crosses end of memory block");
break;
case DAE_BADCMD:
strcpy(da->comment,"Unknown command");
break;
case DAE_BADSEG:
strcpy(da->comment,"Undefined segment register");
break;
case DAE_MEMORY:
strcpy(da->comment,"Illegal use of register");
break;
case DAE_REGISTER:
strcpy(da->comment,"Memory address not allowed");
break;
case DAE_INTERN:
strcpy(da->comment,"Internal OLLYDBG error");
break;
default:
strcpy(da->comment,"Unknown error");
break;
}
}
else if ((da->warnings & DAW_PRIV)!=0 && privileged==0)
strcpy(da->comment,"Privileged command");
else if ((da->warnings & DAW_IO)!=0 && iocommand==0)
strcpy(da->comment,"I/O command");
else if ((da->warnings & DAW_FARADDR)!=0 && farcalls==0)
{
if ((da->cmdtype & C_TYPEMASK)==C_JMP)
strcpy(da->comment,"Far jump");
else if ((da->cmdtype & C_TYPEMASK)==C_CAL)
strcpy(da->comment,"Far call");
else if ((da->cmdtype & C_TYPEMASK)==C_RET)
strcpy(da->comment,"Far return");
}
else if ((da->warnings & DAW_SEGMENT)!=0 && farcalls==0)
strcpy(da->comment,"Modification of segment register");
else if ((da->warnings & DAW_SHIFT)!=0 && badshift==0)
strcpy(da->comment,"Shift constant out of range 1..31");
else if ((da->warnings & DAW_PREFIX)!=0 && extraprefix==0)
strcpy(da->comment,"Superfluous prefix");
else if ((da->warnings & DAW_LOCK)!=0 && lockedbus==0)
strcpy(da->comment,"LOCK prefix");
else if ((da->warnings & DAW_STACK)!=0 && stackalign==0)
strcpy(da->comment,"Unaligned stack operation");
}
return (srcsize-size); // Returns number of recognized bytes
}