📄 disasm.cpp
字号:
if (pfixup==NULL)
pfixup=cmd+2;
da->fixupsize+=4;
if (addr==0)
da->zeroconst=1;
seg=SEG_DS;
Memadr(seg,"",addr,dsize);
}
}
// Next possibility: 32-bit address with SIB byte.
else if ((c & 0x07)==0x04)
{ // SIB addresation
sib=cmd[2]; hassib=1;
*s='\0';
if (c==0x04 && (sib & 0x07)==0x05)
{
dispsize=4; // Immediate address without base
if (size<7)
da->error=DAE_CROSS; // Disp32 outside the memory block
else
{
da->adrconst=addr=*(ulong *)(cmd+3);
if (pfixup==NULL)
pfixup=cmd+3;
da->fixupsize+=4;
if (addr==0)
da->zeroconst=1;
if ((sib & 0x38)!=0x20)
{ // Index register present
da->indexed=1;
if (type==MRJ)
da->jmptable=addr; };
seg=SEG_DS;
}
}
else
{ // Base and, eventually, displacement
if ((c & 0xC0)==0x40)
{ // 8-bit displacement
dispsize=1;
if (size<4)
da->error=DAE_CROSS;
else
{
da->adrconst=addr=(signed char)cmd[3];
if (addr==0) da->zeroconst=1;
}
}
else if ((c & 0xC0)==0x80)
{ // 32-bit displacement
dispsize=4;
if (size<7)
da->error=DAE_CROSS; // Disp32 outside the memory block
else
{
da->adrconst=addr=*(ulong *)(cmd+3);
if (pfixup==NULL)
pfixup=cmd+3;
da->fixupsize+=4;
if (addr==0)
da->zeroconst=1;
// Most compilers use address of type [index*4+displacement] to
// address jump table (switch). But, for completeness, I allow all
// cases which include index with scale 1 or 4, base or both.
if (type==MRJ)
da->jmptable=addr;
}
}
da->indexed=1;
j=sib & 0x07;
if (mode>=DISASM_FILE)
{
strcpy(s,regname[2][j]);
seg=addr32[j].defseg;
da->addrreg1 = j;//
}
}
if ((sib & 0x38)!=0x20)
{ // Scaled index present
if ((sib & 0xC0)==0x40)
da->indexed=2;
else if ((sib & 0xC0)==0x80)
da->indexed=4;
else if ((sib & 0xC0)==0xC0)
da->indexed=8;
else
da->indexed=1;
};
if (mode>=DISASM_FILE && da->error==DAE_NOERR)
{
if ((sib & 0x38)!=0x20)
{ // Scaled index present
if (*s!='\0')
strcat(s,"+");
strcat(s,addr32[(sib>>3) & 0x07].descr);
da->regsscale = 1;
da->addrreg2 = (sib>>3) & 0x07;//第2个寄存器偏移
if ((sib & 0xC0)==0x40)
{
da->jmptable=0; // Hardly a switch!
strcat(s,"*2");
da->regsscale = 2;
}
else if ((sib & 0xC0)==0x80)
{
strcat(s,"*4");
da->regsscale = 4;
}
else if ((sib & 0xC0)==0xC0)
{
da->jmptable=0; // Hardly a switch!
strcat(s,"*8");
da->regsscale = 8;
}
}
Memadr(seg,s,addr,dsize);
};
}
// Last possibility: 32-bit address without SIB byte.
// 最后一个可能: 32位地址
else
{ // No SIB
if ((c & 0xC0)==0x40)
{
dispsize=1;
if (size<3)
da->error=DAE_CROSS; // Disp8 outside the memory block
else
{
da->adrconst=addr=(signed char)cmd[2];
if (addr==0)
da->zeroconst=1;
}
}
else if ((c & 0xC0)==0x80)
{
dispsize=4;
if (size<6)
da->error=DAE_CROSS; // Disp32 outside the memory block
else
{
da->adrconst=addr=*(ulong *)(cmd+2);
if (pfixup==NULL)
pfixup=cmd+2;
da->fixupsize+=4;
if (addr==0)
da->zeroconst=1;
if (type==MRJ)
da->jmptable=addr;
}
}
da->indexed=1;
if (mode>=DISASM_FILE && da->error==DAE_NOERR)
{
seg=addr32[c & 0x07].defseg;
da->addrreg1 = (c & 0x07);
Memadr(seg,addr32[c & 0x07].descr,addr,dsize);
}
}
}
// Disassemble implicit source of string operations and, if available, dump
// address and contents.
//static void DecodeSO(void)
static int DecodeSO(void)
{
if (mode<DISASM_FILE)
return -1; // No need to decode
if (datasize==1)
da->memtype=DEC_BYTE;
else if (datasize==2)
da->memtype=DEC_WORD;
else if (datasize==4)
da->memtype=DEC_DWORD;
da->indexed=1;
Memadr(SEG_DS,regname[addrsize==2?1:2][REG_ESI],0L,datasize);
da->reg[stoperand] = REG_ESI;
return REG_ESI;
}
// Disassemble implicit destination of string operations and, if available,
// dump address and contents. Destination always uses segment ES, and this
// setting cannot be overridden.
//static void DecodeDE(void)
static int DecodeDE(void)
{
int seg;
if (mode<DISASM_FILE)
return -1; // No need to decode
if (datasize==1)
da->memtype=DEC_BYTE;
else if (datasize==2)
da->memtype=DEC_WORD;
else if (datasize==4)
da->memtype=DEC_DWORD;
da->indexed=1;
seg = segprefix;
segprefix=SEG_ES; // Fake Memadr by changing segment prefix
Memadr(SEG_DS,regname[addrsize==2?1:2][REG_EDI],0L,datasize);
segprefix=seg; // Restore segment prefix
da->reg[stoperand] = REG_EDI;
return REG_EDI;
};
// Decode XLAT operand and, if available, dump address and contents.
static void DecodeXL(void)
{
if (mode<DISASM_FILE)
return; // No need to decode
da->memtype=DEC_BYTE;
da->indexed=1;
Memadr(SEG_DS,(addrsize==2?"BX+AL":"EBX+AL"),0L,1);
};
// Decode immediate operand of size constsize. If sxt is non-zero, byte operand
// should be sign-extended to sxt bytes. If type of immediate constant assumes
// this, small negative operands may be displayed as signed negative numbers.
// Note that in most cases immediate operands are not shown in comment window.
static void DecodeIM(int constsize,int sxt,int type)
{
int i;
signed long data;
ulong l;
char name[TEXTLEN],comment[TEXTLEN] = {0};
immsize+=constsize; // Allows several immediate operands
if (mode<DISASM_DATA)
return;
//sprintf_s(da->vm_name,"%s_IMM%02d",da->vm_name,constsize*8);
sprintf_s(da->vm_name,"%s_IMM32",da->vm_name);//IMM只有32位
da->optype[stoperand] = Imm;
l=1+hasrm+hassib+dispsize+(immsize-constsize);
data=0;
if (size<l+constsize)
da->error=DAE_CROSS;
else if (constsize==1)
{
if (sxt==0)
data=(uchar)cmd[l];
else
data=(signed char)cmd[l];
if (type==IMS && ((data & 0xE0)!=0 || data==0))
{
da->warnings|=DAW_SHIFT;
da->cmdtype|=C_RARE;
}
}
else if (constsize==2)
{
if (sxt==0)
data=*(ushort *)(cmd+l);
else
data=*(short *)(cmd+l);
}
else
{
data=*(long *)(cmd+l);
if (pfixup==NULL)
pfixup=cmd+l;
da->fixupsize+=4;
}
if (sxt==2)
data&=0x0000FFFF;
if (data==0 && da->error==0)
da->zeroconst=1;
// Command ENTER, as an exception from Intel's rules, has two immediate
// constants. As the second constant is rarely used, I exclude it from
// search if the first constant is non-zero (which is usually the case).
if (da->immconst==0)
da->immconst=data;
if (mode>=DISASM_FILE && da->error==DAE_NOERR)
{
if (mode>=DISASM_CODE && type!=IMU)
i=Decodeaddress(data,name,TEXTLEN-nresult-24,comment);
else
{
i=0; comment[0]='\0';
}
if (i!=0 && symbolic!=0)
{
strcpy(da->result+nresult,name); nresult+=i;
}
else if (type==IMU || type==IMS || type==IM2 || data>=0 || data<NEGLIMIT)
nresult+=sprintf(da->result+nresult,"%lX",data);
else
nresult+=sprintf(da->result+nresult,"-%lX",-data);
if (addcomment && comment[0]!='\0')
strcpy(da->comment,comment);
}
}
// Decode VxD service name (always 4-byte).
static void DecodeVX(void)
{
ulong l,data;
immsize+=4; // Allows several immediate operands
if (mode<DISASM_DATA)
return;
l=1+hasrm+hassib+dispsize+(immsize-4);
if (size<l+4)
{
da->error=DAE_CROSS;
return;
}
data=*(long *)(cmd+l);
if (data==0 && da->error==0)
da->zeroconst=1;
if (da->immconst==0)
da->immconst=data;
if (mode>=DISASM_FILE && da->error==DAE_NOERR)
{
if ((data & 0x00008000)!=0 && memicmp("VxDCall",da->result,7)==0)
memcpy(da->result,lowercase?"vxdjump":"VxDJump",7);
nresult+=sprintf(da->result+nresult,"%lX",data);
}
}
// Decode implicit constant 1 (used in shift commands). This operand is so
// insignificant that it is never shown in comment window.
static void DecodeC1(void)
{
if (mode<DISASM_DATA)
return;
da->immconst=1;
if (mode>=DISASM_FILE)
nresult+=sprintf(da->result+nresult,"1");
}
// Decode immediate absolute data address. This operand is used in 8080-
// compatible commands which allow to move data from memory to accumulator and
// back. Note that bytes ModRM and SIB never appear in commands with IA operand.
static void DecodeIA(void)
{
ulong addr;
if (size<1+addrsize)
{
da->error=DAE_CROSS;
return;
};
dispsize=addrsize;
if (mode<DISASM_DATA)
return;
if (datasize==1)
da->memtype=DEC_BYTE;
else if (datasize==2)
da->memtype=DEC_WORD;
else if (datasize==4)
da->memtype=DEC_DWORD;
if (addrsize==2)
addr=*(ushort *)(cmd+1);
else
{
addr=*(ulong *)(cmd+1);
if (pfixup==NULL)
pfixup=cmd+1;
da->fixupsize+=4;
}
da->adrconst=addr;
if (addr==0)
da->zeroconst=1;
if (mode>=DISASM_FILE)
{
Memadr(SEG_DS,"",addr,datasize);
}
}
// Decodes jump relative to nextip of size offsize.
static void DecodeRJ(ulong offsize,ulong nextip)
{
sprintf_s(da->vm_name,"%s_IMM%02d",da->vm_name,4*8);//不管长跳短跳都认为是32位地址
da->optype[stoperand] = Imm;
int i;
ulong addr;
char s[TEXTLEN];
if (size<offsize+1)
{
da->error=DAE_CROSS;
return;
}
dispsize=offsize; // Interpret offset as displacement
if (mode<DISASM_DATA)
return;
if (offsize==1)//短跳转
{
addr=(signed char)cmd[1]+nextip;
}
else if (offsize==2)
addr=*(signed short *)(cmd+1)+nextip;
else
addr=*(ulong *)(cmd+1)+nextip;
if (datasize==2)
addr&=0xFFFF;
da->jmpconst=addr;
if (addr==0)
da->zeroconst=1;
if (mode>=DISASM_FILE)
{
if (offsize==1)
nresult+=sprintf(da->result+nresult, "%s ",(lowercase==0?"SHORT":"short"));
if (mode>=DISASM_CODE)
i=Decodeaddress(addr,s,TEXTLEN,da->comment);
else
i=0;
if (symbolic==0 || i==0)
nresult+=sprintf(da->result+nresult,"%08lX",addr);
else
nresult+=sprintf(da->result+nresult,"%.*s",TEXTLEN-nresult-25,s);
if (symbolic==0 && i!=0 && da->comment[0]=='\0')
strcpy(da->comment,s);
}
}
// Decode immediate absolute far jump address. In flat model, such addresses
// are not used (mostly because selector is specified directly in the command),
// so I neither decode as symbol nor comment it. To allow search for selector
// by value, I interprete it as an immediate constant.
static void DecodeJF(void)
{
ulong addr,seg;
if (size<1+addrsize+2)
{
da->error=DAE_CROSS;
return;
}
dispsize=addrsize; immsize=2; // Non-trivial but allowed interpretation
if (mode<DISASM_DATA)
return;
if (addrsize==2)
{
addr=*(ushort *)(cmd+1);
seg=*(ushort *)(cmd+3);
}
else
{
addr=*(ulong *)(cmd+1);
seg=*(ushort *)(cmd+5);
}
da->jmpconst=addr;
da->immconst=seg;
if (addr==0 || seg==0)
da->zeroconst=1;
if (mode>=DISASM_FILE)
{
nresult+=sprintf(da->result+nresult,"%s %04X:%08X",(lowercase==0?"FAR":"far"),seg,addr);
}
}
// Decode segment register. In flat model, operands of this type are seldom.
static void DecodeSG(int index)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -