📄 modsib-x86.c
字号:
msinfo - where to store ModR/M and SIB informationPrerequisites: ws->prefixFlags must reflect whether we are in 16 or 32 bit mode before calling this routineReturn: Upon success, total number of bytes in the ModR/M (and SIB) portion of opcode. This includes the ModR/M byte, the SIB byte (if any) and any displacement bytes, if any. Upon failure, -1.Side effects: On success, 'msinfo' is modified to point to the correct ModR/M information.*/intx86processModSib(struct disasmWorkspace *ws, unsigned char *data, struct x86OpCode *opPtr, struct x86ModSibInfo *msinfo){ unsigned char modrm; /* ModR/M byte */ unsigned char mod, /* MOD portion of ModR/M byte */ reg, /* REG portion of ModR/M byte */ rm; /* R/M portion of ModR/M byte */ unsigned char sib; /* SIB byte */ unsigned char scale, /* scale portion of SIB byte */ index, /* index portion of SIB byte */ base; /* base portion of SIB byte */ int bytes; /* number of bytes in ModR/M, SIB portion of opcode */ int hasEffectiveOperand; /* does instruction need to compute effective address? */ struct x86ModAddrInfo *modptr; struct x86ModAddrInfo *sibptr; bytes = 1; /* * Get the ModR/M byte */ modrm = *data; /* * Strip off the MOD, REG, and R/M fields */ mod = modrm >> 6; reg = (modrm >> 3) & 0x07; rm = modrm & 0x07; if ((opPtr->digit != REGRM) && (opPtr->digit != reg)) { /* * Opcodes defined with /digit must have the REG portion * of their ModR/M byte equal to "digit". This prospective * match does not so it is a bad match. */ return (-1); } modptr = x86getModAddress(ws, mod, reg, rm); if (!modptr) return (-1); /* error */ msinfo->disp = 0; sib = 0; scale = 0; index = 0; base = 0; sibptr = 0; hasEffectiveOperand = x86hasEffectiveOperand(opPtr); if (hasEffectiveOperand) { /* * Only compute SIB bytes and displacements if this opcode * has an operand which requires an effective address. Otherwise * we will end up returning an incorrect byte count. An example * instruction which has a ModR/M byte but no rm/mem operand is * psllw. */ if (modptr->flags & MF_SIB) { /* * The instruction we are disassembling contains a SIB byte */ sib = *(data + 1); ++bytes; scale = sib >> 6; index = (sib >> 3) & 0x07; base = sib & 0x07; sibptr = &x86SibTable[0][index]; if ((base == 5) && (mod == 0)) { /* * This is the special case labelled by [*] in * table 2-3 of IAS. If base is 5 and mod is 0, * a 32 bit displacement follows the SIB byte. */ msinfo->disp = x86getModSibDisplacement(data + bytes, 4); bytes += 4; } } if (modptr->flags & MF_DISP8) { msinfo->disp = x86getModSibDisplacement(data + bytes, 1); bytes += 1; } else if (modptr->flags & MF_DISP16) { msinfo->disp = x86getModSibDisplacement(data + bytes, 2); bytes += 2; } else if (modptr->flags & MF_DISP32) { msinfo->disp = x86getModSibDisplacement(data + bytes, 4); bytes += 4; } } /* if (hasEffectiveOperand) */ msinfo->modptr = modptr; msinfo->modrm = modrm; msinfo->mod = mod; msinfo->reg = reg; msinfo->rm = rm; msinfo->sibptr = sibptr; msinfo->sib = sib; msinfo->scale = scale; msinfo->index = index; msinfo->base = base; return (bytes);} /* x86processModSib() *//*x86getModAddrStr() Look up a ModR/M address offset in our string tableInputs: index - index into x86ModAddrOffsets[] (M_xxx)Return: address string corresponding to mptr*/char *x86getModAddrStr(int index){ assert((index >= 0) && (index <= M_NONE)); return (x86ModAddrOffsets[index]);} /* x86getModAddrStr() *//*x86getModRegister() This routine is called when we are looking for a register specifiedby a ModR/M byte. This can happen two ways:1. We get an r8/r16/r32 operand, in which case the register is specified by the REG field of the ModR/M byte.2. We get an rm8/rm16/rm32/mm/m64 operand with a MOD field of 3, in which case the register is specified by the RM field of the ModR/M byte.Inputs: index - either REG (for case 1) or RM (for case 2) flags - bitmask containing operand size information (BITSXX)Return: pointer to string containing corresponding register*/char *x86getModRegister(unsigned char index, unsigned int flags){ int idx; assert(index <= 7); if (flags & BITS8) idx = x86ModRegisters8[index]; else if (flags & BITS16) idx = x86ModRegisters16[index]; else if (flags & BITS32) idx = x86ModRegisters32[index]; else if (flags & BITS64) idx = M_MM0 + index; else if (flags & REG_MMX) idx = M_MM0 + index; else if (flags & REG_XMM) idx = M_XMM0 + index; else { fprintf(stderr, "x86getModRegister: warning: defaulting to 16 bits\n"); idx = x86ModRegisters16[index]; } return (x86ModAddrOffsets[idx]);} /* x86getModRegister() *//*x86getSibBaseRegister() Lookup a SIB base registerInputs: base - base portion of SIB byteReturn: register string*/char *x86getSibBaseRegister(unsigned char base){ assert(base <= 7); return (x86SibBaseRegisters[base]);} /* x86getSibBaseRegister() *//********************************************************* * INTERNAL ROUTINES * *********************************************************//*x86getModAddress() This routine searches x86ModTableXX[] to find the address offsetfor a given ModR/M byte.Inputs: ws - disasm workspace mod - mod portion of ModR/M byte reg - reg portion of ModR/M byte rm - r/m portion of ModR/M byteReturn: pointer to correct entry in x86ModTableXX[] upon success NULL upon failure*/static struct x86ModAddrInfo *x86getModAddress(struct disasmWorkspace *ws, unsigned char mod, unsigned char reg, unsigned char rm){ struct x86ModAddrInfo *mptr; assert((mod <= 3) && (reg <= 7) && (rm <= 7)); mptr = 0; if (ws->flags & DA_16BITMODE) { if (ws->prefixFlags & PX_ADDROVER) mptr = &x86ModTable32[mod][rm]; else mptr = &x86ModTable16[mod][rm]; } else if (ws->flags & DA_32BITMODE) { if (ws->prefixFlags & PX_ADDROVER) mptr = &x86ModTable16[mod][rm]; else mptr = &x86ModTable32[mod][rm]; } else { fprintf(stderr, "x86getModAddress: error: we are neither in 16 nor 32 bit mode\n"); return (0); } return (mptr);} /* x86getModAddress() *//*x86getModSibDisplacement() Called when our ModR/M or SIB byte requires a displacement. Thedisplacement can be 8, 16, or 32 bits. This routine reads offthe displacement and returns it.Inputs: data - string containing displacement numBytes - number of bytes in displacementReturn: displacement*/static unsigned intx86getModSibDisplacement(unsigned char *data, int numBytes){ unsigned int disp; int len; unsigned long factor; assert(numBytes <= 4); disp = 0; len = 0; /* * XXX - this loop is little-endian specific */ while (numBytes--) { /* * factor = 256^len */ factor = 1 << (8 * len); disp += (unsigned char) data[len++] * factor; } return (disp);} /* x86getModSibDisplacement() *//*x86hasEffectiveOperand() Some MMX instructions (psllw) are defined with a /digit butdo not have rm or mem operands and thus do not need to computeeffective addresses. Our routine x86processModSib() determinesany SIB bytes and displacements before operand processing, soif we get a psllw with a ModR/M which specifies a displacement,we don't want x86processModSib() to compute the displacement sinceno operand needs it and thus it is ignored. This routine determines if any operands of opPtr requirethe calculation of an effective address.Inputs: opPtr - opcode matchReturn: 1 if opPtr has an effective address operand 0 if not*/static intx86hasEffectiveOperand(struct x86OpCode *opPtr){ int ii; for (ii = 0; ii < opPtr->OperandCount; ++ii) { if (opPtr->operands[ii] & (REGMEM | MEMORY)) return (1); } return (0);} /* x86hasEffectiveOperand() */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -