int read_ModR_M(swaddr_t eip, Operand *rm, Operand *reg) { ModR_M m; m.val = instr_fetch(eip, 1); // Log("m.val = %02x", m.val); reg->type = OP_TYPE_REG; reg->reg = m.reg; if(m.mod == 3) { rm->type = OP_TYPE_REG; rm->reg = m.R_M; switch(rm->size) { case 1: rm->val = reg_b(m.R_M); break; case 2: rm->val = reg_w(m.R_M); break; case 4: rm->val = reg_l(m.R_M); break; default: assert(0); } #ifdef DEBUG switch(rm->size) { case 1: sprintf(rm->str, "%%%s", regsb[m.R_M]); break; case 2: sprintf(rm->str, "%%%s", regsw[m.R_M]); break; case 4: sprintf(rm->str, "%%%s", regsl[m.R_M]); break; } #endif return 1; } else { int instr_len = load_addr(eip, &m, rm); rm->val = swaddr_read(rm->addr, rm->size, R_DS); //TODO DS or SS return instr_len; } }
void print_bin_instr(swaddr_t eip, int len) { int i; int l = sprintf(asm_buf, "%8x: ", eip); for(i = 0; i < len; i ++) { l += sprintf(asm_buf + l, "%02x ", instr_fetch(eip + i, 1)); } sprintf(asm_buf + l, "%*.s", 50 - (12 + 3 * len), ""); }
int mov_rm2sr(swaddr_t eip){ /* decode rm */ int len = decode_rm_w(eip + 1); /* decode sreg */ uint8_t addr = instr_fetch(eip + 1, 1); int sr_index = (addr >> 3) & 7; cpu.Sreg[sr_index].val = op_src -> val; /* set sreg base and limit */ uint64_t base_limit = decode_gdt(cpu.Sreg[sr_index].index); cpu.Sreg[sr_index].base = base_limit >> 32; cpu.Sreg[sr_index].limit = (base_limit << 32) >> 32; return len+1; }
static make_helper(_2byte_esc) { eip ++; uint32_t opcode = instr_fetch(eip, 1); ops_decoded.opcode = opcode | 0x100; return _2byte_opcode_table[opcode](eip) + 1; }
int load_addr(swaddr_t eip, ModR_M *m, Operand *rm) { assert(m->mod != 3); int32_t disp; int instr_len, disp_offset, disp_size = 4; int base_reg = -1, index_reg = -1, scale = 0; swaddr_t addr = 0; if(m->R_M == R_ESP) { SIB s; s.val = instr_fetch(eip + 1, 1); base_reg = s.base; disp_offset = 2; scale = s.ss; if(s.index != R_ESP) { index_reg = s.index; } /* if (s.ss==0&&s.index==R_EBP){ rm->sreg=R_SS; } */ } else { /* no SIB */ base_reg = m->R_M; disp_offset = 1; } if (base_reg==R_ESP||base_reg==R_EBP){ rm->sreg=R_SS; }else{ rm->sreg=R_DS; } if(m->mod == 0) { if(base_reg == R_EBP) { base_reg = -1; } else { disp_size = 0; } } else if(m->mod == 1) { disp_size = 1; } instr_len = disp_offset; if(disp_size != 0) { /* has disp */ disp = instr_fetch(eip + disp_offset, disp_size); if(disp_size == 1) { disp = (int8_t)disp; } instr_len += disp_size; addr += disp; } if(base_reg != -1) { addr += reg_l(base_reg); } if(index_reg != -1) { addr += reg_l(index_reg) << scale; } #ifdef DEBUG char disp_buf[16]; char base_buf[8]; char index_buf[8]; if(disp_size != 0) { /* has disp */ sprintf(disp_buf, "%s%#x", (disp < 0 ? "-" : ""), (disp < 0 ? -disp : disp)); } else { disp_buf[0] = '\0'; } if(base_reg == -1) { base_buf[0] = '\0'; } else { sprintf(base_buf, "%%%s", regsl[base_reg]); } if(index_reg == -1) { index_buf[0] = '\0'; } else { sprintf(index_buf, ",%%%s,%d", regsl[index_reg], 1 << scale); } if(base_reg == -1 && index_reg == -1) { sprintf(rm->str, "%s", disp_buf); } else { sprintf(rm->str, "%s(%s%s)", disp_buf, base_buf, index_buf); } #endif rm->type = OP_TYPE_MEM; rm->addr = addr; return instr_len; }
/* For more details about instruction format, please refer to i386 manual. */ int read_ModR_M(swaddr_t eip, swaddr_t *addr) { ModR_M m; m.val = instr_fetch(eip, 1); int32_t disp; int instr_len, disp_offset, disp_size; int base_reg = -1, index_reg = -1, scale = 0; /* When m.mod == 3, the instruction is not going to access memory. * This situation should be handle before calling read_ModR_M(). * Therefore, m.mod should not be 3 here. */ assert(m.mod != 3); disp_size = 4; if(m.R_M == R_ESP) { SIB s; s.val = instr_fetch(eip + 1, 1); base_reg = s.base; disp_offset = 2; scale = s.ss; if(s.index != R_ESP) { index_reg = s.index; } } else { /* no SIB */ base_reg = m.R_M; disp_offset = 1; } if(m.mod == 0) { if(base_reg == R_EBP) { base_reg = -1; } else { disp_size = 0; } } else if(m.mod == 1) { disp_size = 1; } char disp_buf[16]; char base_buf[8]; char index_buf[8]; instr_len = disp_offset; *addr = 0; if(disp_size != 0) { /* has disp */ disp = instr_fetch(eip + disp_offset, disp_size); if(disp_size == 1) { disp = (int8_t)disp; } sprintf(disp_buf, "%s%#x", (disp < 0 ? "-" : ""), (disp < 0 ? -disp : disp)); instr_len += disp_size; *addr += disp; } else { disp_buf[0] = '\0'; } if(base_reg == -1) { base_buf[0] = '\0'; } else { sprintf(base_buf, "%%%s", regsl[base_reg]); *addr += reg_l(base_reg); } if(index_reg == -1) { index_buf[0] = '\0'; } else { sprintf(index_buf, ",%%%s,%d", regsl[index_reg], 1 << scale); *addr += reg_l(index_reg) << scale; } if(base_reg == -1 && index_reg == -1) { print_ModR_M_asm("%s", disp_buf); } else { print_ModR_M_asm("%s(%s%s)", disp_buf, base_buf, index_buf); } return instr_len; }
/* * @describe evaluate the expression and return the value * @param {int, int} p, q * @return {int} value */ uint32_t eval(int p, int q) { if(p > q) { /* Bad expression */ assert(0); } else if(p == q) { /* * Single token * For now, this token should be a number * return the value of the exprssion */ if(tokens[p].type == VAR) { int res = find_var(tokens[p].str); if(res == -1) { printf("undefined reference to %s!\n", tokens[p].str); return 0; } return res; } if(tokens[p].type == DEC_NUM) { return atoi(tokens[p].str); } if(tokens[p].type == HEX_NUM) { return strtol(tokens[p].str, NULL, 16); } if(tokens[p].type == REG) { return getreg(tokens[p].str); } } else if(check_parentness(p, q) == true) { /* * The expression is surrounded by a matched pair of parentheses. * If that is the case, just throw away the parentheses. */ return eval(p + 1, q - 1); } else { int i; int j; int op = -1; int flag = 0; //操作符优先级标志 uint32_t val1; uint32_t val2; if(tokens[p].type == NEG) { if(check_parentness(p + 1, q) || p + 1 == q) { return -1 * eval(p + 1, q); } } else if(tokens[p].type == DEREF) { if(check_parentness(p + 1, q) || p + 1 == q) { return instr_fetch(eval(p + 1, q), 1); } } else if(tokens[p].type == '!') { if(check_parentness(p + 1, q) || p + 1 == q) { return !eval(p + 1, q); } } for(i = p, j = 0; i <= q; i++) { //操作符优先级 if(tokens[i].type == '(' ) { j++; } else if(tokens[i].type == ')') { j--; } else if(j == 0 && (tokens[i].type == EQ || tokens[i].type == NEQ || tokens[i].type == LEQ || tokens[i].type == GEQ || tokens[i].type == L || tokens[i].type == G)) { if(flag < 4) { flag = 4; op = i; } } else if(j == 0 && (tokens[i].type == AND || tokens[i].type == OR)) { if(flag < 3) { op = i; flag = 3; } } else if(j == 0 && (tokens[i].type == '+' || tokens[i].type == '-')) { if(flag < 2) { op = i; flag = 2; } } else if(j == 0 && (tokens[i].type == '*' || tokens[i].type == '/')) { if(flag < 1) { op = i; flag = 1; } } } val1 = eval(p, op - 1); val2 = eval(op + 1, q); switch(tokens[op].type) { case '+': return val1 + val2; break; case '-': return val1 - val2; break; case '*': return val1 * val2; break; case '/': if(val2 == 0) { printf("Error\n"); break; } return val1 / val2; break; case EQ: return val1 == val2 ? 1 : 0; break; case NEQ: return val1 != val2 ? 1 : 0; break; case LEQ: return val1 <= val2 ? 1 : 0; break; case GEQ: return val1 >= val2 ? 1 : 0; break; case L: return val1 < val2 ? 1 : 0; break; case G: return val1 > val2 ? 1 : 0; break; case AND: return val1 && val2; break; case OR: return val1 || val2; break; default: assert(0); } } return 0; }