📄 disasm.cpp
字号:
/************************************************************************
* disasm.cpp *
* This is a fairly big class, even having split off the disio class. *
* The class is the class responsible for maintaining the main *
* disassembly structures of Borg, and for performing the disassembly *
* analysis. The class has some very old code in it, and hasn't *
* undergone much improvement for some time, so parts could do with *
* rewriting. *
************************************************************************/
#include <windows.h>
#include <stdio.h>
#include "disasm.h"
#include "dasm.h"
#include "xref.h"
#include "data.h"
#include "gname.h"
#include "schedule.h"
#include "relocs.h"
#include "debug.h"
/************************************************************************
* constructor function *
* - resets a few class globals *
************************************************************************/
disasm::disasm()
{ lastdis=NULL;
itables=0;
jtables=0;
irefs=0;
}
/************************************************************************
* destructor function is currently null *
************************************************************************/
disasm::~disasm()
{
}
/************************************************************************
* initnewdsm *
* - this is some common code i pulled out and put into a function on *
* its own. when a new disassembly item is created it initialises some *
* of the stucture. *
************************************************************************/
void disasm::initnewdsm(dsmitem *newdsm,lptr loc,dsmitemtype typ)
{ newdsm->addr=loc;
newdsm->type=typ;
newdsm->override=over_null;
newdsm->modrm=0;
newdsm->mode32=options.mode32;
newdsm->flags=0;
newdsm->displayflags=0;
}
/************************************************************************
* dissettable *
* - this function sets up the processor table. It should be called once *
* when the processor has been selected and before disassembly begins *
************************************************************************/
void disasm::dissettable(void)
{ int i=0;
while((procnames[i].num!=0)&&(procnames[i].num!=options.processor))
i++;
itable=procnames[i].tab;
}
/************************************************************************
* nextiter_code *
* - a basic building block piece of code which skips to the next *
* code/data item in the disassembly (identified by having a length), *
* or returns null if it gets to the end *
************************************************************************/
dsmitem *disasm::nextiter_code(dsmitem *tblock)
{ if(tblock!=NULL)
{ while(!tblock->length)
{ tblock=nextiterator();
if(tblock==NULL)
break;
}
}
return tblock;
}
/************************************************************************
* dsmitem_contains_loc *
* - a basic building block piece of code which returns true if the *
* dsmitem straddles loc *
* - added in v2.22 *
************************************************************************/
bool disasm::dsmitem_contains_loc(dsmitem *d,lptr loc)
{ if((d->addr<loc)&&(d->addr+d->length>loc))
return true;
return false;
}
/************************************************************************
* dsmfindaddrtype *
* - a basic building block piece of code which returns a dsmitem *
* pointer using the list class find to find it by loc and type *
* - added in v2.22 *
************************************************************************/
dsmitem *disasm::dsmfindaddrtype(lptr loc,dsmitemtype typ)
{ dsmitem fnd;
fnd.addr=loc;
fnd.type=typ;
return find(&fnd);
}
/************************************************************************
* oktoname *
* - this checks that we arent trying to name a location which is in the *
* middle of an instruction and returns true if it is ok to assign a *
* name here *
************************************************************************/
bool disasm::oktoname(lptr loc)
{ dsmitem *checker;
// check table for the given address
checker=dsmfindaddrtype(loc,dsmcode);
// NULL returned - must be ok.
if(checker==NULL)
return true;
// check bounds.
if(dsmitem_contains_loc(checker,loc))
return false;
return true;
}
/************************************************************************
* checkvalid *
* - this is called when adding an instruction disassembly to the list *
* - it checks that an instruction isnt being added which would overlap *
* with instructions already in the database *
* - it will delete any names and xrefs or comments which get in the way *
************************************************************************/
bool disasm::checkvalid(dsmitem *newdsm)
{ dsmitem *lstdsm,*deldsm;
lstdsm=dsmfindaddrtype(newdsm->addr,dsmnull);
if(lstdsm==NULL)
return true;
// go through the disassembly items nearby and check for any overlaps.
do
{ if(lstdsm->length)
{ if(newdsm->addr.between(lstdsm->addr,lstdsm->addr+lstdsm->length-1))
return false;
if(lstdsm->addr.between(newdsm->addr,newdsm->addr+newdsm->length-1))
return false;
}
if(lstdsm->addr>=(newdsm->addr+newdsm->length))
break;
lstdsm=nextiterator();
} while(lstdsm!=NULL);
deldsm=dsmfindaddrtype(newdsm->addr,dsmnull);
// now go through them again, and this time delete any names/xrefs which get
// in the way.
do
{ if((!deldsm->length)&&(deldsm->addr.segm==newdsm->addr.segm))
{ if(dsmitem_contains_loc(newdsm,deldsm->addr))
{ switch(deldsm->type)
{ case dsmnameloc:
#ifdef DEBUG
DebugMessage("Deleting Name : %s",deldsm->tptr);
#endif
name.delname(deldsm->addr);
break;
case dsmxref:
#ifdef DEBUG
DebugMessage("Deleting Xref at : %04lx:%04lx",deldsm->addr.segm,deldsm->addr.offs);
#endif
break;
default:
break;
}
delfrom(deldsm);
deldsm=dsmfindaddrtype(newdsm->addr,dsmnull);
if(deldsm==NULL)
return true;
}
}
if(newdsm->addr+newdsm->length<=deldsm->addr)
break;
deldsm=nextiterator();
} while(lstdsm!=NULL);
return true;
}
/************************************************************************
* setcodeoverride *
* - sets a particular override for a given location *
* - this subfunction was created in v211 as it was duplicated code in *
* several functions *
************************************************************************/
void disasm::setcodeoverride(lptr loc,byteoverride typ)
{ dsmitem *findit;
findit=dsmfindaddrtype(loc,dsmcode);
if(findit!=NULL)
{ if((findit->addr==loc)&&(findit->type==dsmcode))
{ findit->override=typ;
dio.updatewindowifinrange(loc);
}
}
}
/************************************************************************
* disargnegate *
* - as well as an override I added some displayflags for a disassembly *
* item. There is a negation item which allows immediates to be *
* negated when displayed, and this function sets or resets the flag *
************************************************************************/
void disasm::disargnegate(lptr loc)
{ dsmitem *findit;
findit=dsmfindaddrtype(loc,dsmcode);
if(findit!=NULL)
{ if((findit->addr==loc)&&(findit->type==dsmcode))
{ findit->displayflags=(byte)(findit->displayflags^DISPFLAG_NEGATE);
dio.updatewindowifinrange(loc);
}
}
}
/************************************************************************
* disargoverdec *
* - sets the decimal override for a disassembly item, given the *
* location *
************************************************************************/
void disasm::disargoverdec(lptr loc)
{ setcodeoverride(loc,over_decimal);
}
/************************************************************************
* disargoversingle *
* - sets the single (float) override for a disassembly item, given the *
* location *
************************************************************************/
void disasm::disargoversingle(lptr loc)
{ setcodeoverride(loc,over_single);
}
/************************************************************************
* disargoverhex *
* - sets the hex (null) override for a disassembly item, given the *
* location *
************************************************************************/
void disasm::disargoverhex(lptr loc)
{ setcodeoverride(loc,over_null);
}
/************************************************************************
* disargoverchar *
* - sets the character override for a disassembly item, given the *
* location *
************************************************************************/
void disasm::disargoverchar(lptr loc)
{ setcodeoverride(loc,over_char);
}
/************************************************************************
* disargoveroffsetdseg *
* - sets the dseg override for a disassembly item, given the location *
* - NB at present it does not affect xrefs, to be done....... *
************************************************************************/
void disasm::disargoveroffsetdseg(lptr loc)
{ dsmitem *findit;
lptr j;
findit=dsmfindaddrtype(loc,dsmcode);
if(findit!=NULL)
{ if((findit->addr==loc)&&(findit->type==dsmcode))
{ findit->override=over_dsoffset;
dio.updatewindowifinrange(loc);
if((options.mode32)&&(findit->length>=4))
{ j.assign(options.dseg,((dword *)(&findit->data[findit->length-4]))[0]);
xrefs.addxref(j,loc);
}
}
}
}
/************************************************************************
* disdatastring *
* - disassembles a string at location loc. *
* - also names the location using the string. *
* - C style *
************************************************************************/
void disasm::disdatastring(lptr loc)
{ dsegitem *dblock;
dsmitem *newdsm;
dword maxlen,actuallen;
char callit[GNAME_MAXLEN+1];
dblock=dta.findseg(loc);
if(dblock==NULL)
return;
maxlen=dblock->size-(loc-dblock->addr);
if(maxlen<2)
return;
actuallen=0;
while((dblock->data+(loc-dblock->addr)+actuallen)[0])
{ actuallen++;
maxlen--;
if(!maxlen)
return;
}
actuallen++;
if(actuallen>0xffff)
return; // tooo big
newdsm=new dsmitem;
initnewdsm(newdsm,loc,dsmcode);
newdsm->tptr=&asmstr[0];
newdsm->length=(word)actuallen; // string length
newdsm->data=dblock->data+(loc-dblock->addr);
if(checkvalid(newdsm))
{ callit[0]='s';
callit[1]='_';
if(actuallen>GNAME_MAXLEN-2)
{ callit[GNAME_MAXLEN]=0;
lstrcpyn(callit+2,(char *)newdsm->data,GNAME_MAXLEN-3);
}
else lstrcpy(callit+2,(char *)newdsm->data);
cleanstring(callit);
addto(newdsm);
name.addname(newdsm->addr,callit);
//check if need to update window.
dio.updatewindowifinrange(loc);
}
else
delete newdsm;
}
/************************************************************************
* disdataucstring *
* - disassembles a string at location loc. *
* - also names the location using the string. *
* - unicode C style *
************************************************************************/
void disasm::disdataucstring(lptr loc)
{ // unicode c-style string.
dsegitem *dblock;
dsmitem *newdsm;
dword maxlen,actuallen;
unsigned int i;
char callit[GNAME_MAXLEN+1];
dblock=dta.findseg(loc);
if(dblock==NULL)
return;
maxlen=dblock->size-(loc-dblock->addr);
if(maxlen<2)
return;
actuallen=0;
while((dblock->data+(loc-dblock->addr)+actuallen)[0])
{ actuallen++;
maxlen--;
if(!maxlen)
return;
actuallen++;
maxlen--;
if(!maxlen)
return;
}
actuallen+=2;
if(actuallen>0xffff)
return; // tooo big
newdsm=new dsmitem;
initnewdsm(newdsm,loc,dsmcode);
newdsm->tptr=&asmstr[3];
newdsm->length=(word)actuallen; // string length
newdsm->data=dblock->data+(loc-dblock->addr);
if(checkvalid(newdsm))
{ callit[0]='s';
callit[1]='_';
i=2;
while(i<GNAME_MAXLEN-1)
{ callit[i]=newdsm->data[(i-2)*2];
i++;
if(i*2>actuallen)
break;
}
callit[i]=0;
cleanstring(callit);
addto(newdsm);
name.addname(newdsm->addr,callit);
//check if need to update window.
dio.updatewindowifinrange(loc);
}
else
delete newdsm;
}
/************************************************************************
* disdataupstring *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -