assemble.c

来自「nasm早期的源代码,比较简单是学习汇编和编译原理的好例子」· C语言 代码 · 共 1,987 行 · 第 1/5 页

C
1,987
字号
        case 035:
        case 036:
	case 037:
            if (ins->oprs[c - 034].type & (BITS16 | BITS32 | BITS64))
                length += (ins->oprs[c - 034].type & BITS16) ? 2 : 4;
            else
                length += (bits == 16) ? 2 : 4;
            break;
        case 040:
        case 041:
        case 042:
	case 043:
            length += 4;
            break;
        case 044:
        case 045:
        case 046:
	case 047:
            length += ((ins->oprs[c - 044].addr_size ?
                        ins->oprs[c - 044].addr_size : bits) >> 3);
            break;
        case 050:
        case 051:
        case 052:
	case 053:
            length++;
            break;
        case 054:
        case 055:
        case 056:
	case 057:
            length += 8; /* MOV reg64/imm */
            break;
        case 060:
        case 061:
        case 062:
	case 063:
            length += 2;
            break;
        case 064:
        case 065:
        case 066:
	case 067:
            if (ins->oprs[c - 064].type & (BITS16 | BITS32 | BITS64))
                length += (ins->oprs[c - 064].type & BITS16) ? 2 : 4;
            else
                length += (bits == 16) ? 2 : 4;
            break;
        case 070:
        case 071:
        case 072:
	case 073:
            length += 4;
            break;
        case 074:
        case 075:
        case 076:
        case 077:
            length += 2;
            break;
        case 0140:
        case 0141:
        case 0142:
	case 0143:
            length += is_sbyte(ins, c - 0140, 16) ? 1 : 2;
            break;
        case 0144:
        case 0145:
        case 0146:
        case 0147:
            codes += 2;
            length++;
            break;
        case 0150:
        case 0151:
        case 0152:
        case 0153:
            length += is_sbyte(ins, c - 0150, 32) ? 1 : 4;
            break;
        case 0154:
        case 0155:
        case 0156:
        case 0157:
            codes += 2;
            length++;
            break;
	case 0160:
	case 0161:
	case 0162:
	case 0163:
	    length++;
	    ins->rex |= REX_D;
	    ins->drexdst = regval(&ins->oprs[c & 3]);
	    break;
	case 0164:
	case 0165:
	case 0166:
	case 0167:
	    length++;
	    ins->rex |= REX_D|REX_OC;
	    ins->drexdst = regval(&ins->oprs[c & 3]);
	    break;
        case 0170:
            length++;
            break;
	case 0171:
	    break;
        case 0300:
        case 0301:
        case 0302:         
        case 0303:         
            break;
        case 0310:
	    if (bits == 64)
		return -1;
            length += (bits != 16) && !has_prefix(ins,P_A16);
            break;
        case 0311:
            length += (bits != 32) && !has_prefix(ins,P_A32);
            break;
        case 0312:
            break;     
        case 0313:
	    if (bits != 64 || has_prefix(ins,P_A16) || has_prefix(ins,P_A32))
		return -1;
            break;
        case 0320:
            length += (bits != 16);
            break;
        case 0321:
            length += (bits == 16);
            break;
        case 0322:
            break;
        case 0323:
            rex_mask &= ~REX_W;
            break;
        case 0324:
	    ins->rex |= REX_W;
            break;
        case 0330:
            codes++, length++;
            break;
        case 0331:
            break;
        case 0332:
        case 0333:
            length++;
            break;
	case 0334:
	    assert_no_prefix(ins, P_LOCK);
	    ins->rex |= REX_L;
	    break;
        case 0335:
	    break;
        case 0340:
        case 0341:
        case 0342:
            if (ins->oprs[0].segment != NO_SEG)
                errfunc(ERR_NONFATAL, "attempt to reserve non-constant"
                        " quantity of BSS space");
            else
                length += ins->oprs[0].offset << (c - 0340);
            break;
	case 0364:
	case 0365:
	    break;
        case 0366:
        case 0367:
	    length++;
	    break;
        case 0370:
        case 0371:
        case 0372:
            break;
        case 0373:
            length++;
            break;
        default:               /* can't do it by 'case' statements */
            if (c >= 0100 && c <= 0277) {       /* it's an EA */
                ea ea_data;
                int rfield;
		int32_t rflags;
                ea_data.rex = 0;           /* Ensure ea.REX is initially 0 */
                
		if (c <= 0177) {
		    /* pick rfield from operand b */
		    rflags = regflag(&ins->oprs[c & 7]);
		    rfield = regvals[ins->oprs[c & 7].basereg];
		} else {
		    rflags = 0;
		    rfield = c & 7;
		}

                if (!process_ea
                    (&ins->oprs[(c >> 3) & 7], &ea_data, bits,
                     rfield, rflags, ins->forw_ref)) {
                    errfunc(ERR_NONFATAL, "invalid effective address");
                    return -1;
                } else {
		    ins->rex |= ea_data.rex;
                    length += ea_data.size;
                }
            } else
                errfunc(ERR_PANIC, "internal instruction table corrupt"
                        ": instruction code 0x%02X given", c);
        }

    ins->rex &= rex_mask;
    
    if (ins->rex & REX_D) {
	if (ins->rex & REX_H) {
	    errfunc(ERR_NONFATAL, "cannot use high register in drex instruction");
	    return -1;
	}
	if (bits != 64 && ((ins->rex & (REX_W|REX_X|REX_B)) ||
			   ins->drexdst > 7)) {
	    errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
	    return -1;
	}
	length++;
    } else if (ins->rex & REX_REAL) {
	if (ins->rex & REX_H) {
	    errfunc(ERR_NONFATAL, "cannot use high register in rex instruction");
	    return -1;
	} else if (bits == 64 ||
		   ((ins->rex & REX_L) &&
		    !(ins->rex & (REX_P|REX_W|REX_X|REX_B)) &&
		    cpu >= IF_X86_64)) {
	    length++;
	} else {
	    errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
	    return -1;
	}
    }

    return length;
}

#define EMIT_REX()							\
    if (!(ins->rex & REX_D) && (ins->rex & REX_REAL) && (bits == 64)) {	\
	ins->rex = (ins->rex & REX_REAL)|REX_P;				\
	out(offset, segment, &ins->rex, OUT_RAWDATA+1, NO_SEG, NO_SEG); \
	ins->rex = 0;							\
	offset += 1; \
    }

static void gencode(int32_t segment, int32_t offset, int bits,
                    insn * ins, const char *codes, int32_t insn_end)
{
    static char condval[] = {   /* conditional opcodes */
        0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
        0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
        0x0, 0xA, 0xA, 0xB, 0x8, 0x4
    };
    uint8_t c;
    uint8_t bytes[4];
    int32_t size;
    int64_t data;
    
    while (*codes)
        switch (c = *codes++) {
        case 01:
        case 02:
        case 03:
	    EMIT_REX();
            out(offset, segment, codes, OUT_RAWDATA + c, NO_SEG, NO_SEG);
            codes += c;
            offset += c;
            break;

        case 04:
        case 06:
            switch (ins->oprs[0].basereg) {
            case R_CS:
                bytes[0] = 0x0E + (c == 0x04 ? 1 : 0);
                break;
            case R_DS:
                bytes[0] = 0x1E + (c == 0x04 ? 1 : 0);
                break;
            case R_ES:
                bytes[0] = 0x06 + (c == 0x04 ? 1 : 0);
                break;
            case R_SS:
                bytes[0] = 0x16 + (c == 0x04 ? 1 : 0);
                break;
            default:
                errfunc(ERR_PANIC,
                        "bizarre 8086 segment register received");
            }
            out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
            offset++;
            break;

        case 05:
        case 07:
            switch (ins->oprs[0].basereg) {
            case R_FS:
                bytes[0] = 0xA0 + (c == 0x05 ? 1 : 0);
                break;
            case R_GS:
                bytes[0] = 0xA8 + (c == 0x05 ? 1 : 0);
                break;
            default:
                errfunc(ERR_PANIC,
                        "bizarre 386 segment register received");
            }
            out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
            offset++;
            break;

        case 010:
        case 011:
        case 012:
	case 013:
	    EMIT_REX();
            bytes[0] = *codes++ + ((regval(&ins->oprs[c - 010])) & 7);
            out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
            offset += 1;
            break;

        case 014:
        case 015:
        case 016:
	case 017:
            if (ins->oprs[c - 014].offset < -128
                || ins->oprs[c - 014].offset > 127) {
                errfunc(ERR_WARNING, "signed byte value exceeds bounds");
            }

            if (ins->oprs[c - 014].segment != NO_SEG) {
                data = ins->oprs[c - 014].offset;
                out(offset, segment, &data, OUT_ADDRESS + 1,
                    ins->oprs[c - 014].segment, ins->oprs[c - 014].wrt);
            } else {
                bytes[0] = ins->oprs[c - 014].offset;
                out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
                    NO_SEG);
            }
            offset += 1;
            break;

        case 020:
        case 021:
        case 022:
	case 023:
            if (ins->oprs[c - 020].offset < -256
                || ins->oprs[c - 020].offset > 255) {
                errfunc(ERR_WARNING, "byte value exceeds bounds");
            }
            if (ins->oprs[c - 020].segment != NO_SEG) {
                data = ins->oprs[c - 020].offset;
                out(offset, segment, &data, OUT_ADDRESS + 1,
                    ins->oprs[c - 020].segment, ins->oprs[c - 020].wrt);
            } else {
                bytes[0] = ins->oprs[c - 020].offset;
                out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
                    NO_SEG);
            }
            offset += 1;
            break;

        case 024:
        case 025:
        case 026:
	case 027:
            if (ins->oprs[c - 024].offset < 0
                || ins->oprs[c - 024].offset > 255)
                errfunc(ERR_WARNING, "unsigned byte value exceeds bounds");
            if (ins->oprs[c - 024].segment != NO_SEG) {
                data = ins->oprs[c - 024].offset;
                out(offset, segment, &data, OUT_ADDRESS + 1,
                    ins->oprs[c - 024].segment, ins->oprs[c - 024].wrt);
            } else {
                bytes[0] = ins->oprs[c - 024].offset;
                out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
                    NO_SEG);
            }
            offset += 1;
            break;

        case 030:
        case 031:
        case 032:
	case 033:
            if (ins->oprs[c - 030].segment == NO_SEG &&
                ins->oprs[c - 030].wrt == NO_SEG &&
                (ins->oprs[c - 030].offset < -65536L ||
                 ins->oprs[c - 030].offset > 65535L)) {
                errfunc(ERR_WARNING, "word value exceeds bounds");
            }
            data = ins->oprs[c - 030].offset;
            out(offset, segment, &data, OUT_ADDRESS + 2,
                ins->oprs[c - 030].segment, ins->oprs[c - 030].wrt);
            offset += 2;
            break;

        case 034:

⌨️ 快捷键说明

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