📄 outbin.c
字号:
{ /* Alignment is already satisfied if the previous
* align value is greater. */
if ((sec->flags & VALIGN_DEFINED) && (value < sec->valign))
value = sec->valign;
/* Don't allow a conflicting valign value. */
if ((sec->flags & VSTART_DEFINED) && (sec->vstart & (value - 1)))
error(ERR_NONFATAL, "`valign' value conflicts "
"with `vstart' address");
else
{ sec->valign = value; sec->flags |= VALIGN_DEFINED;
}
}
continue;
/* Handle start attribute. */
case ATTRIB_START:
if (sec->flags & FOLLOWS_DEFINED)
error(ERR_NONFATAL, "cannot combine `start' and `follows'"
" section attributes");
else if (value < 0)
error(ERR_NONFATAL, "attempt to specify a negative"
" section start address");
else if ((sec->flags & START_DEFINED) && (value != sec->start))
error(ERR_NONFATAL, "section start address redefined");
else
{ sec->start = value; sec->flags |= START_DEFINED;
if (sec->flags & ALIGN_DEFINED)
{ if (sec->start & (sec->align - 1))
error (ERR_NONFATAL, "`start' address conflicts"
" with section alignment");
sec->flags ^= ALIGN_DEFINED;
}
}
continue;
/* Handle vstart attribute. */
case ATTRIB_VSTART:
if (sec->flags & VFOLLOWS_DEFINED)
error(ERR_NONFATAL, "cannot combine `vstart' and `vfollows'"
" section attributes");
else if ((sec->flags & VSTART_DEFINED) && (value != sec->vstart))
error(ERR_NONFATAL, "section virtual start address"
" (vstart) redefined");
else
{ sec->vstart = value; sec->flags |= VSTART_DEFINED;
if (sec->flags & VALIGN_DEFINED)
{ if (sec->vstart & (sec->valign - 1))
error (ERR_NONFATAL, "`vstart' address conflicts"
" with `valign' value");
sec->flags ^= VALIGN_DEFINED;
}
}
continue;
/* Handle follows attribute. */
case ATTRIB_FOLLOWS:
p = astring; astring += strcspn(astring, " \t");
if (astring == p)
error(ERR_NONFATAL, "expecting section name for `follows'"
" attribute");
else
{ *(astring++) = '\0';
if (sec->flags & START_DEFINED)
error(ERR_NONFATAL, "cannot combine `start' and `follows'"
" section attributes");
sec->follows = nasm_strdup(p);
sec->flags |= FOLLOWS_DEFINED;
}
continue;
/* Handle vfollows attribute. */
case ATTRIB_VFOLLOWS:
if (sec->flags & VSTART_DEFINED)
error(ERR_NONFATAL, "cannot combine `vstart' and `vfollows'"
" section attributes");
else
{ p = astring; astring += strcspn(astring, " \t");
if (astring == p)
error(ERR_NONFATAL, "expecting section name for `vfollows'"
" attribute");
else
{ *(astring++) = '\0';
sec->vfollows = nasm_strdup(p);
sec->flags |= VFOLLOWS_DEFINED;
}
}
continue;
}
}
}
static void bin_define_section_labels()
{ static int labels_defined = 0;
struct Section * sec;
char * label_name;
size_t base_len;
if (labels_defined) return;
for (sec = sections; sec; sec = sec->next)
{ base_len = strlen(sec->name) + 8;
label_name = nasm_malloc(base_len + 8);
strcpy(label_name, "section.");
strcpy(label_name + 8, sec->name);
/* section.<name>.start */
strcpy(label_name + base_len, ".start");
define_label(label_name, sec->start_index, 0L,
NULL, 0, 0, bin_get_ofmt(), error);
/* section.<name>.vstart */
strcpy(label_name + base_len, ".vstart");
define_label(label_name, sec->vstart_index, 0L,
NULL, 0, 0, bin_get_ofmt(), error);
nasm_free(label_name);
}
labels_defined = 1;
}
static long bin_secname(char *name, int pass, int *bits)
{ char *p;
struct Section *sec;
/* bin_secname is called with *name = NULL at the start of each
* pass. Use this opportunity to establish the default section
* (default is BITS-16 ".text" segment).
*/
if (!name)
{ /* Reset ORG and section attributes at the start of each pass. */
origin_defined = 0;
for (sec = sections; sec; sec = sec->next)
sec->flags &= ~(START_DEFINED | VSTART_DEFINED |
ALIGN_DEFINED | VALIGN_DEFINED);
/* Define section start and vstart labels. */
if (format_mode && (pass != 1)) bin_define_section_labels();
/* Establish the default (.text) section. */
*bits = 16;
sec = find_section_by_name(".text");
sec->flags |= TYPE_DEFINED | TYPE_PROGBITS;
current_section = sec->vstart_index;
return current_section;
}
/* Attempt to find the requested section. If it does not
* exist, create it. */
p = name;
while (*p && !isspace(*p)) p++;
if (*p) *p++ = '\0';
sec = find_section_by_name(name);
if(!sec)
{ sec = create_section(name);
if (!strcmp(name, ".data"))
sec->flags |= TYPE_DEFINED | TYPE_PROGBITS;
else if (!strcmp(name, ".bss"))
{ sec->flags |= TYPE_DEFINED | TYPE_NOBITS;
sec->ifollows = NULL;
}
else if (!format_mode)
{ error(ERR_NONFATAL, "section name must be "
".text, .data, or .bss");
return current_section;
}
}
/* Handle attribute assignments. */
if (pass != 1) bin_assign_attributes(sec, p);
#ifndef ABIN_SMART_ADAPT
/* The following line disables smart adaptation of
* PROGBITS/NOBITS section types (it forces sections to
* default to PROGBITS). */
if ((pass != 1) && !(sec->flags & TYPE_DEFINED))
sec->flags |= TYPE_DEFINED | TYPE_PROGBITS;
#endif
/* Set the current section and return. */
current_section = sec->vstart_index;
return current_section;
}
static int bin_directive (char *directive, char *args, int pass)
{
/* Handle ORG directive */
if (!nasm_stricmp(directive, "org"))
{ struct tokenval tokval;
unsigned long value;
expr *e;
stdscan_reset();
stdscan_bufptr = args;
tokval.t_type = TOKEN_INVALID;
e = evaluate(stdscan, NULL, &tokval, NULL, 1, error, NULL);
if (e)
{ if (!is_really_simple(e))
error(ERR_NONFATAL, "org value must be a critical"
" expression");
else
{ value = reloc_value(e);
/* Check for ORG redefinition. */
if (origin_defined && (value != origin))
error(ERR_NONFATAL, "program origin redefined");
else
{ origin = value;
origin_defined = 1;
}
}
}
else
error(ERR_NONFATAL, "No or invalid offset specified"
" in ORG directive.");
return 1;
}
/* The 'map' directive allows the user to generate section
* and symbol information to stdout, stderr, or to a file. */
else if (format_mode && !nasm_stricmp(directive, "map"))
{ char *p;
if (pass != 1) return 1;
args += strspn(args, " \t");
while (*args)
{ p = args; args += strcspn(args, " \t");
if (*args != '\0') *(args++) = '\0';
if (!nasm_stricmp(p, "all"))
map_control |= MAP_ORIGIN | MAP_SUMMARY | MAP_SECTIONS | MAP_SYMBOLS;
else if (!nasm_stricmp(p, "brief"))
map_control |= MAP_ORIGIN | MAP_SUMMARY;
else if (!nasm_stricmp(p, "sections"))
map_control |= MAP_ORIGIN | MAP_SUMMARY | MAP_SECTIONS;
else if (!nasm_stricmp(p, "segments"))
map_control |= MAP_ORIGIN | MAP_SUMMARY | MAP_SECTIONS;
else if (!nasm_stricmp(p, "symbols"))
map_control |= MAP_SYMBOLS;
else if (!rf)
{ if (!nasm_stricmp(p, "stdout"))
rf = stdout;
else if (!nasm_stricmp(p, "stderr"))
rf = stderr;
else
{ /* Must be a filename. */
rf = fopen(p, "wt");
if (!rf)
{ error(ERR_WARNING, "unable to open map file `%s'", p);
map_control = 0;
return 1;
}
}
}
else error(ERR_WARNING, "map file already specified");
}
if (map_control == 0) map_control |= MAP_ORIGIN | MAP_SUMMARY;
if (!rf) rf = stdout;
return 1;
}
return 0;
}
static void bin_filename (char *inname, char *outname, efunc error)
{ standard_extension(inname, outname, "", error);
infile = inname; outfile = outname;
}
static long bin_segbase (long segment)
{ return segment;
}
static int bin_set_info(enum geninfo type, char **val)
{ return 0;
}
static void bin_init (FILE *afp, efunc errfunc, ldfunc ldef, evalfunc eval)
{ fp = afp;
error = errfunc;
(void) eval; /* Don't warn that this parameter is unused. */
(void) ldef; /* Placate optimizers. */
relocs = NULL;
reloctail = &relocs;
origin_defined = 0;
no_seg_labels = NULL;
nsl_tail = &no_seg_labels;
format_mode = 1; /* Extended bin format
* (set this to zero for old bin format). */
/* Create default section (.text). */
sections = last_section = nasm_malloc(sizeof(struct Section));
last_section->next = NULL;
last_section->name = nasm_strdup(".text");
last_section->contents = saa_init(1L);
last_section->follows = last_section->vfollows = 0;
last_section->ifollows = NULL;
last_section->length = 0;
last_section->flags = TYPE_DEFINED | TYPE_PROGBITS;
last_section->labels = NULL;
last_section->labels_end = &(last_section->labels);
last_section->start_index = seg_alloc();
last_section->vstart_index = current_section = seg_alloc();
}
struct ofmt of_bin = {
"flat-form binary files (e.g. DOS .COM, .SYS)",
"bin",
NULL,
null_debug_arr,
&null_debug_form,
bin_stdmac,
bin_init,
bin_set_info,
bin_out,
bin_deflabel,
bin_secname,
bin_segbase,
bin_directive,
bin_filename,
bin_cleanup
};
/* This is needed for bin_define_section_labels() */
struct ofmt *bin_get_ofmt()
{ return &of_bin;
}
#endif /* #ifdef OF_BIN */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -