📄 outbin.c
字号:
" power of two");
else { /* 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 + -