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

📄 assemble.c

📁 nasm的全套源代码,有些我做了些修改,以方便您更方便更容易调试成功,方便学习做编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
            }
            list->downlevel(LIST_INCBIN);
            if (instruction->times > 1) {
                /*
                 * Dummy call to list->output to give the offset to the
                 * listing module.
                 */
                list->output(offset, NULL, OUT_RAWDATA);
                list->uplevel(LIST_TIMES);
                list->downlevel(LIST_TIMES);
            }
            fclose(fp);
            return instruction->times * len;
        }
        return 0;               /* if we're here, there's an error */
    }

    size_prob = FALSE;
    temp = nasm_instructions[instruction->opcode];
    while (temp->opcode != -1) {
        int m = matches(temp, instruction);
        if (m == 99)
            m += jmp_match(segment, offset, bits, instruction, temp->code);

        if (m == 100) {         /* matches! */
            const char *codes = temp->code;
            long insn_size = calcsize(segment, offset, bits,
                                      instruction, codes);
            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 < instruction->nprefix; j++) {
                        unsigned char 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:
                            c = 0x2E;
                            break;
                        case R_DS:
                            c = 0x3E;
                            break;
                        case R_ES:
                            c = 0x26;
                            break;
                        case R_FS:
                            c = 0x64;
                            break;
                        case R_GS:
                            c = 0x65;
                            break;
                        case R_SS:
                            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 != 16)
                                c = 0x67;
                            break;
                        case P_A32:
                            if (bits != 32)
                                c = 0x67;
                            break;
                        case P_O16:
                            if (bits != 16)
                                c = 0x66;
                            break;
                        case P_O32:
                            if (bits != 32)
                                c = 0x66;
                            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, codes,
                            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);
                        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;
        }
        temp++;
    }

    if (temp->opcode == -1) {   /* didn't match any instruction */
        if (size_prob == 1)     /* would have matched, but for size */
            error(ERR_NONFATAL, "operation size not specified");
        else if (size_prob == 2)
            error(ERR_NONFATAL, "mismatch in operand sizes");
        else if (size_prob == 3)
            error(ERR_NONFATAL, "no instruction for this cpu level");
        else
            error(ERR_NONFATAL,
                  "invalid combination of opcode and operands");
    }
    return 0;
}

long insn_size(long segment, long offset, int bits, unsigned long cp,
               insn * instruction, efunc error)
{
    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) {
        extop *e;
        long 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;
        }

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

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

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

    if (instruction->opcode == I_INCBIN) {
        char fname[FILENAME_MAX];
        FILE *fp;
        long len;
        char *prefix = "", *combine;
        char **pPrevPath = NULL;

        len = FILENAME_MAX - 1;
        if (len > instruction->eops->stringlen)
            len = instruction->eops->stringlen;
        strncpy(fname, instruction->eops->stringval, len);
        fname[len] = '\0';

        while (1) {             /* added by alexfru: 'incbin' uses include paths */
            combine = nasm_malloc(strlen(prefix) + len + 1);
            strcpy(combine, prefix);
            strcat(combine, fname);

            if ((fp = fopen(combine, "rb")) != NULL) {
                nasm_free(combine);
                break;
            }

            nasm_free(combine);
            pPrevPath = pp_get_include_path_ptr(pPrevPath);
            if (pPrevPath == NULL)
                break;
            prefix = *pPrevPath;
        }

        if (fp == NULL)
            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 > instruction->eops->next->next->offset) {
                    len = instruction->eops->next->next->offset;
                }
            }
            return instruction->times * len;
        }
        return 0;               /* if we're here, there's an error */
    }

    temp = nasm_instructions[instruction->opcode];
    while (temp->opcode != -1) {
        int m = matches(temp, instruction);
        if (m == 99)
            m += jmp_match(segment, offset, bits, instruction, temp->code);

        if (m == 100) {
            /* we've matched an instruction. */
            long isize;
            const char *codes = temp->code;
            int j;

            isize = calcsize(segment, offset, bits, instruction, codes);
            if (isize < 0)
                return -1;
            for (j = 0; j < instruction->nprefix; j++) {
                if ((instruction->prefixes[j] != P_A16 &&
                     instruction->prefixes[j] != P_O16 && bits == 16) ||
                    (instruction->prefixes[j] != P_A32 &&
                     instruction->prefixes[j] != P_O32 && bits == 32)) {
                    isize++;
                }
            }
            return isize * instruction->times;
        }
        temp++;
    }
    return -1;                  /* didn't match any instruction */
}

/* check that  opn[op]  is a signed byte of size 16 or 32,
					and return the signed value*/
static int is_sbyte(insn * ins, int op, int size)
{
    signed long v;
    int ret;

    ret = !(ins->forw_ref && ins->oprs[op].opflags) &&  /* dead in the water on forward reference or External */
        optimizing >= 0 &&
        !(ins->oprs[op].type & STRICT) &&
        ins->oprs[op].wrt == NO_SEG && ins->oprs[op].segment == NO_SEG;

    v = ins->oprs[op].offset;
    if (size == 16)
        v = (signed short)v;    /* sign extend if 16 bits */

    return ret && v >= -128L && v <= 127L;
}

static long calcsize(long segment, long offset, int bits,
                     insn * ins, const char *codes)
{
    long length = 0;
    unsigned char c;

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

    while (*codes)
        switch (c = *codes++) {
        case 01:
        case 02:
        case 03:
            codes += c, length += c;
            break;
        case 04:
        case 05:
        case 06:
        case 07:
            length++;
            break;
        case 010:
        case 011:
        case 012:
            codes++, length++;
            break;
        case 017:
            length++;
            break;
        case 014:
        case 015:
        case 016:
            length++;
            break;
        case 020:
        case 021:
        case 022:
            length++;
            break;
        case 024:
        case 025:
        case 026:
            length++;
            break;
        case 030:
        case 031:
        case 032:
            length += 2;
            break;
        case 034:
        case 035:
        case 036:
            if (ins->oprs[c - 034].type & (BITS16 | BITS32))
                length += (ins->oprs[c - 034].type & BITS16) ? 2 : 4;
            else
                length += (bits == 16) ? 2 : 4;
            break;
        case 037:
            length += 2;
            break;
        case 040:
        case 041:
        case 042:
            length += 4;
            break;
        case 044:

⌨️ 快捷键说明

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