⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 disasm.c

📁 PE Monitor是一个小调试器和反汇编器
💻 C
📖 第 1 页 / 共 4 页
字号:
        if (addr==0) da->zeroconst=1;
        seg=SEG_DS;
        Memadr(seg,"",addr,dsize);
      }; }
    else {
      da->indexed=1;
      if ((c & 0xC0)==0x40) {          // 8-bit signed displacement
        if (size<3) da->error=DAE_CROSS;
        else addr=(signed char)cmd[2] & 0xFFFF;
        dispsize=1; }
      else if ((c & 0xC0)==0x80) {     // 16-bit unsigned displacement
        if (size<4) da->error=DAE_CROSS;
        else addr=*(ushort *)(cmd+2);
        dispsize=2; };
      if (mode>=DISASM_DATA && da->error==DAE_NOERR) {
        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] = { 0 };
  char comment[TEXTLEN] = { 0 };
  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;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -