📄 outobj.c
字号:
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 + -