📄 x86expr.c
字号:
/* Figure out what size displacement we will have. */ if (*displen != 0xff && dispval == 0) { /* if we know that the displacement is 0 right now, * go ahead and delete the expr (making it so no * displacement value is included in the output). * The Mod bits of ModRM are set to 0 above, and * we're done with the ModRM byte! * * Don't do this if we came from dispreq check above, so * check *displen. */ yasm_expr_destroy(e); *ep = (yasm_expr *)NULL; } else if (dispval >= -128 && dispval <= 127) { /* It fits into a signed byte */ *displen = 1; *modrm |= 0100; } else { /* It's a 16/32-bit displacement */ *displen = wordsize; *modrm |= 0200; } *v_modrm = 1; /* We're done with ModRM */ } return 0;}/*@=nullstate@*/static intx86_expr_checkea_getregsize_callback(yasm_expr__item *ei, void *d){ unsigned char *addrsize = (unsigned char *)d; if (ei->type == YASM_EXPR_REG) { switch ((x86_expritem_reg_size)(ei->data.reg & ~0xFUL)) { case X86_REG16: *addrsize = 16; break; case X86_REG32: *addrsize = 32; break; case X86_REG64: case X86_RIP: *addrsize = 64; break; default: return 0; } return 1; } else return 0;}intyasm_x86__expr_checkea(yasm_expr **ep, unsigned char *addrsize, unsigned int bits, unsigned int nosplit, unsigned char *displen, unsigned char *modrm, unsigned char *v_modrm, unsigned char *n_modrm, unsigned char *sib, unsigned char *v_sib, unsigned char *n_sib, unsigned char *pcrel, unsigned char *rex, yasm_calc_bc_dist_func calc_bc_dist){ yasm_expr *e, *wrt; int retval; /* First split off any top-level WRT. We'll add it back in at the end */ wrt = yasm_expr_extract_wrt(ep); e = *ep; if (*addrsize == 0) { /* we need to figure out the address size from what we know about: * - the displacement length * - what registers are used in the expression * - the bits setting */ switch (*displen) { case 2: /* must be 16-bit */ *addrsize = 16; break; case 8: /* We have to support this for the MemOffs case, but it's * otherwise illegal. It's also illegal in non-64-bit mode. */ if (*n_modrm || *n_sib) { yasm__error(e->line, N_("invalid effective address (displacement size)")); return 1; } *addrsize = 64; break; case 4: /* Must be 32-bit in 16-bit or 32-bit modes. In 64-bit mode, * we don't know unless we look at the registers, except in the * MemOffs case (see the end of this function). */ if (bits != 64 || (!*n_modrm && !*n_sib)) { *addrsize = 32; break; } /*@fallthrough@*/ default: /* check for use of 16 or 32-bit registers; if none are used * default to bits setting. */ if (!yasm_expr__traverse_leaves_in(e, addrsize, x86_expr_checkea_getregsize_callback)) *addrsize = bits; /* TODO: Add optional warning here if switched address size * from bits setting just by register use.. eg [ax] in * 32-bit mode would generate a warning. */ } } if ((*addrsize == 32 || *addrsize == 64) && ((*n_modrm && !*v_modrm) || (*n_sib && !*v_sib))) { int i; unsigned char low3; typedef enum { REG3264_NONE = -1, REG3264_EAX = 0, REG3264_ECX, REG3264_EDX, REG3264_EBX, REG3264_ESP, REG3264_EBP, REG3264_ESI, REG3264_EDI, REG64_R8, REG64_R9, REG64_R10, REG64_R11, REG64_R12, REG64_R13, REG64_R14, REG64_R15, REG64_RIP } reg3264type; int reg3264mult[17] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; x86_checkea_reg3264_data reg3264_data; int basereg = REG3264_NONE; /* "base" register (for SIB) */ int indexreg = REG3264_NONE; /* "index" register (for SIB) */ /* We can only do 64-bit addresses in 64-bit mode. */ if (*addrsize == 64 && bits != 64) { yasm__error(e->line, N_("invalid effective address (64-bit in non-64-bit mode)")); return 1; } reg3264_data.regs = reg3264mult; reg3264_data.bits = bits; reg3264_data.addrsize = *addrsize; switch (x86_expr_checkea_getregusage(ep, &wrt, &indexreg, pcrel, bits, ®3264_data, x86_expr_checkea_get_reg3264, calc_bc_dist)) { case 1: e = *ep; yasm__error(e->line, N_("invalid effective address")); return 1; case 2: if (wrt) *ep = yasm_expr_create_tree(*ep, YASM_EXPR_WRT, wrt, (*ep)->line); return 2; default: e = *ep; break; } /* If indexreg mult is 0, discard it. * This is possible because of the way indexreg is found in * expr_checkea_getregusage(). */ if (indexreg != REG3264_NONE && reg3264mult[indexreg] == 0) indexreg = REG3264_NONE; /* Find a basereg (*1, but not indexreg), if there is one. * Also, if an indexreg hasn't been assigned, try to find one. * Meanwhile, check to make sure there's no negative register mults. */ for (i=0; i<17; i++) { if (reg3264mult[i] < 0) { yasm__error(e->line, N_("invalid effective address")); return 1; } if (i != indexreg && reg3264mult[i] == 1 && basereg == REG3264_NONE) basereg = i; else if (indexreg == REG3264_NONE && reg3264mult[i] > 0) indexreg = i; } /* Handle certain special cases of indexreg mults when basereg is * empty. */ if (indexreg != REG3264_NONE && basereg == REG3264_NONE) switch (reg3264mult[indexreg]) { case 1: /* Only optimize this way if nosplit wasn't specified */ if (!nosplit) { basereg = indexreg; indexreg = -1; } break; case 2: /* Only split if nosplit wasn't specified */ if (!nosplit) { basereg = indexreg; reg3264mult[indexreg] = 1; } break; case 3: case 5: case 9: basereg = indexreg; reg3264mult[indexreg]--; break; } /* Make sure there's no other registers than the basereg and indexreg * we just found. */ for (i=0; i<17; i++) if (i != basereg && i != indexreg && reg3264mult[i] != 0) { yasm__error(e->line, N_("invalid effective address")); return 1; } /* Check the index multiplier value for validity if present. */ if (indexreg != REG3264_NONE && reg3264mult[indexreg] != 1 && reg3264mult[indexreg] != 2 && reg3264mult[indexreg] != 4 && reg3264mult[indexreg] != 8) { yasm__error(e->line, N_("invalid effective address")); return 1; } /* ESP is not a legal indexreg. */ if (indexreg == REG3264_ESP) { /* If mult>1 or basereg is ESP also, there's no way to make it * legal. */ if (reg3264mult[REG3264_ESP] > 1 || basereg == REG3264_ESP) { yasm__error(e->line, N_("invalid effective address")); return 1; } /* If mult==1 and basereg is not ESP, swap indexreg w/basereg. */ indexreg = basereg; basereg = REG3264_ESP; } /* RIP is only legal if it's the ONLY register used. */ if (indexreg == REG64_RIP || (basereg == REG64_RIP && indexreg != REG3264_NONE)) { yasm__error(e->line, N_("invalid effective address")); return 1; } /* At this point, we know the base and index registers and that the * memory expression is (essentially) valid. Now build the ModRM and * (optional) SIB bytes. */ /* First determine R/M (Mod is later determined from disp size) */ *n_modrm = 1; /* we always need ModRM */ if (basereg == REG3264_NONE && indexreg == REG3264_NONE) { /* Just a disp32: in 64-bit mode the RM encoding is used for RIP * offset addressing, so we need to use the SIB form instead. */ if (bits == 64) { *modrm |= 4; *n_sib = 1; } else { *modrm |= 5; *sib = 0; *v_sib = 0; *n_sib = 0; } } else if (basereg == REG64_RIP) { *modrm |= 5; *sib = 0; *v_sib = 0; *n_sib = 0; /* RIP always requires a 32-bit displacement */ *v_modrm = 1; *displen = 4; if (wrt) *ep = yasm_expr_create_tree(*ep, YASM_EXPR_WRT, wrt, (*ep)->line); return 0; } else if (indexreg == REG3264_NONE) { /* basereg only */ /* Don't need to go to the full effort of determining what type * of register basereg is, as x86_set_rex_from_reg doesn't pay * much attention. */ if (yasm_x86__set_rex_from_reg(rex, &low3, (unsigned int)(X86_REG64 | basereg), bits, X86_REX_B)) { yasm__error(e->line, N_("invalid combination of operands and effective address")); return 1; } *modrm |= low3; /* we don't need an SIB *unless* basereg is ESP or R12 */ if (basereg == REG3264_ESP || basereg == REG64_R12) *n_sib = 1; else { *sib = 0; *v_sib = 0; *n_sib = 0; } } else { /* index or both base and index */ *modrm |= 4; *n_sib = 1; } /* Determine SIB if needed */ if (*n_sib == 1) { *sib = 0; /* start with 0 */ /* Special case: no basereg */ if (basereg == REG3264_NONE) *sib |= 5; else { if (yasm_x86__set_rex_from_reg(rex, &low3, (unsigned int) (X86_REG64 | basereg), bits, X86_REX_B)) { yasm__error(e->line, N_("invalid combination of operands and effective address")); return 1; } *sib |= low3; } /* Put in indexreg, checking for none case */ if (indexreg == REG3264_NONE) *sib |= 040; /* Any scale field is valid, just leave at 0. */ else { if (yasm_x86__set_rex_from_reg(rex, &low3, (unsigned int) (X86_REG64 | indexreg), bits, X86_REX_X)) { yasm__error(e->line, N_("invalid combination of operands and effective address")); return 1; } *sib |= low3 << 3; /* Set scale field, 1 case -> 0, so don't bother. */ switch (reg3264mult[indexreg]) { case 2: *sib |= 0100; break; case 4: *sib |= 0200; break; case 8: *sib |= 0300; break; } } *v_sib = 1; /* Done with SIB */ } /* Calculate displacement length (if possible) */ retval = x86_checkea_calc_displen(ep, 4, basereg == REG3264_NONE, basereg == REG3264_EBP || basereg == REG64_R13, displen, modrm, v_modrm); if (wrt) *ep = yasm_expr_create_tree(*ep, YASM_EXPR_WRT, wrt, (*ep)->line); return retval; } else if (*addrsize == 16 && *n_modrm && !*v_modrm) { static const unsigned char modrm16[16] = { 0006 /* disp16 */, 0007 /* [BX] */, 0004 /* [SI] */, 0000 /* [BX+SI] */, 0005 /* [DI] */, 0001 /* [BX+DI] */, 0377 /* invalid */, 0377 /* invalid */, 0006 /* [BP]+d */, 0377 /* invalid */, 0002 /* [BP+SI] */, 0377 /* invalid */, 0003 /* [BP+DI] */, 0377 /* invalid */, 0377 /* invalid */, 0377 /* invalid */ }; x86_checkea_reg16_data reg16mult = {0, 0, 0, 0}; enum { HAVE_NONE = 0, HAVE_BX = 1<<0, HAVE_SI = 1<<1, HAVE_DI = 1<<2, HAVE_BP = 1<<3 } havereg = HAVE_NONE; /* 64-bit mode does not allow 16-bit addresses */ if (bits == 64) { yasm__error(e->line, N_("16-bit addresses not supported in 64-bit mode")); return 1; } /* 16-bit cannot have SIB */ *sib = 0; *v_sib = 0; *n_sib = 0; switch (x86_expr_checkea_getregusage(ep, &wrt, (int *)NULL, pcrel, bits, ®16mult, x86_expr_checkea_get_reg16, calc_bc_dist)) { case 1: e = *ep; yasm__error(e->line, N_("invalid effective address")); return 1; case 2: if (wrt) *ep = yasm_expr_create_tree(*ep, YASM_EXPR_WRT, wrt, (*ep)->line); return 2; default: e = *ep; break; } /* reg multipliers not 0 or 1 are illegal. */ if (reg16mult.bx & ~1 || reg16mult.si & ~1 || reg16mult.di & ~1 || reg16mult.bp & ~1) { yasm__error(e->line, N_("invalid effective address")); return 1; } /* Set havereg appropriately */ if (reg16mult.bx > 0) havereg |= HAVE_BX; if (reg16mult.si > 0) havereg |= HAVE_SI; if (reg16mult.di > 0) havereg |= HAVE_DI; if (reg16mult.bp > 0) havereg |= HAVE_BP; /* Check the modrm value for invalid combinations. */ if (modrm16[havereg] & 0070) { yasm__error(e->line, N_("invalid effective address")); return 1; } /* Set ModRM byte for registers */ *modrm |= modrm16[havereg]; /* Calculate displacement length (if possible) */ retval = x86_checkea_calc_displen(ep, 2, havereg == HAVE_NONE, havereg == HAVE_BP, displen, modrm, v_modrm); if (wrt) *ep = yasm_expr_create_tree(*ep, YASM_EXPR_WRT, wrt, (*ep)->line); return retval; } else if (!*n_modrm && !*n_sib) { /* Special case for MOV MemOffs opcode: displacement but no modrm. */ switch (*addrsize) { case 64: if (bits != 64) { yasm__error(e->line, N_("invalid effective address (64-bit in non-64-bit mode)")); return 1; } *displen = 8; break; case 32: *displen = 4; break; case 16: /* 64-bit mode does not allow 16-bit addresses */ if (bits == 64) { yasm__error(e->line, N_("16-bit addresses not supported in 64-bit mode")); return 1; } *displen = 2; break; } } if (wrt) *ep = yasm_expr_create_tree(*ep, YASM_EXPR_WRT, wrt, (*ep)->line); return 0;}intyasm_x86__floatnum_tobytes(yasm_arch *arch, const yasm_floatnum *flt, unsigned char *buf, size_t destsize, size_t valsize, size_t shift, int warn, unsigned long line){ if (!yasm_floatnum_check_size(flt, valsize)) { yasm__error(line, N_("invalid floating point constant size")); return 1; } yasm_floatnum_get_sized(flt, buf, destsize, valsize, shift, 0, warn, line); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -