?? disasm.c
字號:
da->adrconst=addr;
if (addr==0) da->zeroconst=1;
seg=addr16[c & 0x07].defseg;
Memadr(seg,addr16[c & 0x07].descr,addr,dsize);
};
};
}
// Next possibility: immediate 32-bit address.
else if (c==0x05) { // Special case of immediate address
dispsize=4;
if (size<6)
da->error=DAE_CROSS; // Disp32 outside the memory block
else if (mode>=DISASM_DATA) {
da->adrconst=addr=*(ulong *)(cmd+2);
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;
};
};
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);
if ((sib & 0xC0)==0x40) {
da->jmptable=0; // Hardly a switch!
strcat(s,"*2"); }
else if ((sib & 0xC0)==0x80)
strcat(s,"*4");
else if ((sib & 0xC0)==0xC0) {
da->jmptable=0; // Hardly a switch!
strcat(s,"*8");
};
};
Memadr(seg,s,addr,dsize);
};
}
// Last possibility: 32-bit address without SIB byte.
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;
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) {
if (mode<DISASM_FILE) return; // 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);
};
// 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) {
int seg;
if (mode<DISASM_FILE) return; // 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
};
// 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];
immsize+=constsize; // Allows several immediate operands
if (mode<DISASM_DATA) return;
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) {
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;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -