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

📄 disasm.c

📁 汇编编译器的最新版本的源码.买了自己动手写操作系统这本书的人一定要下
💻 C
📖 第 1 页 / 共 3 页
字号:
    char *segover;
    int i, slen, colon, n;
    uint8_t *origdata;
    int works;
    insn tmp_ins, ins;
    uint32_t goodness, best;
    int best_pref;
    struct prefix_info prefix;
    bool end_prefix;

    memset(&ins, 0, sizeof ins);

    /*
     * Scan for prefixes.
     */
    memset(&prefix, 0, sizeof prefix);
    prefix.asize = segsize;
    prefix.osize = (segsize == 64) ? 32 : segsize;
    segover = NULL;
    origdata = data;

    ix = itable;

    end_prefix = false;
    while (!end_prefix) {
	switch (*data) {
	case 0xF2:
	case 0xF3:
            prefix.rep = *data++;
	    break;

	case 0xF0:
            prefix.lock = *data++;
	    break;

	case 0x2E:
	    segover = "cs", prefix.seg = *data++;
	    break;
	case 0x36:
	    segover = "ss", prefix.seg = *data++;
	    break;
	case 0x3E:
	    segover = "ds", prefix.seg = *data++;
	    break;
	case 0x26:
	    segover = "es", prefix.seg = *data++;
	    break;
	case 0x64:
	    segover = "fs", prefix.seg = *data++;
	    break;
	case 0x65:
	    segover = "gs", prefix.seg = *data++;
	    break;

	case 0x66:
	    prefix.osize = (segsize == 16) ? 32 : 16;
	    prefix.osp = *data++;
	    break;
	case 0x67:
	    prefix.asize = (segsize == 32) ? 16 : 32;
	    prefix.asp = *data++;
	    break;

	case 0xC4:
	case 0xC5:
	    if (segsize == 64 || (data[1] & 0xc0) == 0xc0) {
		prefix.vex[0] = *data++;
		prefix.vex[1] = *data++;

		prefix.rex = REX_V;

		if (prefix.vex[0] == 0xc4) {
		    prefix.vex[2] = *data++;
		    prefix.rex |= (~prefix.vex[1] >> 5) & 7; /* REX_RXB */
		    prefix.rex |= (prefix.vex[2] >> (7-3)) & REX_W;
		    prefix.vex_m = prefix.vex[1] & 0x1f;
		    prefix.vex_v = (~prefix.vex[2] >> 3) & 15;
		    prefix.vex_lp = prefix.vex[2] & 7;
		} else {
		    prefix.rex |= (~prefix.vex[1] >> (7-2)) & REX_R;
		    prefix.vex_m = 1;
		    prefix.vex_v = (~prefix.vex[1] >> 3) & 15;
		    prefix.vex_lp = prefix.vex[1] & 7;
		}

		ix = itable_VEX[prefix.vex_m][prefix.vex_lp];
	    }
	    end_prefix = true;
	    break;

	case REX_P + 0x0:
	case REX_P + 0x1:
	case REX_P + 0x2:
	case REX_P + 0x3:
	case REX_P + 0x4:
	case REX_P + 0x5:
	case REX_P + 0x6:
	case REX_P + 0x7:
	case REX_P + 0x8:
	case REX_P + 0x9:
	case REX_P + 0xA:
	case REX_P + 0xB:
	case REX_P + 0xC:
	case REX_P + 0xD:
	case REX_P + 0xE:
	case REX_P + 0xF:
	    if (segsize == 64) {
		prefix.rex = *data++;
		if (prefix.rex & REX_W)
		    prefix.osize = 64;
	    }
	    end_prefix = true;
	    break;

	default:
	    end_prefix = true;
	    break;
	}
    }

    best = -1;			/* Worst possible */
    best_p = NULL;
    best_pref = INT_MAX;

    if (!ix)
	return 0;		/* No instruction table at all... */

    dp = data;
    ix += *dp++;
    while (ix->n == -1) {
	ix = (const struct disasm_index *)ix->p + *dp++;
    }

    p = (const struct itemplate * const *)ix->p;
    for (n = ix->n; n; n--, p++) {
        if ((length = matches(*p, data, &prefix, segsize, &tmp_ins))) {
            works = true;
            /*
             * Final check to make sure the types of r/m match up.
	     * XXX: Need to make sure this is actually correct.
             */
            for (i = 0; i < (*p)->operands; i++) {
                if (!((*p)->opd[i] & SAME_AS) &&
		    (
			/* If it's a mem-only EA but we have a
			   register, die. */
			((tmp_ins.oprs[i].segment & SEG_RMREG) &&
			 !(MEMORY & ~(*p)->opd[i])) ||
			/* If it's a reg-only EA but we have a memory
			   ref, die. */
			(!(tmp_ins.oprs[i].segment & SEG_RMREG) &&
			 !(REG_EA & ~(*p)->opd[i]) &&
			 !((*p)->opd[i] & REG_SMASK)) ||
			/* Register type mismatch (eg FS vs REG_DESS):
			   die. */
			((((*p)->opd[i] & (REGISTER | FPUREG)) ||
			  (tmp_ins.oprs[i].segment & SEG_RMREG)) &&
			 !whichreg((*p)->opd[i],
				   tmp_ins.oprs[i].basereg, tmp_ins.rex))
			)) {
                    works = false;
                    break;
                }
            }

	    /*
	     * Note: we always prefer instructions which incorporate
	     * prefixes in the instructions themselves.  This is to allow
	     * e.g. PAUSE to be preferred to REP NOP, and deal with
	     * MMX/SSE instructions where prefixes are used to select
	     * between MMX and SSE register sets or outright opcode
	     * selection.
	     */
            if (works) {
		int i, nprefix;
                goodness = ((*p)->flags & IF_PFMASK) ^ prefer;
		nprefix = 0;
		for (i = 0; i < MAXPREFIX; i++)
		    if (tmp_ins.prefixes[i])
			nprefix++;
                if (nprefix < best_pref ||
		    (nprefix == best_pref && goodness < best)) {
                    /* This is the best one found so far */
                    best = goodness;
                    best_p = p;
		    best_pref = nprefix;
                    best_length = length;
                    ins = tmp_ins;
                }
            }
        }
    }

    if (!best_p)
        return 0;               /* no instruction was matched */

    /* Pick the best match */
    p = best_p;
    length = best_length;

    slen = 0;

    /* TODO: snprintf returns the value that the string would have if
     *      the buffer were long enough, and not the actual length of
     *      the returned string, so each instance of using the return
     *      value of snprintf should actually be checked to assure that
     *      the return value is "sane."  Maybe a macro wrapper could
     *      be used for that purpose.
     */
    for (i = 0; i < MAXPREFIX; i++)
        switch (ins.prefixes[i]) {
	case P_LOCK:
	    slen += snprintf(output + slen, outbufsize - slen, "lock ");
	    break;
        case P_REP:
            slen += snprintf(output + slen, outbufsize - slen, "rep ");
            break;
        case P_REPE:
            slen += snprintf(output + slen, outbufsize - slen, "repe ");
            break;
        case P_REPNE:
            slen += snprintf(output + slen, outbufsize - slen, "repne ");
            break;
        case P_A16:
            slen += snprintf(output + slen, outbufsize - slen, "a16 ");
            break;
        case P_A32:
            slen += snprintf(output + slen, outbufsize - slen, "a32 ");
            break;
        case P_A64:
            slen += snprintf(output + slen, outbufsize - slen, "a64 ");
            break;
        case P_O16:
            slen += snprintf(output + slen, outbufsize - slen, "o16 ");
            break;
        case P_O32:
            slen += snprintf(output + slen, outbufsize - slen, "o32 ");
            break;
        case P_O64:
            slen += snprintf(output + slen, outbufsize - slen, "o64 ");
            break;
	default:
	    break;
        }

    i = (*p)->opcode;
    if (i >= FIRST_COND_OPCODE)
	slen += snprintf(output + slen, outbufsize - slen, "%s%s",
			 nasm_insn_names[i], condition_name[ins.condition]);
    else
        slen += snprintf(output + slen, outbufsize - slen, "%s",
			 nasm_insn_names[i]);

    colon = false;
    length += data - origdata;  /* fix up for prefixes */
    for (i = 0; i < (*p)->operands; i++) {
	opflags_t t = (*p)->opd[i];
	const operand *o = &ins.oprs[i];
	int64_t offs;

	if (t & SAME_AS) {
	    o = &ins.oprs[t & ~SAME_AS];
	    t = (*p)->opd[t & ~SAME_AS];
	}

        output[slen++] = (colon ? ':' : i == 0 ? ' ' : ',');

	offs = o->offset;
        if (o->segment & SEG_RELATIVE) {
            offs += offset + length;
            /*
             * sort out wraparound
             */
            if (!(o->segment & (SEG_32BIT|SEG_64BIT)))
		offs &= 0xffff;
	    else if (segsize != 64)
		offs &= 0xffffffff;

            /*
             * add sync marker, if autosync is on
             */
            if (autosync)
                add_sync(offs, 0L);
        }

        if (t & COLON)
            colon = true;
        else
            colon = false;

        if ((t & (REGISTER | FPUREG)) ||
            (o->segment & SEG_RMREG)) {
	    enum reg_enum reg;
            reg = whichreg(t, o->basereg, ins.rex);
            if (t & TO)
                slen += snprintf(output + slen, outbufsize - slen, "to ");
            slen += snprintf(output + slen, outbufsize - slen, "%s",
                             nasm_reg_names[reg-EXPR_REG_START]);
        } else if (!(UNITY & ~t)) {
            output[slen++] = '1';
        } else if (t & IMMEDIATE) {
            if (t & BITS8) {
                slen +=
                    snprintf(output + slen, outbufsize - slen, "byte ");
                if (o->segment & SEG_SIGNED) {
                    if (offs < 0) {
                        offs *= -1;
                        output[slen++] = '-';
                    } else
                        output[slen++] = '+';
                }
            } else if (t & BITS16) {
                slen +=
                    snprintf(output + slen, outbufsize - slen, "word ");
            } else if (t & BITS32) {
                slen +=
                    snprintf(output + slen, outbufsize - slen, "dword ");
            } else if (t & BITS64) {
                slen +=
                    snprintf(output + slen, outbufsize - slen, "qword ");
            } else if (t & NEAR) {
                slen +=
                    snprintf(output + slen, outbufsize - slen, "near ");
            } else if (t & SHORT) {
                slen +=
                    snprintf(output + slen, outbufsize - slen, "short ");
            }
            slen +=
                snprintf(output + slen, outbufsize - slen, "0x%"PRIx64"",
                         offs);
        } else if (!(MEM_OFFS & ~t)) {
            slen +=
                snprintf(output + slen, outbufsize - slen,
			 "[%s%s%s0x%"PRIx64"]",
                         (segover ? segover : ""),
                         (segover ? ":" : ""),
			 (o->disp_size == 64 ? "qword " :
			  o->disp_size == 32 ? "dword " :
			  o->disp_size == 16 ? "word " : ""), offs);
            segover = NULL;
        } else if (!(REGMEM & ~t)) {
            int started = false;
            if (t & BITS8)
                slen +=
                    snprintf(output + slen, outbufsize - slen, "byte ");
            if (t & BITS16)
                slen +=
                    snprintf(output + slen, outbufsize - slen, "word ");
            if (t & BITS32)
                slen +=
                    snprintf(output + slen, outbufsize - slen, "dword ");
            if (t & BITS64)
                slen +=
                    snprintf(output + slen, outbufsize - slen, "qword ");
            if (t & BITS80)
                slen +=
                    snprintf(output + slen, outbufsize - slen, "tword ");
            if (t & BITS128)
                slen +=
                    snprintf(output + slen, outbufsize - slen, "oword ");
            if (t & BITS256)
                slen +=
                    snprintf(output + slen, outbufsize - slen, "yword ");
            if (t & FAR)
                slen += snprintf(output + slen, outbufsize - slen, "far ");
            if (t & NEAR)
                slen +=
                    snprintf(output + slen, outbufsize - slen, "near ");
            output[slen++] = '[';
            if (o->disp_size)
                slen += snprintf(output + slen, outbufsize - slen, "%s",
                                 (o->disp_size == 64 ? "qword " :
				  o->disp_size == 32 ? "dword " :
                                  o->disp_size == 16 ? "word " :
				  ""));
	    if (o->eaflags & EAF_REL)
		slen += snprintf(output + slen, outbufsize - slen, "rel ");
            if (segover) {
                slen +=
                    snprintf(output + slen, outbufsize - slen, "%s:",
                             segover);
                segover = NULL;
            }
            if (o->basereg != -1) {
                slen += snprintf(output + slen, outbufsize - slen, "%s",
                                 nasm_reg_names[(o->basereg-EXPR_REG_START)]);
                started = true;
            }
            if (o->indexreg != -1) {
                if (started)
                    output[slen++] = '+';
                slen += snprintf(output + slen, outbufsize - slen, "%s",
                                 nasm_reg_names[(o->indexreg-EXPR_REG_START)]);
                if (o->scale > 1)
                    slen +=
                        snprintf(output + slen, outbufsize - slen, "*%d",
                                 o->scale);
                started = true;
            }


            if (o->segment & SEG_DISP8) {
		const char *prefix;
		uint8_t offset = offs;
		if ((int8_t)offset < 0) {
		    prefix = "-";
		    offset = -offset;
		} else {
		    prefix = "+";
		}
                slen +=
                    snprintf(output + slen, outbufsize - slen, "%s0x%"PRIx8"",
			     prefix, offset);
            } else if (o->segment & SEG_DISP16) {
		const char *prefix;
		uint16_t offset = offs;
		if ((int16_t)offset < 0 && started) {
		    offset = -offset;
		    prefix = "-";
		} else {
		    prefix = started ? "+" : "";
		}
                slen +=
                    snprintf(output + slen, outbufsize - slen,
			     "%s0x%"PRIx16"", prefix, offset);
            } else if (o->segment & SEG_DISP32) {
		if (prefix.asize == 64) {
		    const char *prefix;
		    uint64_t offset = (int64_t)(int32_t)offs;
		    if ((int32_t)offs < 0 && started) {
			offset = -offset;
			prefix = "-";
		    } else {
			prefix = started ? "+" : "";
		    }
		    slen +=
			snprintf(output + slen, outbufsize - slen,
				 "%s0x%"PRIx64"", prefix, offset);
		} else {
		    const char *prefix;
		    uint32_t offset = offs;
		    if ((int32_t) offset < 0 && started) {
			offset = -offset;
			prefix = "-";
		    } else {
			prefix = started ? "+" : "";
		    }
		    slen +=
			snprintf(output + slen, outbufsize - slen,
				 "%s0x%"PRIx32"", prefix, offset);
		}
            }
            output[slen++] = ']';
        } else {
            slen +=
                snprintf(output + slen, outbufsize - slen, "<operand%d>",
                         i);
        }
    }
    output[slen] = '\0';
    if (segover) {              /* unused segment override */
        char *p = output;
        int count = slen + 1;
        while (count--)
            p[count + 3] = p[count];
        strncpy(output, segover, 2);
        output[2] = ' ';
    }
    return length;
}

int32_t eatbyte(uint8_t *data, char *output, int outbufsize)
{
    snprintf(output, outbufsize, "db 0x%02X", *data);
    return 1;
}

⌨️ 快捷键说明

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