⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 x86bc.c

📁 支持AMD64的汇编编译器源码
💻 C
📖 第 1 页 / 共 3 页
字号:
		    rel = yasm_intnum_get_int(num);		    rel -= jmp->shortop.opcode_len+1;		    yasm_expr_destroy(temp);		    /* does a short form exist? */		    if (jmp->shortop.opcode_len == 0) {			yasm__error(bc->line, N_("short jump does not exist"));			return YASM_BC_RESOLVE_ERROR |			    YASM_BC_RESOLVE_UNKNOWN_LEN;		    }		    /* short displacement must fit in -128 <= rel <= +127 */		    if (rel < -128 || rel > 127) {			yasm__error(bc->line, N_("short jump out of range"));			return YASM_BC_RESOLVE_ERROR |			    YASM_BC_RESOLVE_UNKNOWN_LEN;		    }		}	    }	    break;	case JMP_NEAR_FORCED:	    /* 2/4 byte relative displacement (depending on operand size) */	    jrtype = JMP_NEAR;	    if (save) {		if (jmp->nearop.opcode_len == 0) {		    yasm__error(bc->line, N_("near jump does not exist"));		    return YASM_BC_RESOLVE_ERROR | YASM_BC_RESOLVE_UNKNOWN_LEN;		}	    }	    break;	default:	    temp = yasm_expr_copy(jmp->target);	    temp = yasm_expr_simplify(temp, NULL);	    /* Check for far displacement (seg:off). */	    if (yasm_expr_is_op(temp, YASM_EXPR_SEGOFF)) {		jrtype = JMP_FAR;		break;	    /* length handled below */	    } else if (jmp->op_sel == JMP_FAR) {		yasm__error(bc->line,			    N_("far jump does not have a far displacement"));		return YASM_BC_RESOLVE_ERROR | YASM_BC_RESOLVE_UNKNOWN_LEN;	    }	    /* Try to find shortest displacement based on difference between	     * target expr value and our (this bytecode's) offset.  Note this	     * requires offset to be set BEFORE calling calc_len in order for	     * this test to be valid.	     */	    temp = yasm_expr_create(YASM_EXPR_SUB, yasm_expr_expr(temp),				    yasm_expr_sym(jmp->origin), bc->line);	    num = yasm_expr_get_intnum(&temp, calc_bc_dist);	    if (num) {		rel = yasm_intnum_get_int(num);		rel -= jmp->shortop.opcode_len+1;		/* short displacement must fit within -128 <= rel <= +127 */		if (jmp->shortop.opcode_len != 0 && rel >= -128 &&		    rel <= 127) {		    /* It fits into a short displacement. */		    jrtype = JMP_SHORT;		} else if (jmp->nearop.opcode_len != 0) {		    /* Near for now, but could get shorter in the future if		     * there's a short form available.		     */		    jrtype = JMP_NEAR;		    if (jmp->shortop.opcode_len != 0)			retval = YASM_BC_RESOLVE_NONE;		} else {		    /* Doesn't fit into short, and there's no near opcode.		     * Error out if saving, otherwise just make it a short		     * (in the hopes that a short might make it possible for		     * it to actually be within short range).		     */		    if (save) {			yasm__error(bc->line,			    N_("short jump out of range (near jump does not exist)"));			return YASM_BC_RESOLVE_ERROR |			    YASM_BC_RESOLVE_UNKNOWN_LEN;		    }		    jrtype = JMP_SHORT;		}	    } else {		/* It's unknown.  Thus, assume near displacement.  If a near		 * opcode is not available, use a short opcode instead.		 * If we're saving, error if a near opcode is not available.		 */		if (jmp->nearop.opcode_len != 0) {		    if (jmp->shortop.opcode_len != 0)			retval = YASM_BC_RESOLVE_NONE;		    jrtype = JMP_NEAR;		} else {		    if (save) {			yasm__error(bc->line,			    N_("short jump out of range (near jump does not exist)"));			return YASM_BC_RESOLVE_ERROR |			    YASM_BC_RESOLVE_UNKNOWN_LEN;		    }		    jrtype = JMP_SHORT;		}	    }	    yasm_expr_destroy(temp);	    break;    }    switch (jrtype) {	case JMP_SHORT:	    if (save)		jmp->op_sel = JMP_SHORT;	    if (jmp->shortop.opcode_len == 0)		return YASM_BC_RESOLVE_UNKNOWN_LEN; /* size not available */	    bc->len += jmp->shortop.opcode_len + 1;	    break;	case JMP_NEAR:	    if (save)		jmp->op_sel = JMP_NEAR;	    if (jmp->nearop.opcode_len == 0)		return YASM_BC_RESOLVE_UNKNOWN_LEN; /* size not available */	    bc->len += jmp->nearop.opcode_len;	    bc->len += (opersize == 16) ? 2 : 4;	    break;	case JMP_FAR:	    if (save)		jmp->op_sel = JMP_FAR;	    if (jmp->farop.opcode_len == 0)		return YASM_BC_RESOLVE_UNKNOWN_LEN; /* size not available */	    bc->len += jmp->farop.opcode_len;	    bc->len += 2;	/* segment */	    bc->len += (opersize == 16) ? 2 : 4;	    break;	default:	    yasm_internal_error(N_("unknown jump type"));    }    bc->len += (jmp->addrsize != 0 && jmp->addrsize != jmp->mode_bits) ? 1:0;    bc->len += (jmp->opersize != 0 && jmp->opersize != jmp->mode_bits) ? 1:0;    bc->len += (jmp->lockrep_pre != 0) ? 1:0;    return retval;}static intx86_bc_insn_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,		    yasm_output_expr_func output_expr,		    /*@unused@*/ yasm_output_reloc_func output_reloc){    x86_insn *insn = (x86_insn *)bc;    /*@null@*/ x86_effaddr *x86_ea = insn->ea;    /*@null@*/ yasm_effaddr *ea = &x86_ea->ea;    yasm_immval *imm = insn->imm;    unsigned int i;    unsigned char *bufp_orig = *bufp;    /* Prefixes */    if (insn->special_prefix != 0)	YASM_WRITE_8(*bufp, insn->special_prefix);    if (insn->lockrep_pre != 0)	YASM_WRITE_8(*bufp, insn->lockrep_pre);    if (x86_ea && x86_ea->segment != 0)	YASM_WRITE_8(*bufp, x86_ea->segment);    if (insn->opersize != 0 &&	((insn->mode_bits != 64 && insn->opersize != insn->mode_bits) ||	 (insn->mode_bits == 64 && insn->opersize == 16)))	YASM_WRITE_8(*bufp, 0x66);    if (insn->addrsize != 0 && insn->addrsize != insn->mode_bits)	YASM_WRITE_8(*bufp, 0x67);    if (insn->rex != 0xff) {	if (insn->mode_bits == 64 && insn->opersize == 64 &&	    insn->def_opersize_64 != 64)	    insn->rex |= 0x48;	if (insn->rex != 0) {	    if (insn->mode_bits != 64)		yasm_internal_error(		    N_("x86: got a REX prefix in non-64-bit mode"));	    YASM_WRITE_8(*bufp, insn->rex);	}    }    /* Opcode */    for (i=0; i<insn->opcode_len; i++)	YASM_WRITE_8(*bufp, insn->opcode[i]);    /* Effective address: ModR/M (if required), SIB (if required), and     * displacement (if required).     */    if (ea) {	if (x86_ea->need_modrm) {	    if (!x86_ea->valid_modrm)		yasm_internal_error(N_("invalid Mod/RM in x86 tobytes_insn"));	    YASM_WRITE_8(*bufp, x86_ea->modrm);	}	if (x86_ea->need_sib) {	    if (!x86_ea->valid_sib)		yasm_internal_error(N_("invalid SIB in x86 tobytes_insn"));	    YASM_WRITE_8(*bufp, x86_ea->sib);	}	if (ea->disp) {	    x86_effaddr eat = *x86_ea;  /* structure copy */	    unsigned char displen = ea->len;	    unsigned char addrsize = insn->addrsize;	    eat.valid_modrm = 0;    /* force checkea to actually run */	    /* Call checkea() to simplify the registers out of the	     * displacement.  Throw away all of the return values except for	     * the modified expr.	     */	    if (yasm_x86__expr_checkea(&ea->disp, &addrsize, insn->mode_bits,				       ea->nosplit, &displen, &eat.modrm,				       &eat.valid_modrm, &eat.need_modrm,				       &eat.sib, &eat.valid_sib,				       &eat.need_sib, &eat.pcrel, &insn->rex,				       yasm_common_calc_bc_dist))		yasm_internal_error(N_("checkea failed"));	    if (ea->disp) {		if (eat.pcrel) {		    /*@null@*/ yasm_expr *wrt = yasm_expr_extract_wrt(&ea->disp);		    ea->disp =			yasm_expr_create(YASM_EXPR_SUB,					 yasm_expr_expr(ea->disp),					 yasm_expr_sym(eat.origin), bc->line);		    if (wrt) {			ea->disp =			    yasm_expr_create(YASM_EXPR_WRT,					     yasm_expr_expr(ea->disp),					     yasm_expr_expr(wrt), bc->line);		    }		    if (output_expr(&ea->disp, *bufp, ea->len,				    (size_t)(ea->len*8), 0,				    (unsigned long)(*bufp-bufp_orig), bc, 1, 1,				    d))			return 1;		} else {		    if (output_expr(&ea->disp, *bufp, ea->len,				    (size_t)(ea->len*8), 0,				    (unsigned long)(*bufp-bufp_orig), bc, 0, 1,				    d))			return 1;		}		*bufp += ea->len;	    } else {		/* 0 displacement, but we didn't know it before, so we have to		 * write out 0 value.		 */		for (i=0; i<ea->len; i++)		    YASM_WRITE_8(*bufp, 0);	    }	}    }    /* Immediate (if required) */    if (imm && imm->val) {	if (output_expr(&imm->val, *bufp, imm->len, (size_t)(imm->len*8), 0,			(unsigned long)(*bufp-bufp_orig), bc, 0, 1, d))	    return 1;	*bufp += imm->len;    }    return 0;}static intx86_bc_jmp_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,		   yasm_output_expr_func output_expr,		   /*@unused@*/ yasm_output_reloc_func output_reloc){    x86_jmp *jmp = (x86_jmp *)bc;    unsigned char opersize;    unsigned int i;    unsigned char *bufp_orig = *bufp;    /*@null@*/ yasm_expr *targetseg;    /*@null@*/ yasm_expr *wrt;    yasm_expr *dup;    /* Prefixes */    if (jmp->lockrep_pre != 0)	YASM_WRITE_8(*bufp, jmp->lockrep_pre);    /* FIXME: branch hints! */    if (jmp->opersize != 0 && jmp->opersize != jmp->mode_bits)	YASM_WRITE_8(*bufp, 0x66);    if (jmp->addrsize != 0 && jmp->addrsize != jmp->mode_bits)	YASM_WRITE_8(*bufp, 0x67);    /* As opersize may be 0, figure out its "real" value. */    opersize = (jmp->opersize == 0) ? jmp->mode_bits : jmp->opersize;    /* Check here to see if forced forms are actually legal. */    switch (jmp->op_sel) {	case JMP_SHORT_FORCED:	case JMP_SHORT:	    /* 1 byte relative displacement */	    if (jmp->shortop.opcode_len == 0)		yasm_internal_error(N_("short jump does not exist"));	    /* Opcode */	    for (i=0; i<jmp->shortop.opcode_len; i++)		YASM_WRITE_8(*bufp, jmp->shortop.opcode[i]);	    /* Relative displacement */	    wrt = yasm_expr_extract_wrt(&jmp->target);	    jmp->target =		yasm_expr_create(YASM_EXPR_SUB, yasm_expr_expr(jmp->target),				 yasm_expr_sym(jmp->origin), bc->line);	    if (wrt)		jmp->target = yasm_expr_create_tree(jmp->target,						    YASM_EXPR_WRT, wrt,						    bc->line);	    if (output_expr(&jmp->target, *bufp, 1, 8, 0,			    (unsigned long)(*bufp-bufp_orig), bc, 1, 1, d))		return 1;	    *bufp += 1;	    break;	case JMP_NEAR_FORCED:	case JMP_NEAR:	    /* 2/4 byte relative displacement (depending on operand size) */	    if (jmp->nearop.opcode_len == 0) {		yasm__error(bc->line, N_("near jump does not exist"));		return 1;	    }	    /* Opcode */	    for (i=0; i<jmp->nearop.opcode_len; i++)		YASM_WRITE_8(*bufp, jmp->nearop.opcode[i]);	    /* Relative displacement */	    wrt = yasm_expr_extract_wrt(&jmp->target);	    jmp->target =		yasm_expr_create(YASM_EXPR_SUB, yasm_expr_expr(jmp->target),				 yasm_expr_sym(jmp->origin), bc->line);	    if (wrt)		jmp->target = yasm_expr_create_tree(jmp->target,						    YASM_EXPR_WRT, wrt,						    bc->line);	    i = (opersize == 16) ? 2 : 4;	    if (output_expr(&jmp->target, *bufp, i, i*8, 0,			    (unsigned long)(*bufp-bufp_orig), bc, 1, 1, d))		return 1;	    *bufp += i;	    break;	case JMP_FAR:	    /* far absolute (4/6 byte depending on operand size) */	    if (jmp->farop.opcode_len == 0) {		yasm__error(bc->line, N_("far jump does not exist"));		return 1;	    }	    /* Opcode */	    for (i=0; i<jmp->farop.opcode_len; i++)		YASM_WRITE_8(*bufp, jmp->farop.opcode[i]);	    /* Absolute displacement: segment and offset */	    jmp->target = yasm_expr_simplify(jmp->target, NULL);	    dup = yasm_expr_copy(jmp->target);	    targetseg = yasm_expr_extract_segoff(&dup);	    if (!targetseg)		yasm_internal_error(N_("could not extract segment for far jump"));	    i = (opersize == 16) ? 2 : 4;	    if (output_expr(&dup, *bufp, i, i*8, 0,			    (unsigned long)(*bufp-bufp_orig), bc, 0, 1, d))		return 1;	    *bufp += i;	    if (output_expr(&targetseg, *bufp, 2, 2*8, 0,			    (unsigned long)(*bufp-bufp_orig), bc, 0, 1, d))		return 1;	    *bufp += 2;	    yasm_expr_destroy(dup);	    yasm_expr_destroy(targetseg);	    break;	default:	    yasm_internal_error(N_("unrecognized relative jump op_sel"));    }    return 0;}intyasm_x86__intnum_fixup_rel(yasm_arch *arch, yasm_intnum *intn, size_t valsize,			   const yasm_bytecode *bc, unsigned long line){    yasm_intnum *delta;    if (valsize != 8 && valsize != 16 && valsize != 32)	yasm_internal_error(	    N_("tried to do PC-relative offset from invalid sized value"));    delta = yasm_intnum_create_uint(bc->len);    yasm_intnum_calc(intn, YASM_EXPR_SUB, delta, line);    yasm_intnum_destroy(delta);    return 0;}intyasm_x86__intnum_tobytes(yasm_arch *arch, const yasm_intnum *intn,			 unsigned char *buf, size_t destsize, size_t valsize,			 int shift, const yasm_bytecode *bc, int warn,			 unsigned long line){    /* Write value out. */    yasm_intnum_get_sized(intn, buf, destsize, valsize, shift, 0, warn,			  line);    return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -