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

📄 disasm.c

📁 nasm早期的源代码,比较简单是学习汇编和编译原理的好例子
💻 C
📖 第 1 页 / 共 3 页
字号:
        case 2:
            op->segment |= SEG_DISP32;
            op->offset = getu32(data);
	    data += 4;
            break;
        }
        return data;
    }
}

/*
 * Determine whether the instruction template in t corresponds to the data
 * stream in data. Return the number of bytes matched if so.
 */
static int matches(const struct itemplate *t, uint8_t *data,
		   const struct prefix_info *prefix, int segsize, insn *ins)
{
    uint8_t *r = (uint8_t *)(t->code);
    uint8_t *origdata = data;
    bool a_used = false, o_used = false;
    enum prefixes drep = 0;
    uint8_t lock = prefix->lock;
    int osize = prefix->osize;
    int asize = prefix->asize;
    int i;

    for (i = 0; i < MAX_OPERANDS; i++) {
	ins->oprs[i].segment = ins->oprs[i].addr_size =
	    (segsize == 64 ? SEG_64BIT : segsize == 32 ? SEG_32BIT : 0);
    }
    ins->condition = -1;
    ins->rex = prefix->rex;

    if (t->flags & (segsize == 64 ? IF_NOLONG : IF_LONG))
        return false;

    if (prefix->rep == 0xF2)
        drep = P_REPNE;
    else if (prefix->rep == 0xF3)
        drep = P_REP;

    while (*r) {
        int c = *r++;

	/* FIX: change this into a switch */
	if (c >= 01 && c <= 03) {
            while (c--)
                if (*r++ != *data++)
                    return false;
	} else if (c == 04) {
            switch (*data++) {
            case 0x07:
                ins->oprs[0].basereg = 0;
                break;
            case 0x17:
                ins->oprs[0].basereg = 2;
                break;
            case 0x1F:
                ins->oprs[0].basereg = 3;
                break;
            default:
                return false;
            }
	} else if (c == 05) {
            switch (*data++) {
            case 0xA1:
                ins->oprs[0].basereg = 4;
                break;
            case 0xA9:
                ins->oprs[0].basereg = 5;
                break;
            default:
                return false;
	    }
	} else if (c == 06) {
            switch (*data++) {
            case 0x06:
                ins->oprs[0].basereg = 0;
                break;
            case 0x0E:
                ins->oprs[0].basereg = 1;
                break;
            case 0x16:
                ins->oprs[0].basereg = 2;
                break;
            case 0x1E:
                ins->oprs[0].basereg = 3;
                break;
            default:
                return false;
            }
	} else if (c == 07) {
            switch (*data++) {
            case 0xA0:
                ins->oprs[0].basereg = 4;
                break;
            case 0xA8:
                ins->oprs[0].basereg = 5;
                break;
            default:
                return false;
            }
	} else if (c >= 010 && c <= 013) {
            int t = *r++, d = *data++;
            if (d < t || d > t + 7)
                return false;
            else {
                ins->oprs[c - 010].basereg = (d-t)+
		    (ins->rex & REX_B ? 8 : 0);
                ins->oprs[c - 010].segment |= SEG_RMREG;
            }
	} else if (c >= 014 && c <= 017) {
            ins->oprs[c - 014].offset = (int8_t)*data++;
            ins->oprs[c - 014].segment |= SEG_SIGNED;
        } else if (c >= 020 && c <= 023) {
            ins->oprs[c - 020].offset = *data++;
	} else if (c >= 024 && c <= 027) {
            ins->oprs[c - 024].offset = *data++;
	} else if (c >= 030 && c <= 033) {
            ins->oprs[c - 030].offset = getu16(data);
	    data += 2;
        } else if (c >= 034 && c <= 037) {
	    if (osize == 32) {
		ins->oprs[c - 034].offset = getu32(data);
		data += 4;
	    } else {
		ins->oprs[c - 034].offset = getu16(data);
		data += 2;
	    }
            if (segsize != asize)
                ins->oprs[c - 034].addr_size = asize;
        } else if (c >= 040 && c <= 043) {
            ins->oprs[c - 040].offset = getu32(data);
	    data += 4;
        } else if (c >= 044 && c <= 047) {
	    switch (asize) {
	    case 16:
		ins->oprs[c - 044].offset = getu16(data);
		data += 2;
		break;
	    case 32:
		ins->oprs[c - 044].offset = getu32(data);
		data += 4;
		break;
	    case 64:
		ins->oprs[c - 044].offset = getu64(data);
		data += 8;
		break;
	    }
            if (segsize != asize)
                ins->oprs[c - 044].addr_size = asize;
        } else if (c >= 050 && c <= 053) {
            ins->oprs[c - 050].offset = gets8(data++);
            ins->oprs[c - 050].segment |= SEG_RELATIVE;
        } else if (c >= 054 && c <= 057) {
	    ins->oprs[c - 054].offset = getu64(data);
	    data += 8;
	} else if (c >= 060 && c <= 063) {
            ins->oprs[c - 060].offset = gets16(data);
	    data += 2;
            ins->oprs[c - 060].segment |= SEG_RELATIVE;
            ins->oprs[c - 060].segment &= ~SEG_32BIT;
        } else if (c >= 064 && c <= 067) {
	    if (osize == 16) {
		ins->oprs[c - 064].offset = getu16(data);
		data += 2;
                ins->oprs[c - 064].segment &= ~(SEG_32BIT|SEG_64BIT);
	    } else if (osize == 32) {
		ins->oprs[c - 064].offset = getu32(data);
		data += 4;
                ins->oprs[c - 064].segment &= ~SEG_64BIT;
                ins->oprs[c - 064].segment |= SEG_32BIT;
	    }	
            if (segsize != osize) {
                ins->oprs[c - 064].type =
                    (ins->oprs[c - 064].type & ~SIZE_MASK)
                    | ((osize == 16) ? BITS16 : BITS32);
            }
        } else if (c >= 070 && c <= 073) {
            ins->oprs[c - 070].offset = getu32(data);
	    data += 4;
            ins->oprs[c - 070].segment |= SEG_32BIT | SEG_RELATIVE;
        } else if (c >= 0100 && c < 0140) {
            int modrm = *data++;
            ins->oprs[c & 07].segment |= SEG_RMREG;
            data = do_ea(data, modrm, asize, segsize,
			 &ins->oprs[(c >> 3) & 07], ins);
	    if (!data)
		return false;
            ins->oprs[c & 07].basereg = ((modrm >> 3)&7)+
		(ins->rex & REX_R ? 8 : 0);
        } else if (c >= 0140 && c <= 0143) {
            ins->oprs[c - 0140].offset = getu16(data);
	    data += 2;
        } else if (c >= 0150 && c <= 0153) {
	    ins->oprs[c - 0150].offset = getu32(data);
	    data += 4;
	} else if (c >= 0160 && c <= 0167) {
	    ins->rex |= (c & 4) ? REX_D|REX_OC : REX_D;
	    ins->drexdst = c & 3;
        } else if (c == 0170) {
            if (*data++)
                return false;
	} else if (c == 0171) {
	    data = do_drex(data, ins);
	    if (!data)
		return false;
        } else if (c >= 0200 && c <= 0277) {
            int modrm = *data++;
            if (((modrm >> 3) & 07) != (c & 07))
                return false;   /* spare field doesn't match up */
            data = do_ea(data, modrm, asize, segsize,
                         &ins->oprs[(c >> 3) & 07], ins);
	    if (!data)
		return false;
        } else if (c == 0310) {
            if (asize != 16)
                return false;
            else
                a_used = true;
        } else if (c == 0311) {
            if (asize == 16)
                return false;
            else
                a_used = true;
        } else if (c == 0312) {
            if (asize != segsize)
                return false;
            else
                a_used = true;
	} else if (c == 0313) {
	    if (asize != 64)
		return false;
	    else
		a_used = true;
        } else if (c == 0320) {
            if (osize != 16)
                return false;
            else
                o_used = true;
        } else if (c == 0321) {
            if (osize != 32)
                return false;
            else
                o_used = true;
        } else if (c == 0322) {
            if (osize != (segsize == 16) ? 16 : 32)
                return false;
            else
                o_used = true;
        } else if (c == 0323) {
	    ins->rex |= REX_W;	/* 64-bit only instruction */
	    osize = 64;
	} else if (c == 0324) {
	    if (!(ins->rex & (REX_P|REX_W)) || osize != 64)
		return false;
	} else if (c == 0330) {
            int t = *r++, d = *data++;
            if (d < t || d > t + 15)
                return false;
            else
                ins->condition = d - t;
        } else if (c == 0331) {
            if (prefix->rep)
                return false;
	} else if (c == 0332) {
	    if (prefix->rep != 0xF2)
		return false;
        } else if (c == 0333) {
            if (prefix->rep != 0xF3)
                return false;
            drep = 0;
        } else if (c == 0334) {
	    if (lock) {
		ins->rex |= REX_R;
		lock = 0;
	    }
        } else if (c == 0335) {
            if (drep == P_REP)
                drep = P_REPE;
	} else if (c == 0364) {
	    if (prefix->osp)
		return false;
	} else if (c == 0365) {
	    if (prefix->asp)
		return false;
	} else if (c == 0366) {
	    if (!prefix->osp)
		return false;
	    o_used = true;
	} else if (c == 0367) {
	    if (!prefix->asp)
		return false;
	    o_used = true;
	}
    }

    /* REX cannot be combined with DREX */
    if ((ins->rex & REX_D) && (prefix->rex))
	return false;

    /*
     * Check for unused rep or a/o prefixes.
     */
    for (i = 0; i < t->operands; i++) {
	if (ins->oprs[i].segment != SEG_RMREG)
	    a_used = true;
    }

    ins->nprefix = 0;
    if (lock)
	ins->prefixes[ins->nprefix++] = P_LOCK;
    if (drep)
        ins->prefixes[ins->nprefix++] = drep;
    if (!a_used && asize != segsize)
        ins->prefixes[ins->nprefix++] = asize == 16 ? P_A16 : P_A32;
    if (!o_used && osize == ((segsize == 16) ? 32 : 16))
        ins->prefixes[ins->nprefix++] = osize == 16 ? P_O16 : P_O32;

    /* Fix: check for redundant REX prefixes */

    return data - origdata;
}

int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize,
            int32_t offset, int autosync, uint32_t prefer)
{
    const struct itemplate * const *p, * const *best_p;
    const struct disasm_index *ix;
    uint8_t *dp;
    int length, best_length = 0;
    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;

    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;

⌨️ 快捷键说明

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