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

📄 outbin.c

📁 一个免费的汇编语言编译器的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:

static void bin_out (long segto, const void *data, unsigned long type,
           long segment, long wrt)
{  unsigned char *p, mydata[4];
   struct Section *s;
   long realbytes;

   if (wrt != NO_SEG)
   {  wrt = NO_SEG;        /* continue to do _something_ */
      error (ERR_NONFATAL,
         "WRT not supported by binary output format");
   }

   /* Handle absolute-assembly (structure definitions). */
   if (segto == NO_SEG)
   {  if ((type & OUT_TYPMASK) != OUT_RESERVE)
         error (ERR_NONFATAL, "attempt to assemble code in"
            " [ABSOLUTE] space");
      return;
   }

   /* Find the segment we are targeting. */
   s = find_section_by_index(segto);
   if (!s)
      error (ERR_PANIC, "code directed to nonexistent segment?");

   /* "Smart" section-type adaptation code. */
   if (!(s->flags & TYPE_DEFINED))
   {  if ((type & OUT_TYPMASK) == OUT_RESERVE)
         s->flags |= TYPE_DEFINED | TYPE_NOBITS;
      else s->flags |= TYPE_DEFINED | TYPE_PROGBITS;
   }

   if ((s->flags & TYPE_NOBITS) && ((type & OUT_TYPMASK) != OUT_RESERVE))
      error(ERR_WARNING, "attempt to initialise memory in a"
         " nobits section: ignored");

   if ((type & OUT_TYPMASK) == OUT_ADDRESS)
   {  if (segment != NO_SEG && !find_section_by_index(segment))
      {  if (segment % 2)
            error(ERR_NONFATAL, "binary output format does not support"
               " segment base references");
         else
            error(ERR_NONFATAL, "binary output format does not support"
               " external references");
         segment = NO_SEG;
      }
      if (s->flags & TYPE_PROGBITS)
      {  if (segment != NO_SEG)
            add_reloc(s, type & OUT_SIZMASK, segment, -1L);
         p = mydata;
         if ((type & OUT_SIZMASK) == 4)
            WRITELONG(p, *(long *)data);
         else
            WRITESHORT(p, *(long *)data);
         saa_wbytes(s->contents, mydata, type & OUT_SIZMASK);
      }
      s->length += type & OUT_SIZMASK;
   }
   else if ((type & OUT_TYPMASK) == OUT_RAWDATA)
   {  type &= OUT_SIZMASK;
      if (s->flags & TYPE_PROGBITS) saa_wbytes(s->contents, data, type);
      s->length += type;
   }
   else if ((type & OUT_TYPMASK) == OUT_RESERVE)
   {  type &= OUT_SIZMASK;
      if (s->flags & TYPE_PROGBITS)
      {  error(ERR_WARNING, "uninitialised space declared in"
            " %s section: zeroing", s->name);
         saa_wbytes (s->contents, NULL, type);
      }
      s->length += type;
   }
   else if ((type & OUT_TYPMASK) == OUT_REL2ADR ||
      (type & OUT_TYPMASK) == OUT_REL4ADR)
   {  realbytes = ((type & OUT_TYPMASK) == OUT_REL4ADR ? 4 : 2);
      if (segment != NO_SEG && !find_section_by_index(segment))
      {  if (segment % 2)
            error(ERR_NONFATAL, "binary output format does not support"
               " segment base references");
         else
            error(ERR_NONFATAL, "binary output format does not support"
               " external references");
         segment = NO_SEG;
      }
      if (s->flags & TYPE_PROGBITS)
      {  add_reloc(s, realbytes, segment, segto);
         p = mydata;
         if (realbytes == 4)
            WRITELONG(p, *(long*)data - realbytes - s->length);
         else
            WRITESHORT(p, *(long*)data - realbytes - s->length);
         saa_wbytes(s->contents, mydata, realbytes);
      }
      s->length += realbytes;
   }
}

static void bin_deflabel (char *name, long segment, long offset,
           int is_global, char *special)
{  (void) segment;   /* Don't warn that this parameter is unused */
   (void) offset;    /* Don't warn that this parameter is unused */

   if (special)
      error (ERR_NONFATAL, "binary format does not support any"
         " special symbol types");
   else if (name[0] == '.' && name[1] == '.' && name[2] != '@')
      error (ERR_NONFATAL, "unrecognised special symbol `%s'", name);
   else if (is_global == 2)
      error (ERR_NONFATAL, "binary output format does not support common"
         " variables");
   else
   {  struct Section *s;
      struct bin_label ***ltp;

      /* Remember label definition so we can look it up later when
       * creating the map file. */
      s = find_section_by_index(segment);
      if (s) ltp = &(s->labels_end);
      else ltp = &nsl_tail;
      (**ltp) = nasm_malloc(sizeof(struct bin_label));
      (**ltp)->name = name;
      (**ltp)->next = NULL;
      *ltp = &((**ltp)->next);
   }

}

/* These constants and the following function are used
 * by bin_secname() to parse attribute assignments. */

enum { ATTRIB_START, ATTRIB_ALIGN, ATTRIB_FOLLOWS,
       ATTRIB_VSTART, ATTRIB_VALIGN, ATTRIB_VFOLLOWS,
       ATTRIB_NOBITS, ATTRIB_PROGBITS };

static int bin_read_attribute(char **line, int *attribute, unsigned long *value)
{  expr *e;
   int attrib_name_size;
   struct tokenval tokval;
   char *exp;

   /* Skip whitespace. */
   while (**line && isspace(**line)) (*line)++;
   if (!**line) return 0;

   /* Figure out what attribute we're reading. */
   if (!nasm_strnicmp(*line,"align=", 6))
   {  *attribute = ATTRIB_ALIGN;
      attrib_name_size = 6;
   }
   else if (format_mode)
   {  if (!nasm_strnicmp(*line,"start=", 6))
      {  *attribute = ATTRIB_START;
         attrib_name_size = 6;
      }
      else if (!nasm_strnicmp(*line,"follows=", 8))
      {  *attribute = ATTRIB_FOLLOWS;
         *line += 8; return 1;
      }
      else if (!nasm_strnicmp(*line,"vstart=", 7))
      {  *attribute = ATTRIB_VSTART;
         attrib_name_size = 7;
      }
      else if (!nasm_strnicmp(*line,"valign=", 7))
      {  *attribute = ATTRIB_VALIGN;
         attrib_name_size = 7;
      }
      else if (!nasm_strnicmp(*line,"vfollows=", 9))
      {  *attribute = ATTRIB_VFOLLOWS;
         *line += 9; return 1;
      }
      else if (!nasm_strnicmp(*line,"nobits", 6) &&
         (isspace((*line)[6]) || ((*line)[6] == '\0')))
      {  *attribute = ATTRIB_NOBITS;
         *line += 6; return 1;
      }
      else if (!nasm_strnicmp(*line,"progbits", 8) &&
         (isspace((*line)[8]) || ((*line)[8] == '\0')))
      {  *attribute = ATTRIB_PROGBITS;
         *line += 8; return 1;
      }
      else return 0;
   }
   else return 0;

   /* Find the end of the expression. */
   if ((*line)[attrib_name_size] != '(')
   {
      /* Single term (no parenthesis). */
      exp = *line += attrib_name_size;
      while (**line && !isspace(**line)) (*line)++;
      if (**line)
      {  **line = '\0'; (*line)++;
      }
   }
   else
   {  char c;
      int pcount = 1;

      /* Full expression (delimited by parenthesis) */
      exp = *line += attrib_name_size + 1;
      while (1)
      {  (*line) += strcspn(*line, "()'\"");
         if (**line == '(')
         {  ++(*line); ++pcount;
         }
         if (**line == ')')
         {  ++(*line); --pcount;
            if (!pcount) break;
         }
         if ((**line == '"') || (**line == '\''))
         {  c = **line;
            while (**line)
            {  ++(*line);
               if (**line == c) break;
            }
            if (!**line)
            {  error(ERR_NONFATAL, "invalid syntax in `section' directive");
               return -1;
            }
            ++(*line);
         }
         if (!**line)
         {  error(ERR_NONFATAL, "expecting `)'");
            return -1;
         }
      }
      *(*line - 1) = '\0';  /* Terminate the expression. */
   }

   /* Check for no value given. */
   if (!*exp)
   {  error(ERR_WARNING, "No value given to attribute in"
         " `section' directive");
      return -1;
   }

   /* Read and evaluate the expression. */
   stdscan_reset();
   stdscan_bufptr = exp;
   tokval.t_type = TOKEN_INVALID;
   e = evaluate(stdscan, NULL, &tokval, NULL, 1, error, NULL);
   if (e)
   {  if (!is_really_simple(e))
      {  error(ERR_NONFATAL, "section attribute value must be"
            " a critical expression");
         return -1;
      }
   }
   else
   {  error(ERR_NONFATAL, "Invalid attribute value"
         " specified in `section' directive.");
      return -1;
   }
   *value = (unsigned long) reloc_value(e);
   return 1;
}

static void bin_assign_attributes(struct Section *sec, char *astring)
{  int attribute, check;
   unsigned long value;
   char *p;

   while (1)
   {  /* Get the next attribute. */
      check = bin_read_attribute(&astring, &attribute, &value);
      /* Skip bad attribute. */
      if (check == -1) continue;
      /* Unknown section attribute, so skip it and warn the user. */
      if (!check)
      {  if (!*astring) break;  /* End of line. */
         else
         {  p = astring; while (*astring && !isspace(*astring)) astring++;
            if (*astring)
            {  *astring = '\0'; astring++;
            }
            error(ERR_WARNING, "ignoring unknown section attribute:"
               " \"%s\"", p);
         }
      continue;
      }

      switch (attribute)
      {  /* Handle nobits attribute. */
         case ATTRIB_NOBITS:
            if ((sec->flags & TYPE_DEFINED) && (sec->flags & TYPE_PROGBITS))
               error(ERR_NONFATAL, "attempt to change section type"
                  " from progbits to nobits");
            else sec->flags |= TYPE_DEFINED | TYPE_NOBITS;
            continue;

         /* Handle progbits attribute. */
         case ATTRIB_PROGBITS:
            if ((sec->flags & TYPE_DEFINED) && (sec->flags & TYPE_NOBITS))
               error(ERR_NONFATAL, "attempt to change section type"
                  " from nobits to progbits");
            else sec->flags |= TYPE_DEFINED | TYPE_PROGBITS;
            continue;

         /* Handle align attribute. */
         case ATTRIB_ALIGN:
            if (!format_mode && (!strcmp(sec->name, ".text")))
               error(ERR_NONFATAL, "cannot specify an alignment"
                  " to the .text section");
            else
            {  if (!value || ((value - 1) & value))
                  error(ERR_NONFATAL, "argument to `align' is not a"
                  " power of two");
               else
               {  /* Alignment is already satisfied if the previous
                   * align value is greater. */
                  if ((sec->flags & ALIGN_DEFINED) && (value < sec->align))
                     value = sec->align;

                  /* Don't allow a conflicting align value. */
                  if ((sec->flags & START_DEFINED) && (sec->start & (value - 1)))
                     error(ERR_NONFATAL, "`align' value conflicts "
                     "with section start address");
                  else
                  {  sec->align = value; sec->flags |= ALIGN_DEFINED;
                  }
               }
            }
            continue;

         /* Handle valign attribute. */
         case ATTRIB_VALIGN:
            if (!value || ((value - 1) & value))
               error(ERR_NONFATAL, "argument to `valign' is not a"
                  " power of two");
            else

⌨️ 快捷键说明

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