📄 disasm.cpp
字号:
case ARG_MODRM:
rm=(byte)((modrmbyte&0xc0)>>6);
switch(rm)
{ case 0:
if(options.mode32)
{ if((modrmbyte&0x07)==5)
return 5; // disp32
if((modrmbyte&0x07)==4)
{ if((sibbyte&0x07)==5)
return 6;
return 2; //sib byte - need to check if r=5 also.
}
}
else
if((modrmbyte&0x07)==6)
return 3;
break;
case 1:
if(options.mode32)
{ if((modrmbyte&0x07)==4)
{ return 3; //sib byte
}
}
return 2; // disp8
case 2:
if(options.mode32)
{ if((modrmbyte&0x07)==4)
return 6; //sib byte
return 5; // disp32
}
else
return 3; // disp16
case 3:
return 1;
}
return 1;
default:
break;
}
return 0;
}
/************************************************************************
* compare function *
* - the compare function for the list of disassembled instructions. *
* - the disassembled instructions are kept in order using location, and *
* type where type indicates instruction, comment, segheader line, etc *
* as these are kept in the database of disassembled instructions. The *
* window that the user sees into the disassembly is simply a view of *
* this database with one line per record. *
************************************************************************/
int disasm::compare(dsmitem *i,dsmitem *j)
{ if(i->addr==j->addr)
{ if(i->type==j->type)
return 0;
else if(i->type>j->type)
return 1;
return -1;
}
if(i->addr>j->addr)
return 1;
return -1;
}
/************************************************************************
* deletion function *
* - in deleting the database we delete any comments that may be *
* attached, overrides the standard list item delete function *
************************************************************************/
//deletion function for list
void disasm::delfunc(dsmitem *i)
{ // bugfix by Mark Ogden - added dsmnameloc
if((i->type!=dsmcode)&&(i->type!=dsmnameloc))
if(i->tptr!=NULL)
delete i->tptr;
delete i;
}
/************************************************************************
* undefineline *
* - this simply deletes any code item in the disassembly database, for *
* the users current line in the database/window *
************************************************************************/
void disasm::undefineline(void)
{ dsmitem *tblock;
lptr outhere;
tblock=dio.findcurrentline();
if(tblock==NULL)
return;
outhere=tblock->addr;
tblock=nextiter_code(tblock);
if(tblock!=NULL)
{ if(outhere==tblock->addr)
{ delfrom(tblock);
dio.updatewindow();
}
}
}
/************************************************************************
* undefinelines *
* - undefines the next 10 lines of code, or until a non-disassembled *
* item is found *
************************************************************************/
void disasm::undefinelines(void)
{ dsmitem *tblock;
lptr outhere;
int i;
tblock=dio.findcurrentline();
if(tblock==NULL)
return;
outhere=tblock->addr;
for(i=0;i<10;i++)
{ tblock=nextiter_code(tblock);
if(tblock!=NULL)
{ if(outhere==tblock->addr)
{ outhere+=tblock->length;
delfrom(tblock);
tblock=nextiterator();
}
else
break;
}
}
dio.updatewindow();
}
/************************************************************************
* undefinelines_long *
* - here we continue undefining any code items in the database from the *
* users line until we come to a location which is not code, or some *
* other kind of item in the database, like a comment, name, or xref *
************************************************************************/
void disasm::undefinelines_long(void)
{ dsmitem *tblock;
lptr outhere;
tblock=dio.findcurrentline();
if(tblock==NULL)
return;
outhere=tblock->addr;
tblock=nextiter_code(tblock);
while(tblock!=NULL)
{ if(!tblock->length)
break;
if(outhere==tblock->addr)
{ outhere+=tblock->length;
delfrom(tblock);
tblock=nextiterator();
}
else
break;
}
dio.updatewindow();
}
/************************************************************************
* undefineblock *
* - a block undefine using a selected block of code, we simply undefine *
* any code items found between the start and end points of the block *
************************************************************************/
void disasm::undefineblock(lptr ufrom,lptr uto)
{ dsmitem *tblock;
lptr outhere;
tblock=dsmfindaddrtype(ufrom,dsmcode);
if(tblock==NULL)
return;
outhere=tblock->addr;
while(tblock!=NULL)
{ if(tblock->addr>uto)
break;
if((tblock->type==dsmcode)&&(tblock->addr>=ufrom))
delfrom(tblock);
tblock=nextiterator();
}
dio.updatewindow();
}
/************************************************************************
* discomment *
* - this adds a comment to the disassembly database. It is used to add *
* different types of comments (like segheaders and user entered *
* comments) *
************************************************************************/
void disasm::discomment(lptr loc,dsmitemtype typ,byte *comment)
{ dsmitem *newdsm;
newdsm=new dsmitem;
initnewdsm(newdsm,loc,typ);
newdsm->tptr=(void *)comment;
newdsm->length=0;
newdsm->data=comment;
addto(newdsm);
dio.updatewindowifinrange(loc);
}
/************************************************************************
* disautocomment *
* - this is a second function to add a comment to the disassembly *
* database, but only if there is no comment already there. This is *
* used to add disassembler autocomments. This is currently only used *
* in resource disassembly, but could easily be used to add standard *
* comments for particular instructions or for API calls, or for DOS *
* INTs. *
************************************************************************/
void disasm::disautocomment(lptr loc,dsmitemtype typ,byte *comment)
{ dsmitem *newdsm,*fdsm;
fdsm=dsmfindaddrtype(loc,typ);
if(fdsm!=NULL)
if((fdsm->addr==loc)&&(fdsm->type==typ))
{ delete comment;
return;
}
newdsm=new dsmitem;
initnewdsm(newdsm,loc,typ);
newdsm->tptr=(void *)comment;
newdsm->length=0;
newdsm->data=comment;
addto(newdsm);
dio.updatewindowifinrange(loc);
}
/************************************************************************
* delcomment *
* - this is used to delete comments from the database. Typically it is *
* called when the user enters a comment for a location. We delete the *
* old one and then add the new one later. *
************************************************************************/
void disasm::delcomment(lptr loc,dsmitemtype typ)
{ dsmitem *fdsm;
fdsm=dsmfindaddrtype(loc,typ);
if(fdsm!=NULL)
if((fdsm->addr==loc)&&(fdsm->type==typ))
{ delfrom(fdsm);
dio.updatewindowifinrange(loc);
}
}
/************************************************************************
* interpretmod *
* - this is used by the jumptable detection routines in order to *
* examine a modrm/sib encoding for information *
* - it returns information about offsets and indexes and the registers *
* in use, and any multiplier *
************************************************************************/
bool disasm::interpretmod(byte *data,dword *toffs,byte *indexreg,byte *indexreg2,byte *indexamount,int *numjumps)
{ byte rm,modrm,sib;
rm=(byte)((data[0]&0xc0)>>6);
modrm=(byte)(data[0]&0x07);
switch(rm)
{ case 0:
if(options.mode32)
{ if(modrm==5) // disp32 only.
{ *toffs=((dword *)(&data[1]))[0];
*numjumps=1;
}
else if(modrm==4) // case 4=sib
{ sib=data[1];
if((sib&0x07)==5)
*toffs=((dword *)(&data[2]))[0]; // disp32
else
return false; // no disp
if(((sib>>3)&0x07)==4)
*numjumps=1; // no scaled index reg
else
{ *indexreg=(byte)((sib>>3)&0x07);
switch(sib>>6)
{ case 0:
*indexamount=1;
break;
case 1:
*indexamount=2;
break;
case 2:
*indexamount=4;
break;
case 3:
*indexamount=8;
break;
}
}
}
else
return false; // no disp
}
else // 16-bit mode
{ if(modrm==6) // disp16 only
{ *toffs=((word *)(&data[1]))[0];
*numjumps=1;
}
else
return false; // no disp
}
break;
case 1:
return false; // all disp8 offsets - don't follow
case 2:
if(options.mode32)
{ if(modrm==4) // case 4=sib
{ sib=data[1];
*toffs=((dword *)(&data[2]))[0];
*indexreg2=(byte)(sib&0x07);
if(((sib>>3)&0x07)==4); // no scaled index reg
else
{ *indexreg=(byte)((sib>>3)&0x07);
switch(sib>>6)
{ case 0:
*indexamount=1;
break;
case 1:
*indexamount=2;
break;
case 2:
*indexamount=4;
break;
case 3:
*indexamount=8;
break;
}
}
}
else
{ *toffs=((dword *)(&data[1]))[0];
*indexreg2=(byte)(data[0]&0x07);
}
}
else // 16bit mode
{ *toffs=((word *)(&data[1]))[0];
*indexreg=(byte)(data[0]&0x07); // NB double index reg eg bx+si
}
break;
case 3:
// case 3 - no jump table offset present. indirect jump.
return false;
}
return true;
}
/************************************************************************
* disjumptable *
* - this was written some ago as a quick hack for decoding jump tables *
* - it tries to obtain information on the table itself, and looks for *
* an indication of the number of items in the table by examining *
* prior instructions, although it is quite unintelligent in some *
* ways. *
* - it also looks for indextables which are used in complex jumptables *
* to decode an initial case number for the jumptable. *
* - although good for some compilers the output from some modern *
* compilers does not fare well in the analysis. *
************************************************************************/
void disasm::disjumptable(lptr loc)
{ dsmitem *investigate;
dsegitem *dblock,*idblock;
byte *data;
byte pbyte; // prefix byte
lptr t,it,index,xr;
int numjumps,inumjumps;
int i;
byte indexreg,indexamount,indexreg2;
byte iindexreg,iindexamount,iindexreg2;
char tablename[20],tablenum[10];
bool itable;
pbyte=0;
numjumps=0;
indexreg=0;
indexreg2=0;
indexamount=0;
inumjumps=0;
iindexreg=0;
iindexreg2=0;
iindexamount=0;
investigate=dsmfindaddrtype(loc,dsmcode);
if(investigate==NULL)
return;
// check that inst is still there/ correct type of jump
// adjust for any segment overrides added since
if((loc-investigate->addr)<4)
loc.offs=investigate->addr.offs;
if((investigate->addr!=loc)||(investigate->type!=dsmcode))
return;
if(DSMITEM_ARG1(investigate)!=ARG_MODRM)
return;
if(!(investigate->flags&(FLAGS_JMP|FLAGS_CALL|FLAGS_CJMP)))
return;
data=investigate->data+investigate->modrm;
if(!interpretmod(data,&t.offs,&indexreg,&indexreg2,&indexamount,&numjumps))
return;
// find target - jump table, need to use default ds:/ check for cs: override
if(investigate->flags&FLAGS_SEGPR
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -