📄 asmserv.cpp
字号:
};
const t_cmddata vxdcmd = // Decoding of VxD calls (Win95/98)
{ 0x00FFFF, 0x0020CD, 2,00, VXD,NNN,NNN, C_CAL+C_RARE+0, "VxDCall" };
// Bit combinations that can be potentially dangerous when executed:
const t_cmddata dangerous[] = {
{ 0x00FFFF, 0x00DCF7, 0,0,0,0,0,C_DANGER95,
"Win95/98 may crash when NEG ESP is executed" },
{ 0x00FFFF, 0x00D4F7, 0,0,0,0,0,C_DANGER95,
"Win95/98 may crash when NOT ESP is executed" },
{ 0x00FFFF, 0x0020CD, 0,0,0,0,0,C_DANGER95,
"Win95/98 may crash when VxD call is executed in user mode" },
{ 0xF8FFFF, 0xC8C70F, 0,0,0,0,1,C_DANGERLOCK,
"LOCK CMPXCHG8B may crash some processors when executed" },
{ 0x000000, 0x000000, 0,0,0,0,0,0, "" }
};
// Decodes address into symb (nsymb bytes long, including the terminating zero
// character) and comments its possible meaning. Returns number of bytes in
// symb not including terminating zero.
int Decodeaddress(ulong addr,char *symb,int nsymb,char *comment)
{
// Environment-specific routine! Do it yourself!
return 0;
};
// Decodes and prints 32-bit float f into string s (which must be at least 16
// bytes long). Returns resulting length of the string.
int Printfloat4(char *s,float f) {
int k;
if (*(ulong *)&f==0x7F800000L)
k=sprintf(s,"+INF 7F800000");
else if (*(ulong *)&f==0xFF800000L)
k=sprintf(s,"-INF FF800000");
else if ((*(ulong *)&f & 0xFF800000L)==0x7F800000L)
k=sprintf(s,"+NAN %08lX",*(ulong *)&f);
else if ((*(ulong *)&f & 0xFF800000L)==0xFF800000L)
k=sprintf(s,"-NAN %08lX",*(ulong *)&f);
else if (f==0.0) // By default, 0 is printed without
k=sprintf(s,"0.0"); // decimal point, which I don't want.
else
k=sprintf(s,"%#.7g",f);
return k;
};
// Decodes and prints 64-bit double d into string s (at least 25 bytes long).
// Returns resulting length of the string.
int Printfloat8(char *s,double d) {
int k;
ulong lod,hid;
lod=((ulong *)&d)[0];
hid=((ulong *)&d)[1];
if (lod==0 && hid==0x7F800000L)
k=sprintf(s,"+INF 7F800000 00000000");
else if (lod==0 && hid==0xFF800000L)
k=sprintf(s,"-INF FF800000 00000000");
else if ((hid & 0xFFF00000L)==0x7FF00000)
k=sprintf(s,"+NAN %08lX %08lX",hid,lod);
else if ((hid & 0xFFF00000L)==0xFFF00000)
k=sprintf(s,"-NAN %08lX %08lX",hid,lod);
else if (d==0.0) // Print 0 with decimal point
k=sprintf(s,"0.0");
else
k=sprintf(s,"%#.16lg",d);
return k;
};
// Decodes and prints 80-bit long double ext into string s (at least 32 bytes
// long). Procedure correctly displays all, even invalid, numbers without
// arithmetical exceptions. Returns resulting length of the string.
int Printfloat10(char *s,long double ext) {
int k;
char *e=(char *)&ext;
if (*(ulong *)e==0 && *(ushort *)(e+4)==0 && *(ulong *)(e+6)==0x7FFF8000L)
k=sprintf(s,"+INF 7FFF 80000000 00000000");
else if (*(ulong *)e==0 && *(ushort *)(e+4)==0 &&
*(ulong *)(e+6)==0xFFFF8000L)
k=sprintf(s,"-INF FFFF 80000000 00000000");
else if ((*(ulong *)(e+6) & 0x7FFF8000L)==0x7FFF8000L)
k=sprintf(s,"%cNAN %04X %08lX %08lX",(e[9] & 0x80)==0?'+':'-',
(int)(*(ushort *)(e+8)),*(ulong *)(e+4),*(ulong *)e);
else if ((*(ulong *)(e+6) & 0x7FFF0000L)==0x7FFF0000L)
k=sprintf(s,"%c??? %04X %08lX %08lX",(e[9] & 0x80)==0?'+':'-',
(int)(*(ushort *)(e+8)),*(ulong *)(e+4),*(ulong *)e);
else if ((*(ulong *)(e+6) & 0x7FFF0000L)!=0 &&
(*(ulong *)(e+6) & 0x00008000)==0)
k=sprintf(s,"%cUNORM %04X %08lX %08lX",(e[9] & 0x80)==0?'+':'-',
(int)(*(ushort *)(e+8)),*(ulong *)(e+4),*(ulong *)e);
else if (*(ulong *)e==0 && *(ushort *)(e+4)==0 &&
*(ulong *)(e+6)==0x80000000L)
k=sprintf(s,"-0.0"); // Negative floating 0.0
else if (ext==0.0)
k=sprintf(s,"0.0"); // Print 0 with decimal point
else if ((ext>=-1.e10 && ext<-1.0) || (ext>1.0 && ext<=1.e10))
k=sprintf(s,"%#.20Lg",ext);
else if ((ext>=-1.0 && ext<=-1.e-5) || (ext>=1.e-5 && ext<=1.0))
k=sprintf(s,"%#.19Lf",ext);
else
k=sprintf(s,"%#.19Le",ext);
return k;
};
// Decodes and prints 64-bit 3DNow! element f into string s (which must be at
// least 30 bytes long). Returns resulting length of the string.
int Print3dnow(char *s,char *f) {
int n;
n=Printfloat4(s,*(float *)(f+4));
n+=sprintf(s+n,", ");
n+=Printfloat4(s+n,*(float *)f);
return n;
};
// Function attempts to calculate address of assembler instruction which is n
// lines back in the listing. Maximal stepback is limited to 127. In general,
// this is rather non-trivial task. Proposed solution may cause problems which
// however are not critical here.
ulong Disassembleback(char *block,ulong base,ulong size,ulong ip,int n) {
int i;
ulong abuf[131],addr,back,cmdsize;
char *pdata;
t_disasm da;
memset(&da,0,sizeof(t_disasm));
if (block==NULL)
return 0; // Error, no code!
if (n<0)
n=0;
else
if (n>127)
n=127; // Try to correct obvious errors
if (ip>base+size)
ip=base+size;
if (n==0)
return ip; // Obvious answers
if (ip<=base+n)
return base;
back=MAXCMDSIZE*(n+3); // Command length limited to MAXCMDSIZE
if (ip<base+back)
back=ip-base;
addr=ip-back;
pdata=block+(addr-base);
for (i=0; addr<ip; i++)
{
abuf[i%128]=addr;
cmdsize=Disasm(pdata,back,addr,&da,DISASM_SIZE);
pdata+=cmdsize;
addr+=cmdsize;
back-=cmdsize; };
if (i<n) return abuf[0];
else return abuf[(i-n+128)%128];
};
// Function attempts to calculate address of assembler instruction which is n
// lines forward in the listing.
ulong Disassembleforward(char *block,ulong base,ulong size,ulong ip,int n)
{
int i;
ulong cmdsize;
char *pdata;
t_disasm da;
memset(&da,0,sizeof(t_disasm));
if (block==NULL)
return 0; // Error, no code!
if (ip<base)
ip=base; // Try to correct obvious errors
if (ip>base+size)
ip=base+size;
if (n<=0)
return ip;
pdata=block+(ip-base);
size-=(ip-base);
for (i=0; i<n && size>0; i++)
{
cmdsize=Disasm(pdata,size,ip,&da,DISASM_SIZE);
pdata+=cmdsize;
ip+=cmdsize;
size-=cmdsize;
}
return ip;
}
// Service function, checks whether command at offset addr in data is a valid
// filling command (usually some kind of NOP) used to align code to a specified
// (align=power of 2, 0 means no alignment) border. Returns length of filling
// command in bytes or 0 if command is not a recognized filling.
int Isfilling(ulong addr,char *data,ulong size,ulong align) {
if (data==NULL) return 0; // Invalid parameters
// Convert power of 2 to bitmask.
align--;
// Many compilers and assemblers use NOP or INT3 as filling:
if (addr<size && (data[addr]==NOP || data[addr]==INT3) &&
(addr & align)!=0)
return 1;
// Borland compilers use XCHG EBX,EBX (87,DB) to fill holes. For the sake of
// completeness, allow any XCHG or MOV of register with self.
if (addr+1<size &&
((data[addr] & 0xFE)==0x86 || (data[addr] & 0xFC)==0x88) &&
(data[addr+1] & 0xC0)==0xC0 &&
(((data[addr+1]>>3)^data[addr+1]) & 0x07)==0 &&
(addr & align)!=0x0F && (addr & align)!=0x00)
return 2;
// Some other programs use LEA EAX,[EAX] (8D,40,00). For completeness, allow
// any register except ESP (here address is constructed differently):
if (addr+2<size &&
data[addr]==0x8D && (data[addr+1] & 0xC0)==0x40 && data[addr+2]==0x00 &&
(data[addr+1] & 0x07)!=REG_ESP &&
(((data[addr+1]>>3)^data[addr+1]) & 0x07)==0)
return 3;
// WATCOM compilers use LEA EAX,[EAX] with SIB and 8-bit zero (8D,44,20,00)
// and without SIB but with 32-bit immediate zero (8D,80,00,00,00,00) and
// alike:
if (addr+3<size &&
data[addr]==0x8D && (data[addr+1] & 0xC0)==0x40 && data[addr+3]==0x00 &&
(((data[addr+1]>>3)^data[addr+2]) & 0x07)==0)
return 4;
if (addr+5<size && data[addr]==0x8D &&
(data[addr+1] & 0xC0)==0x80 && *(ulong *)(data+addr+2)==0 &&
(data[addr+1] & 0x07)!=REG_ESP &&
(((data[addr+1]>>3)^data[addr+1]) & 0x07)==0)
return 6;
// Unable to recognize this code as a valid filling.
return 0;
};