📄 x86asm.cc
字号:
break; case X86ASM_PREFIX_0F7B: emitbyte(0x0f); emitbyte(0x7b); break; case X86ASM_PREFIX_DF: case X86ASM_PREFIX_DE: case X86ASM_PREFIX_DD: case X86ASM_PREFIX_DC: case X86ASM_PREFIX_DB: case X86ASM_PREFIX_DA: case X86ASM_PREFIX_D9: case X86ASM_PREFIX_D8: opcodeb = 0xd8 + prefix - X86ASM_PREFIX_D8; break; } emitbyte(opcodeb); /* encode the ops */ for (int i=0; i < 4; i++) { if (!encode_op(&insn->op[i], &x86_op_type[opcode->op[i]], &esizes[i], eopsize, eaddrsize)) { clearcode(); return false; } } /* write the rest */ if (modrmv != -1) emitbyte(modrmv); if (sibv != -1) emitbyte(sibv); if (drexdest != -1) { byte oc0 = 0; if (drexoc0 != -1) { oc0 = drexoc0; } byte drex = (drexdest << 4) | (oc0 << 3) | (rexprefix & 7); rexprefix = 0; emitbyte(drex); } if (disppos && addrsize == X86_ADDRSIZE64) { // fix ip-relative disp in PM64 mode dispsize = 4; disp -= address + code.size + dispsize + immsize; if (simmsize(disp, 4) > 4) { clearcode(); return false; } } switch (dispsize) { case 1: emitbyte(disp); break; case 2: emitword(disp); break; case 4: emitdword(disp); break; case 8: emitqword(disp); break; } switch (immsize) { case 1: emitbyte(imm); break; case 2: emitword(imm); break; case 4: emitdword(imm); break; case 6: emitdword(imm); emitword(imm2); break; case 8: emitqword(imm); break; } // fix rex code if (rexprefix & 0x40) { code.data[rexpos] = rexprefix; } return true;}bool x86asm::encode_vex_insn(x86asm_insn *insn, x86opc_vex_insn *opcode, int opcodeb, int additional_opcode, int eopsize, int eaddrsize){ rexprefix = 0; disppos = 0; immsize = 0; dispsize = 0; vexvvvv = 0; modrmv = -1; sibv = -1; if (additional_opcode != -1) { emitmodrm_reg(additional_opcode); } switch (insn->lockprefix) { case X86_PREFIX_LOCK: clearcode(); return false; } switch (insn->repprefix) { case X86_PREFIX_REPNZ: case X86_PREFIX_REPZ: clearcode(); return false; } switch (insn->segprefix) { case X86_PREFIX_ES: emitbyte(0x26); break; case X86_PREFIX_CS: emitbyte(0x2e); break; case X86_PREFIX_SS: emitbyte(0x36); break; case X86_PREFIX_DS: emitbyte(0x3e); break; case X86_PREFIX_FS: emitbyte(0x64); break; case X86_PREFIX_GS: emitbyte(0x65); break; } for (int i=0; i < 5; i++) { if (!encode_op(&insn->op[i], &x86_op_type[opcode->op[i]], &esizes[i], eopsize, eaddrsize)) { clearcode(); return false; } } if ((opcode->vex & 0x30) == 0x10 // 0x0f-opcode && !(rexprefix & 3) // no rexb/rexx && !(opcode->vex & W1)) { // use short vex prefix emitbyte(0xc5); byte vex = (~rexprefix & 4) << 5 | ((~vexvvvv & 0xf) << 3) | (opcode->vex & _256) >> 4 | (opcode->vex & 0x3); emitbyte(vex); } else { // use long vex prefix emitbyte(0xc4); byte vex = (~rexprefix & 7) << 5 | ((opcode->vex & 0x30) >> 4); emitbyte(vex); vex = (opcode->vex & W1) | ((~vexvvvv & 0xf) << 3) | (opcode->vex & _256) >> 4 | (opcode->vex & 0x3); emitbyte(vex); } emitbyte(opcodeb); if (modrmv != -1) emitbyte(modrmv); if (sibv != -1) emitbyte(sibv); if (disppos && addrsize == X86_ADDRSIZE64) { // fix ip-relative disp in PM64 mode dispsize = 4; disp -= address + code.size + dispsize + immsize; if (simmsize(disp, 4) > 4) { clearcode(); return false; } } switch (dispsize) { case 1: emitbyte(disp); break; case 2: emitword(disp); break; case 4: emitdword(disp); break; } switch (immsize) { case 1: emitbyte(imm); break; } return true;}bool x86asm::encode_modrm(x86_insn_op *op, char size, bool allow_reg, bool allow_mem, int eopsize, int eaddrsize){ switch (op->type) { case X86_OPTYPE_REG: if (!allow_reg) return false; emitmodrm_mod(3); emitmodrm_rm(op->reg); if (op->reg > 7) rexprefix |= rexb; break; case X86_OPTYPE_MEM: { if (!allow_mem) return false; int addrsize = op->mem.addrsize; int mindispsize = addr2size[addrsize+1]; if (addrsize == X86_ADDRSIZEUNKNOWN) { addrsize = eaddrsize; if (this->addrsize == X86_ADDRSIZE64) { // ip-relative, we check this later mindispsize = 4; } else { mindispsize = op->mem.disp ? simmsize(op->mem.disp, 8) : 0; } } else { mindispsize = op->mem.disp ? simmsize(op->mem.disp, mindispsize) : 0; if (mindispsize > 4) return false; } if (addrsize == X86_ADDRSIZE16) { int mod, rm, dispsize; if (!encode_modrm_v(&modrm16, op, mindispsize, &mod, &rm, &dispsize)) return 0; emitmodrm_mod(mod); emitmodrm_rm(rm); emitdisp(op->mem.disp, dispsize); } else { int mod, rm, dispsize; if (!encode_modrm_v(&modrm32, op, mindispsize, &mod, &rm, &dispsize)) { int scale, index, base, disp=op->mem.disp; if (encode_sib_v(op, mindispsize, &scale, &index, &base, &mod, &dispsize, &disp)) { emitmodrm_mod(mod); emitmodrm_rm(4); /* SIB */ emitsib_scale(scale); emitsib_index(index); emitsib_base(base); emitdisp(disp, dispsize); } else return false; } else { emitmodrm_mod(mod); emitmodrm_rm(rm); emitdisp(op->mem.disp, dispsize); } } break; } case X86_OPTYPE_MMX: if (!allow_reg) return false; emitmodrm_mod(3); emitmodrm_rm(op->mmx); break; case X86_OPTYPE_XMM: if (!allow_reg) return false; emitmodrm_mod(3); emitmodrm_rm(op->xmm); break; case X86_OPTYPE_YMM: if (!allow_reg) return false; emitmodrm_mod(3); emitmodrm_rm(op->ymm); break; default: return false; } return true;}bool x86asm::encode_modrm_v(const x86addrcoding (*modrmc)[3][8], x86_insn_op *op, int mindispsize, int *_mod, int *_rm, int *_dispsize){ if (op->mem.scale > 1) return false; for (int mod=0; mod < 3; mod++) { for (int rm=0; rm < 8; rm++) { const x86addrcoding *c=&(*modrmc)[mod][rm]; int r1=c->reg1, r2=c->reg2; if (r2 == (op->mem.base&~8)) { int t = r1; r1 = r2; r2 = t; } if (r1==(op->mem.base&~8) && r2==(op->mem.index&~8) && c->dispsize>=mindispsize) { *_mod=mod; *_rm=rm; *_dispsize=c->dispsize; if (this->addrsize == X86_ADDRSIZE64 && mod == 0 && rm == 5) { // ip-relative addressing disppos = 1; } if (op->mem.base & 8) rexprefix |= rexb; return true; } } } return false;}bool x86asm::encode_op(x86_insn_op *op, x86opc_insn_op *xop, int *esize, int eopsize, int eaddrsize){ int psize = op->size; switch (xop->type) { case TYPE_0: return true; case TYPE_A: /* direct address without ModR/M */ if (op->type == X86_OPTYPE_FARPTR) { int size = esizeop_ex(xop->size, eopsize); emitfarptr(op->farptr.seg, op->farptr.offset, size == 6); } else { emitimm(op->imm, op->size); } break; case TYPE_C: /* reg of ModR/M picks control register */ emitmodrm_reg(op->crx); if (op->crx > 7) rexprefix |= rexr; break; case TYPE_D: /* reg of ModR/M picks debug register */ emitmodrm_reg(op->drx); if (op->drx > 7) rexprefix |= rexr; break; case TYPE_E: /* ModR/M (general reg or memory) */ if (!encode_modrm(op, xop->size, true, true, eopsize, eaddrsize)) return false; //XXX psize = esizeop(xop->size, eopsize); //XXX break; case TYPE_F: /* r/m of ModR/M picks a fpu register */ emitmodrm_rm(op->stx); break; case TYPE_Fx: /* extra picks a fpu register */ return true; case TYPE_G: /* reg of ModR/M picks general register */ emitmodrm_reg(op->reg); if (op->reg > 7) rexprefix |= rexr; break; case TYPE_Is: { /* signed immediate */ int size = esizeop_ex(xop->size, eopsize); emitimm(op->imm, size); break; } case TYPE_I: { /* unsigned immediate */ int size = esizeop_ex(xop->size, eopsize); emitimm(op->imm, size); break; } case TYPE_Ix: /* fixed immediate */ return true; case TYPE_I4: { /* 4 bit immediate (see TYPE_VI, TYPE_YI) */ if (op->imm > 15) return false; if (immsize == 0) { immsize = 1; imm = 0; } imm |= op->imm; break; } case TYPE_J: { /* relative branch offset */ int size = esizeop_ex(xop->size, eopsize); emitimm(uint32(op->imm - address - code.size - size), size); break; } case TYPE_M: /* ModR/M (memory only) */ if (!encode_modrm(op, xop->size, false, true, eopsize, eaddrsize)) return false; // XXX psize = esizeop(xop->size, eopsize); //XXX break; case TYPE_MR: { /* Same as E, but extra picks reg size */ byte xopsize = xop->size; if (op->type == X86_OPTYPE_REG) { xopsize = xop->extra; } if (!encode_modrm(op, xopsize, true, true, eopsize, eaddrsize)) return false; //XXX psize = esizeop(xopsize, eopsize); //XXX break; } case TYPE_O: { /* direct memory without ModR/M */ if (op->mem.base != X86_REG_NO) return false; if (op->mem.index != X86_REG_NO) return false; psize = esizeop(xop->size, eopsize); // XXX switch (eaddrsize) { case X86_ADDRSIZE16: if (op->mem.disp > 0xffff) return false; emitdisp(op->mem.disp, 2); break; case X86_ADDRSIZE32: if (op->mem.disp > 0xffffffff) return false; emitdisp(op->mem.disp, 4); break; case X86_ADDRSIZE64: emitdisp(op->mem.disp, 8); break; } break; } case TYPE_P: /* reg of ModR/M picks MMX register */ emitmodrm_reg(op->mmx); break; case TYPE_PR: /* rm of ModR/M picks MMX register */ emitmodrm_mod(3); emitmodrm_rm(op->mmx); break; case TYPE_Q: /* ModR/M (MMX reg or memory) */ if (!encode_modrm(op, xop->size, true, true, eopsize, eaddrsize)) return false; //XXX psize = esizeop(xop->size, eopsize); //XXX break; case TYPE_R: /* rm of ModR/M picks general register */ emitmodrm_rm(op->reg); // fall throu case TYPE_Rx: if (op->reg > 7) rexprefix |= rexb; return true; case TYPE_RXx: /* extra picks register, no REX */ return true; case TYPE_S: /* reg of ModR/M picks segment register */ emitmodrm_reg(op->seg); break; case TYPE_Sx: /* extra picks segment register */ return true; case TYPE_V: /* reg of ModR/M picks XMM register */ emitmodrm_reg(op->xmm); if (op->xmm > 7) rexprefix |= rexr; break; case TYPE_VR: /* rm of ModR/M picks XMM register */ emitmodrm_mod(3); emitmodrm_rm(op->xmm); if (op->xmm > 7) rexprefix |= rexb; break; case TYPE_Vx: break; case TYPE_VV: vexvvvv = op->xmm; break; case TYPE_VI: { /* bits 7-4 of imm pick XMM register */ if (immsize == 0) { immsize = 1; imm = 0; } imm |= op->xmm << 4; break; } case TYPE_VD: if (drexdest == -1) { drexdest = op->xmm; } else { if (drexdest != op->xmm) { return false; } } break; case TYPE_VS: if (op->type == X86_OPTYPE_XMM) { if (drexoc0 == 0) { emitmodrm_mod(3); emitmodrm_rm(op->xmm); if (op->xmm > 7) rexprefix |= rexb; } else { emitmodrm_reg(op->xmm); if (op->xmm > 7) rexprefix |= rexr; if (drexoc0 == -1) drexoc0 = 0; } } else { if (drexoc0 == 1) return false; if (drexoc0 == -1) { if (xop->info) return false; drexoc0 = 1; } if (!encode_modrm(op, xop->size, true, true, eopsize, eaddrsize)) return false; //XXX psize = esizeop(xop->size, eopsize); //XXX } break; case TYPE_W: /* ModR/M (XMM reg or memory) */ if (!encode_modrm(op, xop->size, true, true, eopsize, eaddrsize)) return false; //XXX psize = esizeop(xop->size, eopsize); //XXX break; case TYPE_Y: /* reg of ModR/M picks YMM register */ emitmodrm_reg(op->ymm); if (op->ymm > 7) rexprefix |= rexr; break; case TYPE_YI: { /* bits 7-4 of imm pick YMM register */ if (immsize == 0) { immsize = 1; imm = 0; } imm |= op->xmm << 4; break; } case TYPE_YV: vexvvvv = op->ymm; break; case TYPE_YR: /* rm of ModR/M picks YMM register */ emitmodrm_mod(3); emitmodrm_rm(op->ymm); if (op->ymm > 7) rexprefix |= rexb; break; case TYPE_X: /* ModR/M (YMM reg or memory) */ if (!encode_modrm(op, xop->size, true, true, eopsize, eaddrsize)) return false; //XXX psize = esizeop(xop->size, eopsize); //XXX break; } if (!psize) {// set_error_msg(X86ASM_ERRMSG_INTERNAL"FIXME: size ??? %s, %d\n", __FILE__, __LINE__); } if (!*esize) *esize = psize;/* if (!(options & X86ASM_ALLOW_AMBIGUOUS) && *esize != psize) { ambiguous = 1; set_error_msg(X86ASM_ERRMSG_AMBIGUOUS); return 0; }*/ return true;}bool x86asm::encode_sib_v(x86_insn_op *op, int mindispsize, int *_ss, int *_index, int *_base, int *_mod, int *_dispsize, int *disp){ int ss, scale=op->mem.scale, index=op->mem.index, base=op->mem.base, mod, dispsize; if (base == X86_REG_NO && index != X86_REG_NO) { switch (scale) { case 1: case 4: case 8: break; case 2: case 3: case 5: case 9: scale--; base = index; break; default: return false; } } if (index == X86_REG_SP) { if (scale > 1) return false; if (scale == 1) { if (base == X86_REG_SP) return false; int temp = index; index = base; base = temp; } } if (index != X86_REG_NO) { switch (scale) { case 1: ss = 0; break; case 2: ss = 1; break; case 4: ss = 2; break; case 8: ss = 3; break; default: return 0; } } else { ss = 0; index = 4; } switch (mindispsize) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -