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

📄 outobj.c

📁 一个免费的汇编语言编译器的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
			  seg->align);
		    seg->align = 1;
		    break;
		}
	    } else if (!nasm_strnicmp(p, "absolute=", 9)) {
		seg->align = SEG_ABS + readnum(p+9, &rn_error);
		if (rn_error)
		    error (ERR_NONFATAL, "argument to `absolute' segment"
			   " attribute should be numeric");
	    }
	}

        /* We need to know whenever we have at least one 32-bit segment */
        obj_use32 |= seg->use32;

	obj_seg_needs_update = seg;
	if (seg->align >= SEG_ABS)
	    deflabel (name, NO_SEG, seg->align - SEG_ABS,
		      NULL, FALSE, FALSE, &of_obj, error);
	else
	    deflabel (name, seg->index+1, 0L,
		      NULL, FALSE, FALSE, &of_obj, error);
	obj_seg_needs_update = NULL;

	/*
	 * See if this segment is defined in any groups.
	 */
	for (grp = grphead; grp; grp = grp->next) {
	    for (i = grp->nindices; i < grp->nentries; i++) {
		if (!strcmp(grp->segs[i].name, seg->name)) {
		    nasm_free (grp->segs[i].name);
		    grp->segs[i] = grp->segs[grp->nindices];
		    grp->segs[grp->nindices++].index = seg->obj_index;
		    if (seg->grp)
			error(ERR_WARNING, "segment `%s' is already part of"
			      " a group: first one takes precedence",
			      seg->name);
		    else
			seg->grp = grp;
		}
	    }
	}

	/*
	 * Walk through the list of externals with unresolved
	 * default-WRT clauses, and resolve any that point at this
	 * segment.
	 */
	extp = &dws;
	while (*extp) {
	    if ((*extp)->defwrt_type == DEFWRT_STRING &&
		!strcmp((*extp)->defwrt_ptr.string, seg->name)) {
		nasm_free((*extp)->defwrt_ptr.string);
		(*extp)->defwrt_type = DEFWRT_SEGMENT;
		(*extp)->defwrt_ptr.seg = seg;
		*extp = (*extp)->next_dws;
	    } else
		extp = &(*extp)->next_dws;
	}

	if (seg->use32)
	    *bits = 32;
	else
	    *bits = 16;
	current_seg = seg;
	return seg->index;
    }
}

static int obj_directive (char *directive, char *value, int pass) 
{
    if (!strcmp(directive, "group")) {
	char *p, *q, *v;
	if (pass == 1) {
	    struct Group *grp;
	    struct Segment *seg;
	    struct External **extp;
	    int obj_idx;

	    q = value;
	    while (*q == '.')
		q++;		       /* hack, but a documented one */
	    v = q;
	    while (*q && !isspace(*q))
		q++;
	    if (isspace(*q)) {
		*q++ = '\0';
		while (*q && isspace(*q))
		    q++;
	    }
	    /*
	     * Here we used to sanity-check the group directive to
	     * ensure nobody tried to declare a group containing no
	     * segments. However, OS/2 does this as standard
	     * practice, so the sanity check has been removed.
	     *
	     * if (!*q) {
	     *     error(ERR_NONFATAL,"GROUP directive contains no segments");
	     *     return 1;
	     * }
	     */

	    obj_idx = 1;
	    for (grp = grphead; grp; grp = grp->next) {
		obj_idx++;
		if (!strcmp(grp->name, v)) {
		    error(ERR_NONFATAL, "group `%s' defined twice", v);
		    return 1;
		}
	    }

	    *grptail = grp = nasm_malloc(sizeof(*grp));
	    grp->next = NULL;
	    grptail = &grp->next;
	    grp->index = seg_alloc();
	    grp->obj_index = obj_idx;
	    grp->nindices = grp->nentries = 0;
	    grp->name = NULL;

	    obj_grp_needs_update = grp;
	    deflabel (v, grp->index+1, 0L,
		      NULL, FALSE, FALSE, &of_obj, error);
	    obj_grp_needs_update = NULL;

	    while (*q) {
		p = q;
		while (*q && !isspace(*q))
		    q++;
		if (isspace(*q)) {
		    *q++ = '\0';
		    while (*q && isspace(*q))
			q++;
		}
		/*
		 * Now p contains a segment name. Find it.
		 */
		for (seg = seghead; seg; seg = seg->next)
		    if (!strcmp(seg->name, p))
			break;
		if (seg) {
		    /*
		     * We have a segment index. Shift a name entry
		     * to the end of the array to make room.
		     */
		    grp->segs[grp->nentries++] = grp->segs[grp->nindices];
		    grp->segs[grp->nindices++].index = seg->obj_index;
		    if (seg->grp)
			error(ERR_WARNING, "segment `%s' is already part of"
			      " a group: first one takes precedence",
			      seg->name);
		    else
			seg->grp = grp;
		} else {
		    /*
		     * We have an as-yet undefined segment.
		     * Remember its name, for later.
		     */
		    grp->segs[grp->nentries++].name = nasm_strdup(p);
		}
	    }

	    /*
	     * Walk through the list of externals with unresolved
	     * default-WRT clauses, and resolve any that point at
	     * this group.
	     */
	    extp = &dws;
	    while (*extp) {
		if ((*extp)->defwrt_type == DEFWRT_STRING &&
		    !strcmp((*extp)->defwrt_ptr.string, grp->name)) {
		    nasm_free((*extp)->defwrt_ptr.string);
		    (*extp)->defwrt_type = DEFWRT_GROUP;
		    (*extp)->defwrt_ptr.grp = grp;
		    *extp = (*extp)->next_dws;
	    } else
		    extp = &(*extp)->next_dws;
	    }
	}
	return 1;
    }
    if (!strcmp(directive, "uppercase")) {
	obj_uppercase = TRUE;
	return 1;
    }
    if (!strcmp(directive, "import")) {
	char *q, *extname, *libname, *impname;

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

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

	impname = q;

	if (!*extname || !*libname)
	    error(ERR_NONFATAL, "`import' directive requires symbol name"
		  " and library name");
	else {
	    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 */

⌨️ 快捷键说明

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