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

📄 disasm.c

📁 nasm早期的源代码,比较简单是学习汇编和编译原理的好例子
💻 C
📖 第 1 页 / 共 3 页
字号:
    for (;;) {
        if (*data == 0xF3 || *data == 0xF2)
            prefix.rep = *data++;
        else if (*data == 0xF0)
            prefix.lock = *data++;
        else if (*data == 0x2E)
	    segover = "cs", prefix.seg = *data++;
	else if (*data == 0x36)
	    segover = "ss", prefix.seg = *data++;
	else if (*data == 0x3E)
	    segover = "ds", prefix.seg = *data++;
	else if (*data == 0x26)
	    segover = "es", prefix.seg = *data++;
	else if (*data == 0x64)
	    segover = "fs", prefix.seg = *data++;
	else if (*data == 0x65)
	    segover = "gs", prefix.seg = *data++;
	else if (*data == 0x66) {
	    prefix.osize = (segsize == 16) ? 32 : 16;
	    prefix.osp = *data++;
	} else if (*data == 0x67) {
	    prefix.asize = (segsize == 32) ? 16 : 32;
	    prefix.asp = *data++;
	} else if (segsize == 64 && (*data & 0xf0) == REX_P) {
	    prefix.rex = *data++;
	    if (prefix.rex & REX_W)
		prefix.osize = 64;
	    break;		/* REX is always the last prefix */
	} else {
            break;
	}
    }

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

    dp = data;
    ix = itable + *dp++;
    while (ix->n == (size_t)-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) {
                goodness = ((*p)->flags & IF_PFMASK) ^ prefer;
                if (tmp_ins.nprefix < best_pref ||
		    (tmp_ins.nprefix == best_pref && goodness < best)) {
                    /* This is the best one found so far */
                    best = goodness;
                    best_p = p;
		    best_pref = tmp_ins.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 < ins.nprefix; 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_O16:
            slen += snprintf(output + slen, outbufsize - slen, "o16 ");
            break;
        case P_O32:
            slen += snprintf(output + slen, outbufsize - slen, "o32 ");
            break;
	default:
	    break;
        }

    for (i = 0; i < (int)elements(ico); i++)
        if ((*p)->opcode == ico[i]) {
            slen +=
                snprintf(output + slen, outbufsize - slen, "%s%s", icn[i],
                         whichcond(ins.condition));
            break;
        }
    if (i >= (int)elements(ico))
        slen +=
            snprintf(output + slen, outbufsize - slen, "%s",
                     insn_names[(*p)->opcode]);
    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;
            /*
             * 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",
                             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->addr_size ==
                          32 ? "dword " : o->addr_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 & FAR)
                slen += snprintf(output + slen, outbufsize - slen, "far ");
            if (t & NEAR)
                slen +=
                    snprintf(output + slen, outbufsize - slen, "near ");
            output[slen++] = '[';
            if (o->addr_size)
                slen += snprintf(output + slen, outbufsize - slen, "%s",
                                 (o->addr_size == 64 ? "qword " :
				  o->addr_size == 32 ? "dword " :
                                  o->addr_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",
                                 reg_names[(o->basereg -
                                            EXPR_REG_START)]);
                started = true;
            }
            if (o->indexreg != -1) {
                if (started)
                    output[slen++] = '+';
                slen += snprintf(output + slen, outbufsize - slen, "%s",
                                 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) {
		int minus = 0;
		int8_t offset = offs;
		if (offset < 0) {
		    minus = 1;
		    offset = -offset;
		}
                slen +=
                    snprintf(output + slen, outbufsize - slen, "%s0x%"PRIx8"",
			     minus ? "-" : "+", offset);
            } else if (o->segment & SEG_DISP16) {
		int minus = 0;
		int16_t offset = offs;
		if (offset < 0) {
		    minus = 1;
		    offset = -offset;
		}
                slen +=
                    snprintf(output + slen, outbufsize - slen, "%s0x%"PRIx16"",
			     minus ? "-" : started ? "+" : "", offset);
            } else if (o->segment & SEG_DISP32) {
		    char *prefix = "";
		    int32_t offset = offs;
		    if (offset < 0) {
			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 + -