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

📄 x86bc.c

📁 支持AMD64的汇编编译器源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * x86 bytecode utility functions * *  Copyright (C) 2001  Peter Johnson * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */#include <util.h>/*@unused@*/ RCSID("$Id: x86bc.c 1168 2004-10-31 01:07:52Z peter $");#define YASM_LIB_INTERNAL#define YASM_BC_INTERNAL#define YASM_EXPR_INTERNAL#include <libyasm.h>#include "x86arch.h"/* Effective address type */typedef struct x86_effaddr {    yasm_effaddr ea;		/* base structure */    /* PC-relative portions are for AMD64 only (RIP addressing) */    /*@null@*/ /*@dependent@*/ yasm_symrec *origin;    /* pcrel origin */    unsigned char segment;	/* segment override, 0 if none */    /* How the spare (register) bits in Mod/RM are handled:     * Even if valid_modrm=0, the spare bits are still valid (don't overwrite!)     * They're set in bytecode_create_insn().     */    unsigned char modrm;    unsigned char valid_modrm;	/* 1 if Mod/RM byte currently valid, 0 if not */    unsigned char need_modrm;	/* 1 if Mod/RM byte needed, 0 if not */    unsigned char sib;    unsigned char valid_sib;	/* 1 if SIB byte currently valid, 0 if not */    unsigned char need_sib;	/* 1 if SIB byte needed, 0 if not,				   0xff if unknown */    unsigned char pcrel;	/* 1 if PC-relative transformation needed */} x86_effaddr;/* Bytecode types */typedef struct x86_insn {    yasm_bytecode bc;		/* base structure */    /*@null@*/ x86_effaddr *ea;	/* effective address */    /*@null@*/ yasm_immval *imm;/* immediate or relative value */    unsigned char opcode[3];	/* opcode */    unsigned char opcode_len;    unsigned char addrsize;	/* 0 or =mode_bits => no override */    unsigned char opersize;	/* 0 or =mode_bits => no override */    unsigned char lockrep_pre;	/* 0 indicates no prefix */    unsigned char def_opersize_64;  /* default operand size in 64-bit mode */    unsigned char special_prefix;   /* "special" prefix (0=none) */    unsigned char rex;		/* REX AMD64 extension, 0 if none,				   0xff if not allowed (high 8 bit reg used) */    /* HACK, but a space-saving one: shift opcodes have an immediate     * form and a ,1 form (with no immediate).  In the parser, we     * set this and opcode_len=1, but store the ,1 version in the     * second byte of the opcode array.  We then choose between the     * two versions once we know the actual value of imm (because we     * don't know it in the parser module).     *     * A override to force the imm version should just leave this at     * 0.  Then later code won't know the ,1 version even exists.     * TODO: Figure out how this affects CPU flags processing.     *     * Call x86_SetInsnShiftFlag() to set this flag to 1.     */    unsigned char shift_op;    /* HACK, similar to that for shift_op above, for optimizing instructions     * that take a sign-extended imm8 as well as imm values (eg, the arith     * instructions and a subset of the imul instructions).     */    unsigned char signext_imm8_op;    /* HACK, similar to those above, for optimizing long (modrm+sib) mov     * instructions in amd64 into short mov instructions if a 32-bit address     * override is applied in 64-bit mode to an EA of just an offset (no     * registers) and the target register is al/ax/eax/rax.     */    unsigned char shortmov_op;    unsigned char mode_bits;} x86_insn;typedef struct x86_jmp {    yasm_bytecode bc;		/* base structure */    yasm_expr *target;		/* target location */    /*@dependent@*/ yasm_symrec *origin;    /* jump origin */    struct {	unsigned char opcode[3];	unsigned char opcode_len;   /* 0 = no opc for this version */    } shortop, nearop, farop;    /* which opcode are we using? */    /* The *FORCED forms are specified in the source as such */    x86_jmp_opcode_sel op_sel;    unsigned char addrsize;	/* 0 or =mode_bits => no override */    unsigned char opersize;	/* 0 indicates no override */    unsigned char lockrep_pre;	/* 0 indicates no prefix */    unsigned char mode_bits;} x86_jmp;/* Effective address callback function prototypes */static void x86_ea_destroy(yasm_effaddr *ea);static void x86_ea_print(const yasm_effaddr *ea, FILE *f, int indent_level);/* Bytecode callback function prototypes */static void x86_bc_insn_destroy(yasm_bytecode *bc);static void x86_bc_insn_print(const yasm_bytecode *bc, FILE *f,			      int indent_level);static yasm_bc_resolve_flags x86_bc_insn_resolve    (yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist);static int x86_bc_insn_tobytes(yasm_bytecode *bc, unsigned char **bufp,			       void *d, yasm_output_expr_func output_expr,			       /*@null@*/ yasm_output_reloc_func output_reloc);static void x86_bc_jmp_destroy(yasm_bytecode *bc);static void x86_bc_jmp_print(const yasm_bytecode *bc, FILE *f,			     int indent_level);static yasm_bc_resolve_flags x86_bc_jmp_resolve    (yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist);static int x86_bc_jmp_tobytes(yasm_bytecode *bc, unsigned char **bufp,			      void *d, yasm_output_expr_func output_expr,			      /*@null@*/ yasm_output_reloc_func output_reloc);/* Effective address callback structures */static const yasm_effaddr_callback x86_ea_callback = {    x86_ea_destroy,    x86_ea_print};/* Bytecode callback structures */static const yasm_bytecode_callback x86_bc_callback_insn = {    x86_bc_insn_destroy,    x86_bc_insn_print,    x86_bc_insn_resolve,    x86_bc_insn_tobytes};static const yasm_bytecode_callback x86_bc_callback_jmp = {    x86_bc_jmp_destroy,    x86_bc_jmp_print,    x86_bc_jmp_resolve,    x86_bc_jmp_tobytes};intyasm_x86__set_rex_from_reg(unsigned char *rex, unsigned char *low3,			   unsigned long reg, unsigned int bits,			   x86_rex_bit_pos rexbit){    *low3 = (unsigned char)(reg&7);    if (bits == 64) {	x86_expritem_reg_size size = (x86_expritem_reg_size)(reg & ~0xFUL);	if (size == X86_REG8X || (reg & 0xF) >= 8) {	    if (*rex == 0xff)		return 1;	    *rex |= 0x40 | (((reg & 8) >> 3) << rexbit);	} else if (size == X86_REG8 && (reg & 7) >= 4) {	    /* AH/BH/CH/DH, so no REX allowed */	    if (*rex != 0 && *rex != 0xff)		return 1;	    *rex = 0xff;	}    }    return 0;}/*@-compmempass -mustfree@*/yasm_bytecode *yasm_x86__bc_create_insn(yasm_arch *arch, x86_new_insn_data *d){    yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)arch;    x86_insn *insn;       insn = (x86_insn *)yasm_bc_create_common(&x86_bc_callback_insn,					     sizeof(x86_insn), d->line);    insn->ea = (x86_effaddr *)d->ea;    if (d->ea) {	insn->ea->origin = d->ea_origin;	insn->ea->modrm &= 0xC7;	/* zero spare/reg bits */	insn->ea->modrm |= (d->spare << 3) & 0x38;  /* plug in provided bits */    }    if (d->imm) {	insn->imm = yasm_imm_create_expr(d->imm);	insn->imm->len = d->im_len;	insn->imm->sign = d->im_sign;    } else	insn->imm = NULL;    insn->opcode[0] = d->op[0];    insn->opcode[1] = d->op[1];    insn->opcode[2] = d->op[2];    insn->opcode_len = d->op_len;    insn->addrsize = 0;    insn->opersize = d->opersize;    insn->def_opersize_64 = d->def_opersize_64;    insn->special_prefix = d->special_prefix;    insn->lockrep_pre = 0;    insn->rex = d->rex;    insn->shift_op = d->shift_op;    insn->signext_imm8_op = d->signext_imm8_op;    insn->shortmov_op = d->shortmov_op;    insn->mode_bits = arch_x86->mode_bits;    return (yasm_bytecode *)insn;}/*@=compmempass =mustfree@*//*@-compmempass -mustfree@*/yasm_bytecode *yasm_x86__bc_create_jmp(yasm_arch *arch, x86_new_jmp_data *d){    yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)arch;    x86_jmp *jmp;    jmp = (x86_jmp *) yasm_bc_create_common(&x86_bc_callback_jmp,					    sizeof(x86_jmp), d->line);    jmp->target = d->target;    jmp->origin = d->origin;    jmp->op_sel = d->op_sel;    if ((d->op_sel == JMP_SHORT_FORCED) && (d->near_op_len == 0))	yasm__error(d->line,		    N_("no SHORT form of that jump instruction exists"));    if ((d->op_sel == JMP_NEAR_FORCED) && (d->short_op_len == 0))	yasm__error(d->line,		    N_("no NEAR form of that jump instruction exists"));    jmp->shortop.opcode[0] = d->short_op[0];    jmp->shortop.opcode[1] = d->short_op[1];    jmp->shortop.opcode[2] = d->short_op[2];    jmp->shortop.opcode_len = d->short_op_len;    jmp->nearop.opcode[0] = d->near_op[0];    jmp->nearop.opcode[1] = d->near_op[1];    jmp->nearop.opcode[2] = d->near_op[2];    jmp->nearop.opcode_len = d->near_op_len;    jmp->farop.opcode[0] = d->far_op[0];    jmp->farop.opcode[1] = d->far_op[1];    jmp->farop.opcode[2] = d->far_op[2];    jmp->farop.opcode_len = d->far_op_len;    jmp->addrsize = d->addrsize;    jmp->opersize = d->opersize;    jmp->lockrep_pre = 0;    jmp->mode_bits = arch_x86->mode_bits;    return (yasm_bytecode *)jmp;}/*@=compmempass =mustfree@*/voidyasm_x86__ea_set_segment(yasm_effaddr *ea, unsigned int segment,			 unsigned long line){    x86_effaddr *x86_ea = (x86_effaddr *)ea;    if (!ea)	return;    if (segment != 0 && x86_ea->segment != 0)	yasm__warning(YASM_WARN_GENERAL, line,		      N_("multiple segment overrides, using leftmost"));    x86_ea->segment = (unsigned char)segment;}voidyasm_x86__ea_set_disponly(yasm_effaddr *ea){    x86_effaddr *x86_ea = (x86_effaddr *)ea;    x86_ea->valid_modrm = 0;    x86_ea->need_modrm = 0;    x86_ea->valid_sib = 0;    x86_ea->need_sib = 0;    x86_ea->pcrel = 0;}yasm_effaddr *yasm_x86__ea_create_reg(unsigned long reg, unsigned char *rex,			unsigned int bits){    x86_effaddr *x86_ea;    unsigned char rm;    if (yasm_x86__set_rex_from_reg(rex, &rm, reg, bits, X86_REX_B))	return NULL;    x86_ea = yasm_xmalloc(sizeof(x86_effaddr));    x86_ea->ea.callback = &x86_ea_callback;    x86_ea->ea.disp = (yasm_expr *)NULL;    x86_ea->ea.len = 0;    x86_ea->ea.nosplit = 0;    x86_ea->segment = 0;    x86_ea->modrm = 0xC0 | rm;	/* Mod=11, R/M=Reg, Reg=0 */    x86_ea->valid_modrm = 1;    x86_ea->need_modrm = 1;    x86_ea->sib = 0;    x86_ea->valid_sib = 0;    x86_ea->need_sib = 0;    x86_ea->pcrel = 0;    return (yasm_effaddr *)x86_ea;}yasm_effaddr *yasm_x86__ea_create_expr(yasm_arch *arch, yasm_expr *e){    x86_effaddr *x86_ea;    x86_ea = yasm_xmalloc(sizeof(x86_effaddr));    x86_ea->ea.callback = &x86_ea_callback;    x86_ea->ea.disp = e;    x86_ea->ea.len = 0;    x86_ea->ea.nosplit = 0;    x86_ea->segment = 0;    x86_ea->modrm = 0;    x86_ea->valid_modrm = 0;    x86_ea->need_modrm = 1;    x86_ea->sib = 0;    x86_ea->valid_sib = 0;    /* We won't know whether we need an SIB until we know more about expr and     * the BITS/address override setting.     */    x86_ea->need_sib = 0xff;    x86_ea->pcrel = 0;    return (yasm_effaddr *)x86_ea;}/*@-compmempass@*/yasm_effaddr *yasm_x86__ea_create_imm(yasm_expr *imm, unsigned int im_len){    x86_effaddr *x86_ea;    x86_ea = yasm_xmalloc(sizeof(x86_effaddr));    x86_ea->ea.callback = &x86_ea_callback;    x86_ea->ea.disp = imm;    x86_ea->ea.len = (unsigned char)im_len;    x86_ea->ea.nosplit = 0;    x86_ea->segment = 0;    x86_ea->modrm = 0;    x86_ea->valid_modrm = 0;    x86_ea->need_modrm = 0;    x86_ea->sib = 0;    x86_ea->valid_sib = 0;    x86_ea->need_sib = 0;    x86_ea->pcrel = 0;

⌨️ 快捷键说明

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