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

📄 assemble.c

📁 nasm早期的源代码,比较简单是学习汇编和编译原理的好例子
💻 C
📖 第 1 页 / 共 5 页
字号:
                        out(offset, segment, &data, OUT_ADDRESS + 1,
                            ins->oprs[(c >> 3) & 7].segment,
                            ins->oprs[(c >> 3) & 7].wrt);
                    } else {
                        *bytes = ins->oprs[(c >> 3) & 7].offset;
                        out(offset, segment, bytes, OUT_RAWDATA + 1,
                            NO_SEG, NO_SEG);
                    }
                    s++;
                    break;
                case 8:               
                case 2:
                case 4:
                    data = ins->oprs[(c >> 3) & 7].offset;
                    out(offset, segment, &data,
                        (ea_data.rip ?  OUT_REL4ADR : OUT_ADDRESS)
			+ ea_data.bytes,
                        ins->oprs[(c >> 3) & 7].segment,
                        ins->oprs[(c >> 3) & 7].wrt);
                    s += ea_data.bytes;
                    break;
                }
                offset += s;
            } else
                errfunc(ERR_PANIC, "internal instruction table corrupt"
                        ": instruction code 0x%02X given", c);
        }
}

static int32_t regflag(const operand * o)
{
    if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
        errfunc(ERR_PANIC, "invalid operand passed to regflag()");
    }
    return reg_flags[o->basereg];
}

static int32_t regval(const operand * o)
{
    if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
        errfunc(ERR_PANIC, "invalid operand passed to regval()");
    }
    return regvals[o->basereg];
}

static int op_rexflags(const operand * o, int mask)
{
    int32_t flags;
    int val;

    if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
        errfunc(ERR_PANIC, "invalid operand passed to op_rexflags()");
    }

    flags = reg_flags[o->basereg];
    val = regvals[o->basereg];

    return rexflags(val, flags, mask);
}

static int rexflags(int val, int32_t flags, int mask)
{
    int rex = 0;

    if (val >= 8)
	rex |= REX_B|REX_X|REX_R;
    if (flags & BITS64)
	rex |= REX_W;
    if (!(REG_HIGH & ~flags))	/* AH, CH, DH, BH */
	rex |= REX_H;
    else if (!(REG8 & ~flags) && val >= 4) /* SPL, BPL, SIL, DIL */
	rex |= REX_P;

    return rex & mask;
}

static int matches(const struct itemplate *itemp, insn * instruction, int bits)
{
    int i, size[MAX_OPERANDS], asize, oprs, ret;

    ret = 100;

    /*
     * Check the opcode
     */
    if (itemp->opcode != instruction->opcode)
        return 0;

    /*
     * Count the operands
     */
    if (itemp->operands != instruction->operands)
        return 0;

    /*
     * Check that no spurious colons or TOs are present
     */
    for (i = 0; i < itemp->operands; i++)
        if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON | TO))
            return 0;
            
    /*
     * Check that the operand flags all match up
     */
    for (i = 0; i < itemp->operands; i++) {
	if (itemp->opd[i] & SAME_AS) {
	    int j = itemp->opd[i] & ~SAME_AS;
	    if (instruction->oprs[i].type != instruction->oprs[j].type ||
		instruction->oprs[i].basereg != instruction->oprs[j].basereg)
		return 0;
	} else if (itemp->opd[i] & ~instruction->oprs[i].type ||
            ((itemp->opd[i] & SIZE_MASK) &&
             ((itemp->opd[i] ^ instruction->oprs[i].type) & SIZE_MASK))) {
            if ((itemp->opd[i] & ~instruction->oprs[i].type & ~SIZE_MASK) ||
                (instruction->oprs[i].type & SIZE_MASK))
                return 0;
            else
                return 1;
        }
    }

    /*
     * Check operand sizes
     */
    if (itemp->flags & IF_ARMASK) {
	memset(size, 0, sizeof size);

        switch (itemp->flags & IF_ARMASK) {
        case IF_AR0:
            i = 0;
            break;
        case IF_AR1:
            i = 1;
            break;
        case IF_AR2:
            i = 2;
            break;
	case IF_AR3:
	    i = 3;
	    break;
        default:
            break;              /* Shouldn't happen */
        }
	switch (itemp->flags & IF_SMASK) {
	case IF_SB:
            size[i] = BITS8;
	    break;
	case IF_SW:
            size[i] = BITS16;
	    break;
	case IF_SD:
            size[i] = BITS32;
	    break;
	case IF_SQ:
            size[i] = BITS64;
	    break;
	case IF_SO:
	    size[i] = BITS128;
	    break;
	default:
	    break;
        }
    } else {
        asize = 0;
	switch (itemp->flags & IF_SMASK) {
	case IF_SB:
            asize = BITS8;
            oprs = itemp->operands;
	    break;
	case IF_SW:
            asize = BITS16;
            oprs = itemp->operands;
	    break;
	case IF_SD:
            asize = BITS32;
            oprs = itemp->operands;
	    break;
	case IF_SQ:
            asize = BITS64;
            oprs = itemp->operands;
	    break;
	case IF_SO:
            asize = BITS128;
            oprs = itemp->operands;
	    break;
	default:
	    break;
        }
	for (i = 0; i < MAX_OPERANDS; i++)
	    size[i] = asize;
    }
    
    if (itemp->flags & (IF_SM | IF_SM2)) {
        oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
        asize = 0;
        for (i = 0; i < oprs; i++) {
            if ((asize = itemp->opd[i] & SIZE_MASK) != 0) {
                int j;
                for (j = 0; j < oprs; j++)
                    size[j] = asize;
                break;
            }
        }
    } else {
        oprs = itemp->operands;
    }

    for (i = 0; i < itemp->operands; i++) {
        if (!(itemp->opd[i] & SIZE_MASK) &&
            (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
            return 2;
    }

    /*
     * Check template is okay at the set cpu level
     */
    if (((itemp->flags & IF_PLEVEL) > cpu))
        return 3;
        
    /*
     * Check if instruction is available in long mode
     */
    if ((itemp->flags & IF_NOLONG) && (bits == 64))
        return 4;

    /*
     * Check if special handling needed for Jumps
     */
    if ((uint8_t)(itemp->code[0]) >= 0370)
        return 99;

    return ret;
}

static ea *process_ea(operand * input, ea * output, int addrbits,
                      int rfield, int32_t rflags, int forw_ref)
{
    output->rip = false;

    /* REX flags for the rfield operand */
    output->rex |= rexflags(rfield, rflags, REX_R|REX_P|REX_W|REX_H);

    if (!(REGISTER & ~input->type)) {   /* register direct */
        int i;
	int32_t f;

        if (input->basereg < EXPR_REG_START /* Verify as Register */
            || input->basereg >= REG_ENUM_LIMIT)
            return NULL;
	f = regflag(input);
        i = regvals[input->basereg];

	if (REG_EA & ~f)
	    return NULL;	/* Invalid EA register */
	
	output->rex |= op_rexflags(input, REX_B|REX_P|REX_W|REX_H);

        output->sib_present = false;             /* no SIB necessary */
        output->bytes = 0;  /* no offset necessary either */
        output->modrm = 0xC0 | ((rfield & 7) << 3) | (i & 7);
    } else {                    /* it's a memory reference */
        if (input->basereg == -1
            && (input->indexreg == -1 || input->scale == 0)) {
            /* it's a pure offset */
            if (input->addr_size)
                addrbits = input->addr_size;

            if (globalbits == 64 && (~input->type & IP_REL)) {
              int scale, index, base;
              output->sib_present = true;
              scale = 0;
              index = 4;
              base = 5;
              output->sib = (scale << 6) | (index << 3) | base;
              output->bytes = 4;
              output->modrm = 4 | ((rfield & 7) << 3);
	      output->rip = false;
            } else {
              output->sib_present = false;
              output->bytes = (addrbits != 16 ? 4 : 2);
              output->modrm = (addrbits != 16 ? 5 : 6) | ((rfield & 7) << 3);
	      output->rip = globalbits == 64;
            }
        } else {                /* it's an indirection */
            int i = input->indexreg, b = input->basereg, s = input->scale;
            int32_t o = input->offset, seg = input->segment;
            int hb = input->hintbase, ht = input->hinttype;
            int t;
            int it, bt;
	    int32_t ix, bx;	/* register flags */

            if (s == 0)
                i = -1;         /* make this easy, at least */
                
            if (i >= EXPR_REG_START && i < REG_ENUM_LIMIT) {
                it = regvals[i];
		ix = reg_flags[i];
	    } else {
                it = -1;
		ix = 0;
	    }
                
	    if (b != -1 && b >= EXPR_REG_START && b < REG_ENUM_LIMIT) {
                bt = regvals[b];
		bx = reg_flags[b];
	    } else {
                bt = -1;
		bx = 0;
	    }
                
	    /* check for a 32/64-bit memory reference... */
	    if ((ix|bx) & (BITS32|BITS64)) {
                /* it must be a 32/64-bit memory reference. Firstly we have
                 * to check that all registers involved are type E/Rxx. */
		int32_t sok = BITS32|BITS64;

                if (it != -1) {
		    if (!(REG64 & ~ix) || !(REG32 & ~ix))
			sok &= ix;
		    else
			return NULL;
		}

		if (bt != -1) {
		    if (REG_GPR & ~bx)
			return NULL; /* Invalid register */
		    if (~sok & bx & SIZE_MASK)
			return NULL; /* Invalid size */
		    sok &= ~bx;
		}
                
                /* While we're here, ensure the user didn't specify WORD. */
                if (input->addr_size == 16 ||
		    (input->addr_size == 32 && !(sok & BITS32)) ||
		    (input->addr_size == 64 && !(sok & BITS64)))
                    return NULL;

                /* now reorganize base/index */
                if (s == 1 && bt != it && bt != -1 && it != -1 &&
                    ((hb == b && ht == EAH_NOTBASE)
                     || (hb == i && ht == EAH_MAKEBASE))) {
		    /* swap if hints say so */
                    t = bt, bt = it, it = t;
		    t = bx, bx = ix, ix = t;
		}
                if (bt == it)     /* convert EAX+2*EAX to 3*EAX */
                    bt = -1, bx = 0, s++;
                if (bt == -1 && s == 1 && !(hb == it && ht == EAH_NOTBASE)) {
		    /* make single reg base, unless hint */
                    bt = it, bx = ix, it = -1, ix = 0;
		}
                if (((s == 2 && it != REG_NUM_ESP
                      && !(input->eaflags & EAF_TIMESTWO)) || s == 3
                     || s == 5 || s == 9) && bt == -1)
                    bt = it, bx = ix, s--; /* convert 3*EAX to EAX+2*EAX */
                if (it == -1 && (bt & 7) != REG_NUM_ESP
                    && (input->eaflags & EAF_TIMESTWO))
                    it = bt, ix = bx, bt = -1, bx = 0, s = 1;
                /* convert [NOSPLIT EAX] to sib format with 0x0 displacement */
                if (s == 1 && it == REG_NUM_ESP) {
		    /* swap ESP into base if scale is 1 */
                    t = it, it = bt, bt = t;
		    t = ix, ix = bx, bx = t;
		}
                if (it == REG_NUM_ESP
                    || (s != 1 && s != 2 && s != 4 && s != 8 && it != -1))
                    return NULL;        /* wrong, for various reasons */

		output->rex |= rexflags(it, ix, REX_X);
		output->rex |= rexflags(bt, bx, REX_B);

                if (it == -1 && (bt & 7) != REG_NUM_ESP) {
		    /* no SIB needed */
                    int mod, rm;
                    
                    if (bt == -1) {
                        rm = 5;
                        mod = 0;
                    } else {
                        rm = (bt & 7);
                        if (rm != REG_NUM_EBP && o == 0 &&
                                seg == NO_SEG && !forw_ref &&
                                !(input->eaflags &
                                  (EAF_BYTEOFFS | EAF_WORDOFFS)))
                            mod = 0;
                        else if (input->eaflags & EAF_BYTEOFFS ||
                                 (o >= -128 && o <= 127 && seg == NO_SEG
                                  && !forw_ref
                                  && !(input->eaflags & EAF_WORDOFFS)))
                            mod = 1;
                        else
                            mod = 2;
                    }

                    output->sib_present = false;

⌨️ 快捷键说明

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