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

📄 assemble.c

📁 汇编编译器的最新版本的源码.买了自己动手写操作系统这本书的人一定要下
💻 C
📖 第 1 页 / 共 5 页
字号:
                list->downlevel(LIST_TIMES);
            }
            fclose(fp);
            return instruction->times * len;
        }
        return 0;               /* if we're here, there's an error */
    }

    /* Check to see if we need an address-size prefix */
    add_asp(instruction, bits);

    size_prob = false;

    for (temp = nasm_instructions[instruction->opcode]; temp->opcode != -1; temp++){
        int m = matches(temp, instruction, bits);
	if (m == 100 ||
	    (m == 99 && jmp_match(segment, offset, bits,
				  instruction, temp->code))) {
	    /* Matches! */
            int64_t insn_size = calcsize(segment, offset, bits,
                                      instruction, temp->code);
            itimes = instruction->times;
            if (insn_size < 0)  /* shouldn't be, on pass two */
                error(ERR_PANIC, "errors made it through from pass one");
            else
                while (itimes--) {
                    for (j = 0; j < MAXPREFIX; j++) {
                        uint8_t c = 0;
                        switch (instruction->prefixes[j]) {
                        case P_LOCK:
                            c = 0xF0;
                            break;
                        case P_REPNE:
                        case P_REPNZ:
                            c = 0xF2;
                            break;
                        case P_REPE:
                        case P_REPZ:
                        case P_REP:
                            c = 0xF3;
                            break;
                        case R_CS:
                            if (bits == 64) {
                                error(ERR_WARNING | ERR_PASS2,
                                      "cs segment base generated, but will be ignored in 64-bit mode");
                            }
                            c = 0x2E;
                            break;
                        case R_DS:
                            if (bits == 64) {
                                error(ERR_WARNING | ERR_PASS2,
                                      "ds segment base generated, but will be ignored in 64-bit mode");
                            }
                            c = 0x3E;
                            break;
                        case R_ES:
                           if (bits == 64) {
                                error(ERR_WARNING | ERR_PASS2,
                                      "es segment base generated, but will be ignored in 64-bit mode");
                           }
                            c = 0x26;
                            break;
                        case R_FS:
                            c = 0x64;
                            break;
                        case R_GS:
                            c = 0x65;
                            break;
                        case R_SS:
                            if (bits == 64) {
                                error(ERR_WARNING | ERR_PASS2,
                                      "ss segment base generated, but will be ignored in 64-bit mode");
                            }
                            c = 0x36;
                            break;
                        case R_SEGR6:
                        case R_SEGR7:
                            error(ERR_NONFATAL,
                                  "segr6 and segr7 cannot be used as prefixes");
                            break;
                        case P_A16:
                            if (bits == 64) {
                                error(ERR_NONFATAL,
				      "16-bit addressing is not supported "
				      "in 64-bit mode");
                            } else if (bits != 16)
                                c = 0x67;
                            break;
                        case P_A32:
                            if (bits != 32)
                                c = 0x67;
                            break;
			case P_A64:
			    if (bits != 64) {
				error(ERR_NONFATAL,
				      "64-bit addressing is only supported "
				      "in 64-bit mode");
			    }
			    break;
			case P_ASP:
			    c = 0x67;
			    break;
                        case P_O16:
                            if (bits != 16)
                                c = 0x66;
                            break;
                        case P_O32:
                            if (bits == 16)
                                c = 0x66;
                            break;
			case P_O64:
			    /* REX.W */
			    break;
			case P_OSP:
			    c = 0x66;
			    break;
			case P_none:
			    break;
                        default:
                            error(ERR_PANIC, "invalid instruction prefix");
                        }
                        if (c != 0) {
                            out(offset, segment, &c, OUT_RAWDATA, 1,
                                NO_SEG, NO_SEG);
                            offset++;
                        }
                    }
                    insn_end = offset + insn_size;
                    gencode(segment, offset, bits, instruction,
			    temp, insn_end);
                    offset += insn_size;
                    if (itimes > 0 && itimes == instruction->times - 1) {
                        /*
                         * Dummy call to list->output to give the offset to the
                         * listing module.
                         */
                        list->output(offset, NULL, OUT_RAWDATA, 0);
                        list->uplevel(LIST_TIMES);
                    }
                }
            if (instruction->times > 1)
                list->downlevel(LIST_TIMES);
            return offset - start;
        } else if (m > 0 && m > size_prob) {
            size_prob = m;
        }
    }

    if (temp->opcode == -1) {   /* didn't match any instruction */
	switch (size_prob) {
	case 1:
	    error(ERR_NONFATAL, "operation size not specified");
	    break;
	case 2:
            error(ERR_NONFATAL, "mismatch in operand sizes");
	    break;
	case 3:
            error(ERR_NONFATAL, "no instruction for this cpu level");
	    break;
	case 4:
            error(ERR_NONFATAL, "instruction not supported in 64-bit mode");
	    break;
	default:
            error(ERR_NONFATAL,
                  "invalid combination of opcode and operands");
	    break;
	}
    }
    return 0;
}

int64_t insn_size(int32_t segment, int64_t offset, int bits, uint32_t cp,
               insn * instruction, efunc error)
{
    const struct itemplate *temp;

    errfunc = error;            /* to pass to other functions */
    cpu = cp;

    if (instruction->opcode == -1)
        return 0;

    if (instruction->opcode == I_DB || instruction->opcode == I_DW ||
        instruction->opcode == I_DD || instruction->opcode == I_DQ ||
	instruction->opcode == I_DT || instruction->opcode == I_DO ||
	instruction->opcode == I_DY) {
        extop *e;
        int32_t isize, osize, wsize = 0;   /* placate gcc */

        isize = 0;
        switch (instruction->opcode) {
        case I_DB:
            wsize = 1;
            break;
        case I_DW:
            wsize = 2;
            break;
        case I_DD:
            wsize = 4;
            break;
        case I_DQ:
            wsize = 8;
            break;
        case I_DT:
            wsize = 10;
            break;
	case I_DO:
	    wsize = 16;
	    break;
	case I_DY:
	    wsize = 32;
	    break;
	default:
	    break;
        }

        for (e = instruction->eops; e; e = e->next) {
            int32_t align;

            osize = 0;
            if (e->type == EOT_DB_NUMBER)
                osize = 1;
            else if (e->type == EOT_DB_STRING ||
		     e->type == EOT_DB_STRING_FREE)
                osize = e->stringlen;

            align = (-osize) % wsize;
            if (align < 0)
                align += wsize;
            isize += osize + align;
        }
        return isize * instruction->times;
    }

    if (instruction->opcode == I_INCBIN) {
	const char *fname = instruction->eops->stringval;
        FILE *fp;
        size_t len;

	fp = fopen(fname, "rb");
	if (!fp)
            error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
                  fname);
        else if (fseek(fp, 0L, SEEK_END) < 0)
            error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
                  fname);
        else {
            len = ftell(fp);
            fclose(fp);
            if (instruction->eops->next) {
                len -= instruction->eops->next->offset;
                if (instruction->eops->next->next &&
                    len > (size_t)instruction->eops->next->next->offset) {
                    len = (size_t)instruction->eops->next->next->offset;
                }
            }
            return instruction->times * len;
        }
        return 0;               /* if we're here, there's an error */
    }

    /* Check to see if we need an address-size prefix */
    add_asp(instruction, bits);

    for (temp = nasm_instructions[instruction->opcode]; temp->opcode != -1; temp++) {
        int m = matches(temp, instruction, bits);
        if (m == 100 ||
	    (m == 99 && jmp_match(segment, offset, bits,
				  instruction, temp->code))) {
            /* we've matched an instruction. */
            int64_t isize;
            const uint8_t *codes = temp->code;
            int j;

            isize = calcsize(segment, offset, bits, instruction, codes);
            if (isize < 0)
                return -1;
            for (j = 0; j < MAXPREFIX; j++) {
		switch (instruction->prefixes[j]) {
		case P_A16:
		    if (bits != 16)
			isize++;
		    break;
		case P_A32:
		    if (bits != 32)
			isize++;
		    break;
		case P_O16:
		    if (bits != 16)
			isize++;
		    break;
		case P_O32:
		    if (bits == 16)
			isize++;
		    break;
		case P_A64:
		case P_O64:
		case P_none:
		    break;
		default:
		    isize++;
		    break;
		}
            }
            return isize * instruction->times;
        }
    }
    return -1;                  /* didn't match any instruction */
}

static bool possible_sbyte(operand *o)
{
    return o->wrt == NO_SEG && o->segment == NO_SEG &&
	!(o->opflags & OPFLAG_FORWARD) &&
	optimizing >= 0 && !(o->type & STRICT);
}

/* check that opn[op]  is a signed byte of size 16 or 32 */
static bool is_sbyte16(operand *o)
{
    int16_t v;

    if (!possible_sbyte(o))
	return false;

    v = o->offset;
    return v >= -128 && v <= 127;
}

static bool is_sbyte32(operand *o)
{
    int32_t v;

    if (!possible_sbyte(o))
	return false;

    v = o->offset;
    return v >= -128 && v <= 127;
}

/* Common construct */
#define case4(x) case (x): case (x)+1: case (x)+2: case (x)+3

static int64_t calcsize(int32_t segment, int64_t offset, int bits,
			insn * ins, const uint8_t *codes)
{
    int64_t length = 0;
    uint8_t c;
    int rex_mask = ~0;
    struct operand *opx;

    ins->rex = 0;               /* Ensure REX is reset */

    if (ins->prefixes[PPS_OSIZE] == P_O64)
	ins->rex |= REX_W;

    (void)segment;              /* Don't warn that this parameter is unused */
    (void)offset;               /* Don't warn that this parameter is unused */

    while (*codes) {
	c = *codes++;
	opx = &ins->oprs[c & 3];
        switch (c) {
        case 01:
        case 02:
        case 03:
            codes += c, length += c;
            break;

	case4(010):
	    ins->rex |=
		op_rexflags(opx, REX_B|REX_H|REX_P|REX_W);
            codes++, length++;
            break;

	case4(014):
	case4(020):
	case4(024):
            length++;
            break;

	case4(030):
            length += 2;
            break;

	case4(034):
            if (opx->type & (BITS16 | BITS32 | BITS64))
                length += (opx->type & BITS16) ? 2 : 4;
            else
                length += (bits == 16) ? 2 : 4;
            break;

	case4(040):
            length += 4;
            break;

	case4(044):
            length += ins->addr_size >> 3;
            break;

	case4(050):
            length++;
            break;

	case4(054):
            length += 8; /* MOV reg64/imm */
            break;

	case4(060):
            length += 2;
            break;

	case4(064):
            if (opx->type & (BITS16 | BITS32 | BITS64))
                length += (opx->type & BITS16) ? 2 : 4;
            else
                length += (bits == 16) ? 2 : 4;
            break;

	case4(070):
            length += 4;
            break;

	case4(074):
            length += 2;
            break;

	case4(0140):
            length += is_sbyte16(opx) ? 1 : 2;
            break;

	case4(0144):
            codes++;
            length++;
            break;

	case4(0150):

⌨️ 快捷键说明

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