📄 x86asm.cc
字号:
for (int l=0; l < 2; l++) { if (match_allops(insn, group[k].op, 4, opsize, eaddrsize)) { if (encode_insn(insn, &group[k], 0xc0 | j<<3 | k, -1, X86ASM_PREFIX_D8+i, opsize, eaddrsize)) { pushcode(); newcode(); } } switch (eaddrsize) { case X86_ADDRSIZE64: case X86_ADDRSIZE16: eaddrsize = X86_ADDRSIZE32; break; case X86_ADDRSIZE32: eaddrsize = X86_ADDRSIZE16; break; } } } } } } }}bool x86asm::opreg(x86_insn_op *op, const char *xop){ for (int i=0; i<3; i++) { for (int j=0; j<8; j++) { if (x86_regs[i][j] && strcmp(xop, x86_regs[i][j])==0) { op->type = X86_OPTYPE_REG; op->size = reg2size[i]; op->reg = j; return true; } } } return false;}bool x86asm::opmmx(x86_insn_op *op, const char *xop){ if (strlen(xop) == 3 && xop[0] == 'm' && xop[1] == 'm' && xop[2] >= '0' && xop[2] <= '7') { op->type = X86_OPTYPE_MMX; op->size = 8; op->mmx = xop[2] - '0'; return true; } else { return false; }}bool x86asm::opxmm(x86_insn_op *op, const char *xop){ if (strlen(xop) == 4 && xop[0] == 'x' && xop[1] == 'm' && xop[2] == 'm' && xop[3] >= '0' && xop[3] <= '7') { op->type = X86_OPTYPE_XMM; op->size = 16; op->xmm = xop[3] - '0'; return true; } else { return false; }}bool x86asm::opymm(x86_insn_op *op, const char *xop){ if (strlen(xop) == 4 && xop[0] == 'y' && xop[1] == 'm' && xop[2] == 'm' && xop[3] >= '0' && xop[3] <= '7') { op->type = X86_OPTYPE_YMM; op->size = 32; op->xmm = xop[3] - '0'; return true; } else { return false; }}bool x86asm::opseg(x86_insn_op *op, const char *xop){ for (int i=0; i<8; i++) { if (x86_segs[i] && strcmp(xop, x86_segs[i])==0) { op->type = X86_OPTYPE_SEG; op->size = 2; op->seg = i; return true; } } return false;}bool x86asm::opfarptr(x86_insn_op *op, const char *xop){ return false;/*FIXME: uint64 seg, offset; char *x = xop; if (!fetch_number(&x, &seg)) return false; if (*x != ':') return false; x++; if (!fetch_number(&x, &offset)) return false; if (*x) return false; op->type = X86_OPTYPE_FARPTR; if (offset > 0xffff) op->size=6; else op->size=4; op->farptr.seg = seg; op->farptr.offset = offset; return true;*/}bool x86asm::opimm(x86_insn_op *op, const char *xop){ uint64 i; if (!str2int(xop, i)) return false; op->type = X86_OPTYPE_IMM; if (i > 0xffffffffULL) { op->size = 8; } else if (i > 0xffff) { op->size = 4; } else if (i > 0xff) { op->size = 2; } else { op->size = 1; } op->imm = i; return true;}bool x86asm::opplugimm(x86_insn_op *op, const char *xop){ uint64 d; if (imm_eval_proc && imm_eval_proc(imm_eval_context, xop, d)) { op->type = X86_OPTYPE_IMM; if (d > 0xffffffff) { op->size = 8; } else if (d > 0xffff) { op->size = 4; } else if (d > 0xff) { op->size = 2; } else { op->size = 1; } op->imm = d; return true; } return false;}bool x86asm::opmem(x86asm_insn *asm_insn, x86_insn_op *op, const char *s){ /* FIXME: dirty implementation! */ int opsize = 0, hsize = 0; bool floatptr = false; char token[256]; const char *sep = "[]()*+-:"; tok(&s, token, sizeof token, sep); static const char *types[] = {"byte", "word", "dword", "pword", "qword", "oword", "ymmword", "single", "double", "extended"}; static byte type_size[] = {1, 2, 4, 6, 8, 16, 32, 4, 8, 10}; // typecast for (uint i=0; i < sizeof types / sizeof types[0]; i++) { if (strcmp(token, types[i]) == 0) { hsize = type_size[i]; if (i >= 6) floatptr = true; break; } } if (hsize) { tok(&s, token, sizeof token, sep); if (!(strcmp(token, "ptr") == 0)) return false; opsize = hsize; tok(&s, token, sizeof token, sep); } // segprefixes (e.g. fs:) for (int i = 0; i < 8; i++) { if (x86_segs[i]) { if (strcmp(x86_segs[i], token)==0) { tok(&s, token, sizeof token, sep); if (!(strcmp(token, ":") == 0)) return false; static const int c2p[8] = {X86_PREFIX_ES, X86_PREFIX_CS, X86_PREFIX_SS, X86_PREFIX_DS, X86_PREFIX_FS, X86_PREFIX_GS, 0, 0}; asm_insn->segprefix = c2p[i]; tok(&s, token, sizeof token, sep); break; } } } if (!(strcmp(token, "[") == 0)) return false; int scale = 0, index = X86_REG_NO, base = X86_REG_NO; uint64 disp = 0; int addrsize = X86_ADDRSIZEUNKNOWN; int lasttokenreg = X86_REG_NO; bool need_rex = false; int sign = 1; sep = "[]()*+-"; while (1) {cont: tok(&s, token, sizeof token, sep); if (strcmp(token, "+") == 0) { if (!sign) sign = 1; continue; } if (strcmp(token, "-") == 0) { if (sign) { sign = -sign; } else { sign = -1; } continue; } if (strcmp(token, "]") == 0) { if (sign) return false; break; } if (strcmp(token, "*") == 0) { tok(&s, token, sizeof token, sep); if (lasttokenreg == X86_REG_NO) { /* FIXME: case "imm*reg" not yet supported! cleaner implementation needed! */ return false; } else { uint64 v; if (!str2int(token, v)) return false; if (v > 1) { if (index == lasttokenreg) { scale += v-1; } else if (base == lasttokenreg) { if (index != X86_REG_NO) return false; index = base; base = X86_REG_NO; scale = v; } } } lasttokenreg = X86_REG_NO; sign = 0; continue; } /* test if reg */ for (int i=1; i < 4; i++) { for (int j=0; j < 16; j++) { if (x86_64regs[i][j] && strcmp(token, x86_64regs[i][j])==0) { if (j > 7 || i == 3) { if (this->addrsize != X86_ADDRSIZE64) break; if (j > 7) need_rex = true; } if (sign < 0) return false; static const byte sizer[] = {X86_ADDRSIZE16, X86_ADDRSIZE32, X86_ADDRSIZE64}; int caddrsize = sizer[i-1]; if (addrsize == X86_ADDRSIZEUNKNOWN) { addrsize = caddrsize; } else if (addrsize != caddrsize) { return false; } if (index == j) { scale++; } else if (base == X86_REG_NO) { base = j; } else if (index == X86_REG_NO) { index = j; scale = 1; } else if (base == j && scale == 1) { int t = index; index = base; base = t; scale = 2; } else return false; lasttokenreg = j; sign = 0; goto cont; } } } lasttokenreg = X86_REG_NO; /* test if number */ uint64 v; if ((imm_eval_proc && imm_eval_proc(imm_eval_context, token, v)) || str2int(token, v)) { if (!sign) return false; if (sign < 0) disp -= v; else disp += v; sign = 0; continue; } return false; } op->type = X86_OPTYPE_MEM; op->size = opsize; op->mem.base = base; op->mem.index = index; op->mem.scale = scale; op->mem.addrsize = addrsize; op->mem.disp = disp; op->mem.floatptr = floatptr; op->need_rex = need_rex; return true;}bool x86asm::opspecialregs(x86_insn_op *op, const char *xop){ char *e; if (strcmp(xop, "st")==0) { op->type=X86_OPTYPE_STX; op->size=10; op->stx=0; return true; } else if (ht_strncmp(xop, "st", 2)==0 && xop[2]=='(' && xop[4]==')') { int w = strtol(xop+3, &e, 10); if (e != xop+4 || w > 7) return false; op->type = X86_OPTYPE_STX; op->size = 10; op->stx = w; return 1; } /* FIXME: do we need this? * strtol sets e to next untranslatable char, * this case is caught below... */ if (strlen(xop) != 3) return 0; int w = strtol(xop+2, &e, 10); if (*e || w > 7) return 0; if (ht_strncmp(xop, "cr", 2) == 0) { op->type = X86_OPTYPE_CRX; op->size = 4; op->crx = w; return true; } else if (ht_strncmp(xop, "dr", 2) == 0) { op->type = X86_OPTYPE_DRX; op->size = 4; op->drx = w; return true; } return false;}bool x86asm::translate_str(asm_insn *asm_insn, const char *s){ x86asm_insn *insn=(x86asm_insn*)asm_insn; char *opp[5], op[5][256]; opp[0]=op[0]; opp[1]=op[1]; opp[2]=op[2]; opp[3]=op[3]; opp[4]=op[4]; for (int i=0; i<5; i++) { insn->op[i].need_rex = insn->op[i].forbid_rex = false; insn->op[i].type = X86_OPTYPE_EMPTY; } insn->lockprefix = X86_PREFIX_NO; insn->repprefix = X86_PREFIX_NO; insn->segprefix = X86_PREFIX_NO; insn->opsizeprefix = X86_PREFIX_NO; const char *p = s, *a, *b; /* prefixes */ whitespaces(p); a=p; non_whitespaces(p); b=p; if (ht_strncmp(a, "rep", b-a) == 0 || ht_strncmp(a, "repe", b-a) == 0 || ht_strncmp(a, "repz", b-a) == 0) { insn->repprefix=X86_PREFIX_REPZ; s = p; } else if (ht_strncmp(a, "repne", b-a) == 0 || ht_strncmp(a, "repnz", b-a) == 0) { insn->repprefix=X86_PREFIX_REPNZ; s = p; } else if (ht_strncmp(a, "lock", b-a) == 0) { insn->lockprefix=X86_PREFIX_LOCK; s = p; } /**/ splitstr(s, insn->n, sizeof insn->n, (char**)&opp, 256); insn->name=insn->n; for (int i=0; i<5; i++) { if (!*op[i]) break; if (!(opplugimm(&insn->op[i], op[i]) || opreg(&insn->op[i], op[i]) || opmmx(&insn->op[i], op[i]) || opxmm(&insn->op[i], op[i]) || opymm(&insn->op[i], op[i]) || opfarptr(&insn->op[i], op[i]) || opimm(&insn->op[i], op[i]) || opseg(&insn->op[i], op[i]) || opmem(insn, &insn->op[i], op[i]) || opspecialregs(&insn->op[i], op[i]))) { set_error_msg(X86ASM_ERRMSG_UNKNOWN_SYMBOL, op[i]); return false; } } return true;}int x86asm::simmsize(uint64 imm, int immsize){ switch (immsize) { case 1: if (imm <= 0xff) return 1; break; case 2: if (imm <= 0xffff) imm = sint64(sint16(imm)); break; case 4: if (imm <= 0xffffffff) imm = sint64(sint32(imm)); break; } if (imm >= 0xffffffffffffff80ULL || imm < 0x80) return 1; if (imm >= 0xffffffffffff8000ULL || imm < 0x8000) return 2; if (imm >= 0xffffffff80000000ULL || imm < 0x80000000) return 4; return 8;}void x86asm::splitstr(const char *s, char *name, int size, char *op[5], int opsize){ const char *a, *b; bool wantbreak = false; *name=0; *op[0]=0; *op[1]=0; *op[2]=0; *op[3]=0; *op[4]=0; /* find name */ whitespaces(s); a = s; non_whitespaces(s); b = s; ht_strlcpy(name, a, MIN(b-a+1, size)); /* find ops */ for (int i = 0; i < 5; i++) { whitespaces(s); if (!*s) break; a = s; waitforchar(s, ','); while (is_whitespace(s[-1])) s--; if (!*s) wantbreak = true; b = s; whitespaces(s); if (!*s) wantbreak = true; ht_strlcpy(op[i], a, MIN(b-a+1, opsize)); whitespaces(s); if (wantbreak || *s != ',') break; s++; }}void x86asm::tok(const char **s, char *res, int reslen, const char *sep){ if (reslen <= 0) return; whitespaces(*s); if (strchr(sep, **s)) { if (reslen > 0) *res++ = *((*s)++); } else { while (reslen > 1) { *res++ = *((*s)++); reslen--; if (**s == ' ' || **s == '\t') break; if (strchr(sep, **s)) break; } } *res = 0;}/************************************************************************ * */x86opc_insn (*x86_64asm::x86_64_insns)[256];x86_64asm::x86_64asm() : x86asm(X86_OPSIZE32, X86_ADDRSIZE64){ prepInsns();}void x86_64asm::prepInsns(){ if (!x86_64_insns) { x86_64_insns = ht_malloc(sizeof *x86_64_insns); memcpy(x86_64_insns, x86_32_insns, sizeof x86_32_insns); int i = 0; while (x86_64_insn_patches[i].opc != -1) { (*x86_64_insns)[x86_64_insn_patches[i].opc] = x86_64_insn_patches[i].insn; i++; } } x86_insns = x86_64_insns;}x86dis *x86_64asm::createCompatibleDisassembler(){ return new x86_64dis();}bool x86_64asm::opreg(x86_insn_op *op, const char *xop){ for (int i=0; i < 4; i++) { for (int j=0; j < 16; j++) { if (x86_64regs[i][j] && strcmp(xop, x86_64regs[i][j])==0) { op->type = X86_OPTYPE_REG; op->size = reg2size[i]; op->reg = j; if (j > 7 || (i == 0 && j > 3)) { op->need_rex = true; } return true; } } } // check for legacy ah, ch, dh, bh for (int j=4; j < 8; j++) { if (x86_regs[0][j] && strcmp(xop, x86_regs[0][j])==0) { op->type = X86_OPTYPE_REG; op->size = reg2size[0]; op->reg = j; op->forbid_rex = true; return true; } } return false;}bool x86_64asm::opxmm(x86_insn_op *op, const char *xop){ int slen = strlen(xop); if ((slen == 4 || slen == 5) && xop[0] == 'x' && xop[1] == 'm' && xop[2] == 'm' && xop[3] >= '0' && xop[3] <= '9') { int x = xop[3] - '0'; if (slen == 5) { if (xop[4] < '0' || xop[4] > '9') return false; x *= 10; x += xop[4] - '0'; if (x > 15) return false; } op->type = X86_OPTYPE_XMM; op->size = 16; op->xmm = x; if (x > 7) op->need_rex = true; return true; } else { return false; }}bool x86_64asm::opymm(x86_insn_op *op, const char *xop){ int slen = strlen(xop); if ((slen == 4 || slen == 5) && xop[0] == 'y' && xop[1] == 'm' && xop[2] == 'm' && xop[3] >= '0' && xop[3] <= '9') { int x = xop[3] - '0'; if (slen == 5) { if (xop[4] < '0' || xop[4] > '9') return false; x *= 10; x += xop[4] - '0'; if (x > 15) return false; } op->type = X86_OPTYPE_YMM; op->size = 32; op->xmm = x; if (x > 7) op->need_rex = true; return true; } else { return false; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -