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

📄 outobj.c

📁 nasm的全套源代码,有些我做了些修改,以方便您更方便更容易调试成功,方便学习做编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
            struct ImpDef *imp;
            int err = FALSE;

            imp = *imptail = nasm_malloc(sizeof(struct ImpDef));
            imptail = &imp->next;
            imp->next = NULL;
            imp->extname = nasm_strdup(extname);
            imp->libname = nasm_strdup(libname);
            imp->impindex = readnum(impname, &err);
            if (!*impname || err)
                imp->impname = nasm_strdup(impname);
            else
                imp->impname = NULL;
        }

        return 1;
    }
    if (!strcmp(directive, "export")) {
        char *q, *extname, *intname, *v;
        struct ExpDef *export;
        int flags = 0;
        unsigned int ordinal = 0;

        if (pass == 2)
            return 1;           /* ignore in pass two */
        intname = q = value;
        while (*q && !isspace(*q))
            q++;
        if (isspace(*q)) {
            *q++ = '\0';
            while (*q && isspace(*q))
                q++;
        }

        extname = q;
        while (*q && !isspace(*q))
            q++;
        if (isspace(*q)) {
            *q++ = '\0';
            while (*q && isspace(*q))
                q++;
        }

        if (!*intname) {
            error(ERR_NONFATAL, "`export' directive requires export name");
            return 1;
        }
        if (!*extname) {
            extname = intname;
            intname = "";
        }
        while (*q) {
            v = q;
            while (*q && !isspace(*q))
                q++;
            if (isspace(*q)) {
                *q++ = '\0';
                while (*q && isspace(*q))
                    q++;
            }
            if (!nasm_stricmp(v, "resident"))
                flags |= EXPDEF_FLAG_RESIDENT;
            else if (!nasm_stricmp(v, "nodata"))
                flags |= EXPDEF_FLAG_NODATA;
            else if (!nasm_strnicmp(v, "parm=", 5)) {
                int err = FALSE;
                flags |= EXPDEF_MASK_PARMCNT & readnum(v + 5, &err);
                if (err) {
                    error(ERR_NONFATAL,
                          "value `%s' for `parm' is non-numeric", v + 5);
                    return 1;
                }
            } else {
                int err = FALSE;
                ordinal = readnum(v, &err);
                if (err) {
                    error(ERR_NONFATAL,
                          "unrecognised export qualifier `%s'", v);
                    return 1;
                }
                flags |= EXPDEF_FLAG_ORDINAL;
            }
        }

        export = *exptail = nasm_malloc(sizeof(struct ExpDef));
        exptail = &export->next;
        export->next = NULL;
        export->extname = nasm_strdup(extname);
        export->intname = nasm_strdup(intname);
        export->ordinal = ordinal;
        export->flags = flags;

        return 1;
    }
    return 0;
}

static long obj_segbase(long segment)
{
    struct Segment *seg;

    /*
     * Find the segment in our list.
     */
    for (seg = seghead; seg; seg = seg->next)
        if (seg->index == segment - 1)
            break;

    if (!seg) {
        /*
         * Might be an external with a default WRT.
         */
        long i = segment / 2;
        struct ExtBack *eb = ebhead;
        struct External *e;

        while (i > EXT_BLKSIZ) {
            if (eb)
                eb = eb->next;
            else
                break;
            i -= EXT_BLKSIZ;
        }
        if (eb) {
            e = eb->exts[i];
            if (e->defwrt_type == DEFWRT_NONE)
                return segment; /* fine */
            else if (e->defwrt_type == DEFWRT_SEGMENT)
                return e->defwrt_ptr.seg->index + 1;
            else if (e->defwrt_type == DEFWRT_GROUP)
                return e->defwrt_ptr.grp->index + 1;
            else
                return NO_SEG;  /* can't tell what it is */
        }

        return segment;         /* not one of ours - leave it alone */
    }

    if (seg->align >= SEG_ABS)
        return seg->align;      /* absolute segment */
    if (seg->grp)
        return seg->grp->index + 1;     /* grouped segment */

    return segment;             /* no special treatment */
}

static void obj_filename(char *inname, char *outname, efunc lerror)
{
    strcpy(obj_infile, inname);
    standard_extension(inname, outname, ".obj", lerror);
}

static void obj_write_file(int debuginfo)
{
    struct Segment *seg, *entry_seg_ptr = 0;
    struct FileName *fn;
    struct LineNumber *ln;
    struct Group *grp;
    struct Public *pub, *loc;
    struct External *ext;
    struct ImpDef *imp;
    struct ExpDef *export;
    static char boast[] = "The Netwide Assembler " NASM_VER;
    int lname_idx;
    ObjRecord *orp;

    /*
     * Write the THEADR module header.
     */
    orp = obj_new();
    orp->type = THEADR;
    obj_name(orp, obj_infile);
    obj_emit2(orp);

    /*
     * Write the NASM boast comment.
     */
    orp->type = COMENT;
    obj_rword(orp, 0);          /* comment type zero */
    obj_name(orp, boast);
    obj_emit2(orp);

    orp->type = COMENT;
    /*
     * Write the IMPDEF records, if any.
     */
    for (imp = imphead; imp; imp = imp->next) {
        obj_rword(orp, 0xA0);   /* comment class A0 */
        obj_byte(orp, 1);       /* subfunction 1: IMPDEF */
        if (imp->impname)
            obj_byte(orp, 0);   /* import by name */
        else
            obj_byte(orp, 1);   /* import by ordinal */
        obj_name(orp, imp->extname);
        obj_name(orp, imp->libname);
        if (imp->impname)
            obj_name(orp, imp->impname);
        else
            obj_word(orp, imp->impindex);
        obj_emit2(orp);
    }

    /*
     * Write the EXPDEF records, if any.
     */
    for (export = exphead; export; export = export->next) {
        obj_rword(orp, 0xA0);   /* comment class A0 */
        obj_byte(orp, 2);       /* subfunction 2: EXPDEF */
        obj_byte(orp, export->flags);
        obj_name(orp, export->extname);
        obj_name(orp, export->intname);
        if (export->flags & EXPDEF_FLAG_ORDINAL)
            obj_word(orp, export->ordinal);
        obj_emit2(orp);
    }

    /* we're using extended OMF if we put in debug info */
    if (debuginfo) {
        orp->type = COMENT;
        obj_byte(orp, 0x40);
        obj_byte(orp, dEXTENDED);
        obj_emit2(orp);
    }

    /*
     * Write the first LNAMES record, containing LNAME one, which
     * is null. Also initialise the LNAME counter.
     */
    orp->type = LNAMES;
    obj_byte(orp, 0);
    lname_idx = 1;
    /*
     * Write some LNAMES for the segment names
     */
    for (seg = seghead; seg; seg = seg->next) {
        orp = obj_name(orp, seg->name);
        if (seg->segclass)
            orp = obj_name(orp, seg->segclass);
        if (seg->overlay)
            orp = obj_name(orp, seg->overlay);
        obj_commit(orp);
    }
    /*
     * Write some LNAMES for the group names
     */
    for (grp = grphead; grp; grp = grp->next) {
        orp = obj_name(orp, grp->name);
        obj_commit(orp);
    }
    obj_emit(orp);

    /*
     * Write the SEGDEF records.
     */
    orp->type = SEGDEF;
    for (seg = seghead; seg; seg = seg->next) {
        int acbp;
        unsigned long seglen = seg->currentpos;

        acbp = (seg->combine << 2);     /* C field */

        if (seg->use32)
            acbp |= 0x01;       /* P bit is Use32 flag */
        else if (seglen == 0x10000L) {
            seglen = 0;         /* This special case may be needed for old linkers */
            acbp |= 0x02;       /* B bit */
        }

        /* A field */
        if (seg->align >= SEG_ABS)
            /* acbp |= 0x00 */ ;
        else if (seg->align >= 4096) {
            if (seg->align > 4096)
                error(ERR_NONFATAL, "segment `%s' requires more alignment"
                      " than OBJ format supports", seg->name);
            acbp |= 0xC0;       /* PharLap extension */
        } else if (seg->align >= 256) {
            acbp |= 0x80;
        } else if (seg->align >= 16) {
            acbp |= 0x60;
        } else if (seg->align >= 4) {
            acbp |= 0xA0;
        } else if (seg->align >= 2) {
            acbp |= 0x40;
        } else
            acbp |= 0x20;

        obj_byte(orp, acbp);
        if (seg->align & SEG_ABS) {
            obj_x(orp, seg->align - SEG_ABS);   /* Frame */
            obj_byte(orp, 0);   /* Offset */
        }
        obj_x(orp, seglen);
        obj_index(orp, ++lname_idx);
        obj_index(orp, seg->segclass ? ++lname_idx : 1);
        obj_index(orp, seg->overlay ? ++lname_idx : 1);
        obj_emit2(orp);
    }

    /*
     * Write the GRPDEF records.
     */
    orp->type = GRPDEF;
    for (grp = grphead; grp; grp = grp->next) {
        int i;

        if (grp->nindices != grp->nentries) {
            for (i = grp->nindices; i < grp->nentries; i++) {
                error(ERR_NONFATAL, "group `%s' contains undefined segment"
                      " `%s'", grp->name, grp->segs[i].name);
                nasm_free(grp->segs[i].name);
                grp->segs[i].name = NULL;
            }
        }
        obj_index(orp, ++lname_idx);
        for (i = 0; i < grp->nindices; i++) {
            obj_byte(orp, 0xFF);
            obj_index(orp, grp->segs[i].index);
        }
        obj_emit2(orp);
    }

    /*
     * Write the PUBDEF records: first the ones in the segments,
     * then the far-absolutes.
     */
    orp->type = PUBDEF;
    orp->ori = ori_pubdef;
    for (seg = seghead; seg; seg = seg->next) {
        orp->parm[0] = seg->grp ? seg->grp->obj_index : 0;
        orp->parm[1] = seg->obj_index;
        for (pub = seg->pubhead; pub; pub = pub->next) {
            orp = obj_name(orp, pub->name);
            orp = obj_x(orp, pub->offset);
            orp = obj_byte(orp, 0);     /* type index */
            obj_commit(orp);
        }
        obj_emit(orp);
    }
    orp->parm[0] = 0;
    orp->parm[1] = 0;
    for (pub = fpubhead; pub; pub = pub->next) {        /* pub-crawl :-) */
        if (orp->parm[2] != pub->segment) {
            obj_emit(orp);
            orp->parm[2] = pub->segment;
        }
        orp = obj_name(orp, pub->name);
        orp = obj_x(orp, pub->offset);
        orp = obj_byte(orp, 0); /* type index */
        obj_commit(orp);
    }
    obj_emit(orp);

    /*
     * Write the EXTDEF and COMDEF records, in order.
     */
    orp->ori = ori_null;
    for (ext = exthead; ext; ext = ext->next) {
        if (ext->commonsize == 0) {
            if (orp->type != EXTDEF) {
                obj_emit(orp);
                orp->type = EXTDEF;
            }
            orp = obj_name(orp, ext->name);
            orp = obj_index(orp, 0);
        } else {
            if (orp->type != COMDEF) {
                obj_emit(orp);
                orp->type = COMDEF;
            }
            orp = obj_name(orp, ext->name);
            orp = obj_index(orp, 0);
            if (ext->commonelem) {
                orp = obj_byte(orp, 0x61);      /* far communal */
                orp = obj_value(orp, (ext->commonsize / ext->commonelem));
                orp = obj_value(orp, ext->commonelem);
            } else {
                orp = obj_byte(orp, 0x62);      /* near communal */
                orp = obj_value(orp, ext->commonsize);
            }
        }
        obj_commit(orp);
    }
    obj_emit(orp);

    /*
     * Write a COMENT record stating that the linker's first pass
     * may stop processing at this point. Exception is if our
     * MODEND record specifies a start point, in which case,
     * according to some variants of the documentation, this COMENT
     * should be omitted. So we'll omit it just in case.
     * But, TASM puts it in all the time so if we are using
     * TASM debug stuff we are putting it in
     */
    if (debuginfo || obj_entry_seg == NO_SEG) {
        orp->type = COMENT;
        obj_byte(orp, 0x40);
        obj_byte(orp, dLINKPASS);
        obj_byte(orp, 1);
        obj_emit2(orp);
    }

    /*
     * 1) put out the compiler type
     * 2) Put out the type info.  The only type we are using is near label #19
     */
    if (debuginfo) {
        int i;
        struct Array *arrtmp = arrhead;
        orp->type = COMENT;
        obj_byte(orp, 0

⌨️ 快捷键说明

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