NASM 0.98.15
authorH. Peter Anvin <hpa@zytor.com>
Tue, 30 Apr 2002 21:02:47 +0000 (21:02 +0000)
committerH. Peter Anvin <hpa@zytor.com>
Tue, 30 Apr 2002 21:02:47 +0000 (21:02 +0000)
README09b.txt [new file with mode: 0644]
assemble.c
macros.c
misc/exasm.zip
nasm.h
preproc.c
rdoff/ldrdf.c
test/multisection.asm [new file with mode: 0644]

diff --git a/README09b.txt b/README09b.txt
new file mode 100644 (file)
index 0000000..affb91a
--- /dev/null
@@ -0,0 +1,82 @@
+
+                    README
+          NASM, the Netwide Assembler
+
+
+ Changes from 0.98.07 release to 98.09b as of 28-Oct-2001
+ ========================================================
+
+1. More closely compatible with 0.98 when -O0 is implied 
+or specified.  Not strictly identical, since backward 
+branches in range of short offsets are recognized, and signed
+byte values with no explicit size specification will be
+assembled as a single byte.
+
+2. More forgiving with the PUSH instruction.  0.98 requires
+a size to be specified always.  0.98.09b will imply the size
+from the current BITS setting (16 or 32).
+
+3. Changed definition of the optimization flag:
+
+       -O0     strict two-pass assembly, JMP and Jcc are
+               handled more like 0.98, except that back-
+               ward JMPs are short, if possible.
+
+       -O1     strict two-pass assembly, but forward
+               branches are assembled with code guaranteed
+               to reach; may produce larger code than
+               -O0, but will produce successful assembly
+               more often if branch offset sizes are not
+               specified.
+
+       -O2     multi-pass optimization, minimize branch
+               offsets; also will minimize signed immed-
+               iate bytes, overriding size specification.
+
+       -O3     like -O2, but more passes taken, if needed
+
+
+ Changes from 0.98 release to 98.03 as of 27-Jul-2000
+ ====================================================
+
+1. Added signed byte optimizations for the 0x81/0x83 class
+of instructions: ADC, ADD, AND, CMP, OR, SBB, SUB, XOR:
+when used as 'ADD reg16,imm' or 'ADD reg32,imm.'  Also
+optimization of signed byte form of 'PUSH imm' and 'IMUL
+reg,imm'/'IMUL reg,reg,imm.'  No size specification is needed.
+
+2. Added multi-pass JMP and Jcc offset optimization.  Offsets
+on forward references will preferentially use the short form,
+without the need to code a specific size (short or near) for
+the branch.  Added instructions for 'Jcc label' to use the
+form 'Jnotcc $+3/JMP label', in cases where a short offset
+is out of bounds.  If compiling for a 386 or higher CPU, then
+the 386 form of Jcc will be used instead.
+
+This feature is controlled by a new command-line switch: "O",
+(upper case letter O).  "-O0" reverts the assembler to no
+extra optimization passes, "-O1" allows up to 5 extra passes,
+and "-O2"(default), allows up to 10 extra optimization passes.
+
+3. Added a new directive:  'cpu XXX', where XXX is any of: 
+8086, 186, 286, 386, 486, 586, pentium, 686, PPro, P2, P3 or
+Katmai.  All are case insensitive.  All instructions will
+be selected only if they apply to the selected cpu or lower.
+Corrected a couple of bugs in cpu-dependence in 'insns.dat'.
+
+4. Added to 'standard.mac', the "use16" and "use32" forms of
+the "bits 16/32" directive. This is nothing new, just conforms
+to a lot of other assemblers. (minor)
+
+5. Changed label allocation from 320/32 (10000 labels @ 200K+) 
+to 32/37 (1000 labels); makes running under DOS much easier.
+Since additional label space is allocated dynamically, this
+should have no effect on large programs with lots of labels.
+The 37 is a prime, believed to be better for hashing. (minor)
+
+6. Integrated patchfile 0.98-0.98.01.  I call this version
+0.98.03, for historical reasons:  0.98.02 was trashed.
+
+--John Coffman <johninsd@san.rr.com>               27-Jul-2000
+
+(end)
\ No newline at end of file
index b9271a4..f560112 100644 (file)
@@ -102,8 +102,8 @@ static int  chsize (operand *, int);
 static void out (long offset, long segto, void *data, unsigned long type,
                 long segment, long wrt) 
 {
-    static long lineno;
-    static char *lnfname;
+    long lineno;
+    char *lnfname = NULL;
 
     if ((type & OUT_TYPMASK) == OUT_ADDRESS) {
        if (segment != NO_SEG || wrt != NO_SEG) {
@@ -143,7 +143,7 @@ static void out (long offset, long segto, void *data, unsigned long type,
     if (src_get(&lineno,&lnfname))
     {
        outfmt->current_dfmt->linenum(lnfname,lineno,segto);
-       if (lnfname) nasm_free(lnfname);
+        if (lnfname) nasm_free(lnfname);
     }
 
     outfmt->output (segto, data, type, segment, wrt);
index ed70a75..38a7e0f 100644 (file)
--- a/macros.c
+++ b/macros.c
@@ -1,6 +1,12 @@
 /* This file auto-generated from standard.mac by macros.pl - don't edit it */
 
 static char *stdmac[] = {
+    "%idefine IDEAL",
+    "%idefine JUMPS",
+    "%idefine P386",
+    "%idefine P486",
+    "%idefine P586",
+    "%idefine END",
     "%define __NASM_MAJOR__ 0",
     "%define __NASM_MINOR__ 98",
     "%define __FILE__",
@@ -57,6 +63,12 @@ static char *stdmac[] = {
     "%imacro bits 1+.nolist",
     "[bits %1]",
     "%endmacro",
+    "%imacro use16 0.nolist",
+    "[bits 16]",
+    "%endmacro",
+    "%imacro use32 0.nolist",
+    "[bits 32]",
+    "%endmacro",
     "%imacro global 1-*.nolist",
     "%rep %0",
     "[global %1]",
@@ -69,5 +81,9 @@ static char *stdmac[] = {
     "%rotate 1",
     "%endrep",
     "%endmacro",
+    "%imacro cpu 1+.nolist",
+    "[cpu %1]",
+    "%endmacro",
     NULL
 };
+#define TASM_MACRO_COUNT 6
index b4e9e58..e813018 100644 (file)
Binary files a/misc/exasm.zip and b/misc/exasm.zip differ
diff --git a/nasm.h b/nasm.h
index c0dc0e5..c9a8f06 100644 (file)
--- a/nasm.h
+++ b/nasm.h
@@ -13,7 +13,7 @@
 
 #define NASM_MAJOR_VER 0
 #define NASM_MINOR_VER 98
-#define NASM_VER "0.98.14"
+#define NASM_VER "0.98.15"
 
 #ifndef NULL
 #define NULL 0
index 0277a45..4ec3826 100644 (file)
--- a/preproc.c
+++ b/preproc.c
@@ -924,7 +924,7 @@ delete_Blocks(void)
                        nasm_free(b->chunk);
                a = b;
                b = b->next;
-               if (a != &blocks)
+                if (a != &blocks)
                        nasm_free(a);
        }
 }      
index 3d9d749..d9aac2f 100644 (file)
-/* ldrdf.c      RDOFF Object File linker/loader main program
- *
- * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
- * Julian Hall. All rights reserved. The software is
- * redistributable under the licence given in the file "Licence"
- * distributed in the NASM archive.
- */
-
-/*
- * TODO: actually get this new version working!
- * - finish off write_output()       - appears to be done
- * - implement library searching     - appears to be done
- *   - maybe we only want to do one pass, for performance reasons?
- *     this makes things a little harder, but unix 'ld' copes...
- * - implement command line options  - appears to be done
- * - improve symbol table implementation  - done, thanks to Graeme Defty
- * - keep a cache of symbol names in each library module so
- *   we don't have to constantly recheck the file
- * - general performance improvements
- *
- * BUGS & LIMITATIONS: this program doesn't support multiple code, data
- * or bss segments, therefore for 16 bit programs whose code, data or BSS
- * segment exceeds 64K in size, it will not work. This program probably
- * wont work if compiled by a 16 bit compiler. Try DJGPP if you're running
- * under DOS. '#define STINGY_MEMORY' may help a little.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "multboot.h"
-#include "rdoff.h"
-#include "symtab.h"
-#include "collectn.h"
-#include "rdlib.h"
-#include "segtab.h"
-
-#define LDRDF_VERSION "1.02"
-
-#define RDF_MAXSEGS 64
-/* #define STINGY_MEMORY */
-
-/* =======================================================================
- * Types & macros that are private to this program
- */
-
-struct segment_infonode {
-    int                dest_seg;       /* output segment to be placed into, -1 to 
-                                  skip linking this segment */
-    long       reloc;          /* segment's relocation factor */
-};
-
-
-struct modulenode {
-    rdffile    f;              /* the RDOFF file structure */
-    struct segment_infonode seginfo[RDF_MAXSEGS]; /* what are we doing
-                                                    with each segment? */
-    void       * header;
-    char       * name;
-    struct modulenode * next;
-    long       bss_reloc;
-};
-
-#include "ldsegs.h"
-
-#define newstr(str) strcpy(malloc(strlen(str) + 1),str)
-#define newstrcat(s1,s2) strcat(strcpy(malloc(strlen(s1)+strlen(s2)+1),s1),s2)
-
-/* ==========================================================================
- * Function prototypes of private utility functions
- */
-
-void processmodule(const char * filename, struct modulenode * mod);
-int allocnewseg(int16 type,int16 reserved);
-int findsegment(int16 type,int16 reserved);
-void symtab_add(const char * symbol, int segment, long offset);
-int symtab_get(const char * symbol, int * segment, long * offset);
-
-/* =========================================================================
- * Global data structures.
- */
-
-/* a linked list of modules that will be included in the output */
-struct modulenode      * modules = NULL;
-struct modulenode      * lastmodule = NULL;
-
-/* a linked list of libraries to be searched for unresolved imported symbols */
-struct librarynode     * libraries = NULL;
-struct librarynode     * lastlib = NULL;
-
-/* the symbol table */
-void                   * symtab = NULL;
-
-/* objects search path */
-char                   * objpath = NULL;
-
-/* libraries search path */
-char                   * libpath = NULL;
-
-/* error file */
-static FILE            * error_file;
-
-#ifdef _MULTBOOT_H
-
-/* loading address for multiboot header */
-unsigned               MBHloadAddr;
-
-/*
- * Tiny code that moves RDF loader to its working memory region:
- *     mov     esi,SOURCE_ADDR         ; BE xx xx xx xx
- *     mov     edi,DEST_ADDR           ; BF xx xx xx xx
- *     mov     esp,edi                 ; 89 FC
- *     push    edi                     ; 57
- *     mov     ecx,RDFLDR_LENGTH/4     ; B9 xx xx xx xx
- *     cld                             ; FC
- *     rep     movsd                   ; F3 A5
- *     ret                             ; C3
- */
-
-#define        RDFLDR_LENGTH   4096            /* Loader will be moved to unused */
-#define        RDFLDR_DESTLOC  0xBF000         /* video page                     */
-unsigned char RDFloaderMover[]={
-       0xBE, 0, 0, 0, 0, 0xBF, 0, 0xF0, 0xB, 0,
-       0x89, 0xFC, 0x57,
-       0xB9, 0, 4, 0, 0,
-       0xFC, 0xF3, 0xA5, 0xC3
-};
-               
-#endif
-
-/* the header of the output file, built up stage by stage */
-rdf_headerbuf          * newheader = NULL;
-
-/* The current state of segment allocation, including information about
- * which output segment numbers have been allocated, and their types and
- * amount of data which has already been allocated inside them. 
- */
-struct SegmentHeaderRec        outputseg[RDF_MAXSEGS];
-int                    nsegs = 0;
-long                   bss_length;
-
-/* global options which affect how the program behaves */
-struct ldrdfoptions {
-    int                verbose;
-    int                align;
-    int                warnUnresolved;
-    int                errorUnresolved;
-    int                strip;
-    int         respfile;
-    int         stderr_redir;
-    int         objpath;
-    int         libpath;
-    int                addMBheader;
-} options;
-
-int errorcount = 0;    /* determines main program exit status */
-
-/* =========================================================================
- * Utility functions
- */
-
-
-/*
- * initsegments()
- *
- * sets up segments 0, 1, and 2, the initial code data and bss segments
- */
-
-void initsegments()
-{
-    nsegs = 3;
-    outputseg[0].type = 1;
-    outputseg[0].number = 0;
-    outputseg[0].reserved = 0;
-    outputseg[0].length = 0;
-    outputseg[1].type = 2;
-    outputseg[1].number = 1;
-    outputseg[1].reserved = 0;
-    outputseg[1].length = 0;
-    outputseg[2].type = 0xFFFF;        /* reserved segment type */
-    outputseg[2].number = 2;
-    outputseg[2].reserved = 0;
-    outputseg[2].length = 0;
-    bss_length = 0;
-}
-
-/*
- * loadmodule
- *
- * Determine the characteristics of a module, and decide what to do with
- * each segment it contains (including determining destination segments and
- * relocation factors for segments that        are kept).
- */
-
-void loadmodule(const char * filename)
-{
-    if (options.verbose)
-       printf("loading `%s'\n", filename);
-
-    /* allocate a new module entry on the end of the modules list */
-    if (!modules)
-    {
-       modules = malloc (sizeof(*modules));
-       lastmodule = modules;
-    }
-    else
-    {
-       lastmodule->next = malloc (sizeof(*modules));
-       lastmodule = lastmodule->next;
-    }
-
-    if ( ! lastmodule)
-    {
-       fprintf(stderr, "ldrdf: out of memory\n");
-       exit(1);
-    }
-
-    /* open the file using 'rdfopen', which returns nonzero on error */
-
-    if (rdfopen(&lastmodule->f, filename) != 0)
-    {
-       rdfperror("ldrdf", filename);
-       exit(1);
-    }
-
-    /* 
-     * store information about the module, and determine what segments
-     * it contains, and what we should do with them (determine relocation
-     * factor if we decide to keep them)
-     */
-
-    lastmodule->header = NULL;
-    lastmodule->name = strdup(filename);
-    lastmodule->next = NULL;
-
-    processmodule(filename, lastmodule);
-}
-       
-/*
- * processmodule()
- *
- * step through each segment, determine what exactly we're doing with
- * it, and if we intend to keep it, determine (a) which segment to
- * put it in and (b) whereabouts in that segment it will end up.
- * (b) is fairly easy, cos we're now keeping track of how big each segment
- * in our output file is...
- */
-
-void processmodule(const char * filename, struct modulenode * mod)
-{
-    struct segconfig sconf;
-    int                seg, outseg;
-    void       * header;
-    rdfheaderrec * hr;
-    long       bssamount = 0;
-
-    for (seg = 0; seg < mod->f.nsegs; seg++)
-    {
-       /*
-        * get the segment configuration for this type from the segment
-        * table. getsegconfig() is a macro, defined in ldsegs.h.
-        */
-       getsegconfig(sconf, mod->f.seg[seg].type);
-
-       if (options.verbose > 1) {
-           printf ("%s %04x [%04x:%10s] ", filename, mod->f.seg[seg].number, 
-                   mod->f.seg[seg].type, sconf.typedesc);
-       }
-       /*
-        * sconf->dowhat tells us what to do with a segment of this type.
-        */
-       switch (sconf.dowhat) {
-       case SEG_IGNORE:
-           /*
-            * Set destination segment to -1, to indicate that this segment
-            * should be ignored for the purpose of output, ie it is left
-            * out of the linked executable.
-            */
-           mod->seginfo[seg].dest_seg = -1;
-           if (options.verbose > 1) printf("IGNORED\n");
-           break;
-
-       case SEG_NEWSEG:
-           /*
-            * The configuration tells us to create a new segment for
-            * each occurrence of this segment type.
-            */
-           outseg = allocnewseg(sconf.mergetype,
-                                mod->f.seg[seg].reserved);
-           mod->seginfo[seg].dest_seg = outseg;
-           mod->seginfo[seg].reloc = 0;
-           outputseg[outseg].length = mod->f.seg[seg].length;
-           if (options.verbose > 1) 
-               printf ("=> %04x:%08lx (+%04lx)\n", outseg,
-                       mod->seginfo[seg].reloc,
-                       mod->f.seg[seg].length);
-           break;
-
-       case SEG_MERGE:
-           /*
-            * The configuration tells us to merge the segment with
-            * a previously existing segment of type 'sconf.mergetype',
-            * if one exists. Otherwise a new segment is created.
-            * This is handled transparently by 'findsegment()'.
-            */
-           outseg = findsegment(sconf.mergetype,
-                                mod->f.seg[seg].reserved);
-           mod->seginfo[seg].dest_seg = outseg;
-
-           /*
-            * We need to add alignment to these segments.
-            */
-           if (outputseg[outseg].length % options.align != 0)
-               outputseg[outseg].length += 
-                   options.align - (outputseg[outseg].length % options.align);
-           
-           mod->seginfo[seg].reloc = outputseg[outseg].length;
-           outputseg[outseg].length  += mod->f.seg[seg].length;
-
-           if (options.verbose > 1) 
-               printf ("=> %04x:%08lx (+%04lx)\n", outseg,
-                       mod->seginfo[seg].reloc,
-                       mod->f.seg[seg].length);
-       }
-
-    }
-
-    /*
-     * extract symbols from the header, and dump them into the
-     * symbol table
-     */
-    header = malloc(mod->f.header_len);
-    if (!header) {
-       fprintf(stderr, "ldrdf: not enough memory\n");
-       exit(1);
-    }
-    if (rdfloadseg(&mod->f, RDOFF_HEADER, header)) {
-       rdfperror("ldrdf", filename);
-       exit(1);
-    }
-
-    while ((hr = rdfgetheaderrec (&mod->f)))
-    {
-       switch(hr->type) {
-       case 2: /* imported symbol - define with seg = -1 */
-       case 7:
-           symtab_add(hr->i.label, -1, 0);
-           break;
-
-       case 3: /* exported symbol */
-           {
-            int destseg;
-            long destreloc;
-
-            if (hr->e.segment == 2)
-             {
-               destreloc = bss_length;
-               if (destreloc % options.align != 0)
-                  destreloc +=  options.align - (destreloc % options.align);
-               destseg = 2;
-             }
-            else
-             {
-               if ((destseg = mod->seginfo[(int)hr->e.segment].dest_seg) == -1)
-                  continue;
-               destreloc = mod->seginfo[(int)hr->e.segment].reloc;
-             }
-           symtab_add(hr->e.label, destseg, destreloc + hr->e.offset);
-           break;
-           }
-
-       case 5: /* BSS reservation */
-           /*
-            * first, amalgamate all BSS reservations in this module
-            * into one, because we allow this in the output format.
-            */
-           bssamount += hr->b.amount;
-           break;
-       }
-    }
-
-    if (bssamount != 0)
-    {
-       /*
-        * handle the BSS segment - first pad the existing bss length
-        * to the correct alignment, then store the length in bss_reloc
-        * for this module. Then add this module's BSS length onto
-        * bss_length.
-        */
-       if (bss_length % options.align != 0)
-           bss_length +=  options.align - (bss_length % options.align);
-    
-       mod->bss_reloc = bss_length;
-       if (options.verbose > 1) {
-           printf ("%s 0002 [            BSS] => 0002:%08lx (+%04lx)\n",
-                   filename, bss_length, bssamount);
-       }
-       bss_length += bssamount;
-    }
-
-#ifdef STINGY_MEMORY
-    /*
-     * we free the header buffer here, to save memory later.
-     * this isn't efficient, but probably halves the memory usage
-     * of this program...
-     */
-    mod->f.header_loc = NULL;
-    free(header);
-
-#endif
-
-}
-
-
-/*
- * Look in list for module by its name.
- */
-int lookformodule(const char *name)
- {
-  struct modulenode *curr=modules;
-
-  while(curr) {
-   if (!strcmp(name,curr->name)) return 1;
-   curr = curr->next;
-  }
-  return 0;
- }
-
-
-/*
- * allocnewseg()
- * findsegment()
- *
- * These functions manipulate the array of output segments, and are used
- * by processmodule(). allocnewseg() allocates a segment in the array,
- * initialising it to be empty. findsegment() first scans the array for
- * a segment of the type requested, and if one isn't found allocates a
- * new one.
- */
-int allocnewseg(int16 type,int16 reserved)
-{
-    outputseg[nsegs].type = type;
-    outputseg[nsegs].number = nsegs;
-    outputseg[nsegs].reserved = reserved;
-    outputseg[nsegs].length = 0;
-    outputseg[nsegs].offset = 0;
-    outputseg[nsegs].data = NULL;
-
-    return nsegs++;
-}
-
-int findsegment(int16 type,int16 reserved)
-{
-    int i;
-
-    for (i = 0; i < nsegs; i++)
-       if (outputseg[i].type == type) return i;
-
-    return allocnewseg(type,reserved);
-}
-
-/*
- * symtab_add()
- *
- * inserts a symbol into the global symbol table, which associates symbol
- * names either with addresses, or a marker that the symbol hasn't been
- * resolved yet, or possibly that the symbol has been defined as
- * contained in a dynamic [load time/run time] linked library.
- *
- * segment = -1 => not yet defined
- * segment = -2 => defined as dll symbol
- *
- * If the symbol is already defined, and the new segment >= 0, then
- * if the original segment was < 0 the symbol is redefined, otherwise
- * a duplicate symbol warning is issued. If new segment == -1, this
- * routine won't change a previously existing symbol. It will change
- * to segment = -2 only if the segment was previously < 0.
- */
-
-void symtab_add(const char * symbol, int segment, long offset)
-{
-    symtabEnt * ste;
-
-    ste = symtabFind(symtab, symbol);
-    if (ste)
-    {
-       if (ste->segment >= 0) {
-           /*
-            * symbol previously defined
-            */
-           if (segment < 0) return;
-           fprintf (error_file, "warning: `%s' redefined\n", symbol);
-           return;
-       }
-
-       /*
-        * somebody wanted the symbol, and put an undefined symbol
-        * marker into the table
-        */
-       if (segment == -1) return;
-       /*
-        * we have more information now - update the symbol's entry
-        */
-       ste->segment = segment;
-       ste->offset = offset;
-       ste->flags = 0;
-       return;
-    }
-    /*
-     * this is the first declaration of this symbol
-     */
-    ste = malloc(sizeof(symtabEnt));
-    if (!ste) {
-       fprintf(stderr, "ldrdf: out of memory\n");
-       exit(1);
-    }
-    ste->name = strdup(symbol);
-    ste->segment = segment;
-    ste->offset = offset;
-    ste->flags = 0;
-    symtabInsert(symtab, ste);
-}
-
-/*
- * symtab_get()
- *
- * Retrieves the values associated with a symbol. Undefined symbols
- * are assumed to have -1:0 associated. Returns 1 if the symbol was
- * successfully located.
- */
-
-int symtab_get(const char * symbol, int * segment, long * offset)
-{
-    symtabEnt * ste = symtabFind(symtab, symbol);
-    if (!ste) {
-       *segment = -1;
-       *offset = 0;
-       return 0;
-    }
-    else
-    {
-       *segment = ste->segment;
-       *offset = ste->offset;
-       return 1;
-    }
-}
-
-/*
- * add_library()
- *
- * checks that a library can be opened and is in the correct format,
- * then adds it to the linked list of libraries.
- */
-
-void add_library(const char * name)
-{
-    if (rdl_verify(name)) {
-       rdl_perror("ldrdf", name);
-       errorcount++;
-       return;
-    }
-    if (! libraries)
-    {
-       lastlib = libraries = malloc(sizeof(*libraries));
-       if (! libraries) {
-           fprintf(stderr, "ldrdf: out of memory\n");
-           exit(1);
-       }
-    }
-    else
-    {
-       lastlib->next = malloc(sizeof(*libraries));
-       if (!lastlib->next) {
-           fprintf(stderr, "ldrdf: out of memory\n");
-           exit(1);
-       }
-       lastlib = lastlib->next;
-    }
-    lastlib->next = NULL;
-    if (rdl_open(lastlib, name)) {
-       rdl_perror("ldrdf", name);
-       errorcount++;
-       return;
-    }
-}
-
-/*
- * search_libraries()
- *
- * scans through the list of libraries, attempting to match symbols
- * defined in library modules against symbols that are referenced but
- * not defined (segment = -1 in the symbol table)
- *
- * returns 1 if any extra library modules are included, indicating that
- * another pass through the library list should be made (possibly).
- */
-
-int search_libraries()
-{
-    struct librarynode * cur;
-    rdffile f;
-    int     i;
-    void    * header;
-    int            segment;
-    long    offset;
-    int            doneanything = 0, pass = 1, keepfile;
-    rdfheaderrec * hr;
-
-    cur = libraries;
-
-    while (cur)
-    {
-       if (options.verbose > 2)
-           printf("scanning library `%s', pass %d...\n", cur->name, pass);
-       
-       for (i = 0; rdl_openmodule(cur, i, &f) == 0; i++)
-       {
-           if (pass == 2 && lookformodule(f.name)) continue;
-
-           if (options.verbose > 3)
-               printf("  looking in module `%s'\n", f.name);
-
-           header = malloc(f.header_len);
-           if (!header) {
-               fprintf(stderr, "ldrdf: not enough memory\n");
-               exit(1);
-           }
-           if (rdfloadseg(&f, RDOFF_HEADER, header)) {
-               rdfperror("ldrdf", f.name);
-               errorcount++;
-               return 0;
-           }
-           
-           keepfile = 0;
-
-           while ((hr = rdfgetheaderrec (&f)))
-           {
-                /* we're only interested in exports, so skip others: */
-               if (hr->type != 3) continue; 
-
-               /*
-                * Find the symbol in the symbol table. If the symbol isn't
-                * defined, we aren't interested, so go on to the next.
-                * If it is defined as anything but -1, we're also not
-                * interested. But if it is defined as -1, insert this
-                * module into the list of modules to use, and go
-                * immediately on to the next module...
-                */
-               if (! symtab_get(hr->e.label, &segment, &offset) 
-                   || segment != -1)
-               {
-                   continue;    
-               }
-               
-               doneanything = 1;
-               keepfile = 1;
-
-               /*
-                * as there are undefined symbols, we can assume that
-                * there are modules on the module list by the time
-                * we get here.
-                */
-               lastmodule->next = malloc(sizeof(*lastmodule->next));
-               if (!lastmodule->next) {
-                   fprintf(stderr, "ldrdf: not enough memory\n");
-                   exit(1);
-               }
-               lastmodule = lastmodule->next;
-               memcpy(&lastmodule->f, &f, sizeof(f));
-               lastmodule->name = strdup(f.name);
-                lastmodule->next = NULL;
-               processmodule(f.name, lastmodule);
-               break;
-           }
-           if (!keepfile)
-             {
-              free(f.name);
-              f.name = NULL;
-              f.fp = NULL;
-             }
-       }
-       if (rdl_error != 0 && rdl_error != RDL_ENOTFOUND)
-           rdl_perror("ldrdf", cur->name);
-
-       cur = cur->next;
-       if (cur == NULL && pass == 1) {
-           cur = libraries;
-           pass++;
-       }
-    }
-
-    return doneanything;
-}
-
-/*
- * write_output()
- *
- * this takes the linked list of modules, and walks through it, merging
- * all the modules into a single output module, and then writes this to a
- * file.
- */
-void write_output(const char * filename)
-{
-    FILE          * f;
-    rdf_headerbuf * rdfheader;
-    struct modulenode * cur;
-    int                  i, availableseg, seg, localseg, isrelative;
-    void         * header;
-    rdfheaderrec  * hr, newrec;
-    symtabEnt    * se;
-    segtab       segs;
-    long         offset;
-    byte         * data;
-
-    if ((f = fopen(filename, "wb"))==NULL) {
-       fprintf(stderr, "ldrdf: couldn't open %s for output\n", filename);
-       exit(1);
-    }
-    if ((rdfheader=rdfnewheader())==NULL) {
-       fprintf(stderr, "ldrdf: out of memory\n");
-       exit(1);
-    }
-    
-    /*
-     * Add multiboot header if appropriate option is specified.
-     * Multiboot record *MUST* be the first record in output file.
-     */
-    if (options.addMBheader) {
-       if (options.verbose)
-           puts("\nadding multiboot header record");
-    
-        hr = (rdfheaderrec *) malloc(sizeof(struct MultiBootHdrRec));
-        hr->mbh.type = 9;
-        hr->mbh.reclen = sizeof(struct tMultiBootHeader)+RDFLDRMOVER_SIZE;
-           
-        hr->mbh.mb.Magic = MB_MAGIC;
-        hr->mbh.mb.Flags = MB_FL_KLUDGE;
-       hr->mbh.mb.Checksum = ~(MB_MAGIC+MB_FL_KLUDGE-1);
-        hr->mbh.mb.HeaderAddr = MBHloadAddr+16;
-        hr->mbh.mb.LoadAddr = MBHloadAddr;
-       hr->mbh.mb.Entry = MBHloadAddr+16+sizeof(struct tMultiBootHeader);
-       
-       memcpy(hr->mbh.mover,RDFloaderMover,RDFLDRMOVER_SIZE);
-           
-        rdfaddheader(rdfheader,hr);
-        free(hr);
-    }
-
-    if (options.verbose)
-       printf ("\nbuilding output module (%d segments)\n", nsegs);
-
-    /*
-     * Allocate the memory for the segments. We may be better off
-     * building the output module one segment at a time when running
-     * under 16 bit DOS, but that would be a slower way of doing this.
-     * And you could always use DJGPP...
-     */
-    for (i = 0; i < nsegs; i++)
-    {
-       outputseg[i].data=NULL;
-       if(!outputseg[i].length) continue;
-       outputseg[i].data = malloc(outputseg[i].length);
-       if (!outputseg[i].data) {
-           fprintf(stderr, "ldrdf: out of memory\n");
-           exit(1);
-       }
-    }
-
-    /*
-     * initialise availableseg, used to allocate segment numbers for
-     * imported and exported labels...
-     */
-    availableseg = nsegs;
-
-    /*
-     * Step through the modules, performing required actions on each one
-     */
-    for (cur = modules; cur; cur=cur->next)
-    {
-       /*
-        * Read the actual segment contents into the correct places in
-        * the newly allocated segments
-        */
-
-       for (i = 0; i < cur->f.nsegs; i++)
-       {
-           int dest = cur->seginfo[i].dest_seg;
-
-           if (dest == -1) continue;
-           if (rdfloadseg(&cur->f, i, 
-                          outputseg[dest].data + cur->seginfo[i].reloc))
-           {
-               rdfperror("ldrdf", cur->name);
-               exit(1);
-           }
-       }
-       /*
-        * Perform fixups, and add new header records where required
-        */
-
-       header = malloc(cur->f.header_len);
-       if (!header) {
-           fprintf(stderr, "ldrdf: out of memory\n");
-           exit(1);
-       }
-
-       if (cur->f.header_loc)
-           rdfheaderrewind(&cur->f);
-       else
-           if (rdfloadseg(&cur->f, RDOFF_HEADER, header))
-           {
-               rdfperror("ldrdf", cur->name);
-               exit(1);
-           }
-       
-       /*
-        * we need to create a local segment number -> location
-        * table for the segments in this module.
-        */
-       init_seglocations(&segs);
-       for (i = 0; i < cur->f.nsegs; i++)
-       {
-           add_seglocation(&segs, cur->f.seg[i].number,
-                           cur->seginfo[i].dest_seg, cur->seginfo[i].reloc);
-       }
-       /*
-        * and the BSS segment (doh!)
-        */
-       add_seglocation (&segs, 2, 2, cur->bss_reloc);
-       
-       while ((hr = rdfgetheaderrec(&cur->f)))
-       {
-           switch(hr->type) {
-           case 1: /* relocation record - need to do a fixup */
-               /*
-                * First correct the offset stored in the segment from
-                * the start of the segment (which may well have changed).
-                *
-                * To do this we add to the number stored the relocation
-                * factor associated with the segment that contains the
-                * target segment.
-                *
-                * The relocation could be a relative relocation, in which
-                * case we have to first subtract the amount we've relocated
-                * the containing segment by.
-                */
-               
-               if (!get_seglocation(&segs, hr->r.refseg, &seg, &offset))
-               {
-                   fprintf(stderr, "%s: reloc to undefined segment %04x\n",
-                           cur->name, (int) hr->r.refseg);
-                   errorcount++;
-                   break;
-               }
-
-               isrelative = (hr->r.segment & 64) == 64;
-               hr->r.segment &= 63;
-
-               if (hr->r.segment == 2 || 
-                   (localseg = rdffindsegment(&cur->f, hr->r.segment)) == -1)
-               {
-                   fprintf(stderr, "%s: reloc from %s segment (%d)\n", 
-                           cur->name,
-                           hr->r.segment == 2 ? "BSS" : "unknown",
-                           hr->r.segment);
-                   errorcount++;
-                   break;
-               }
-
-               if (hr->r.length != 1 && hr->r.length != 2 && hr->r.length!=4)
-               {
-                   fprintf(stderr, "%s: nonstandard length reloc "
-                           "(%d bytes)\n", cur->name, hr->r.length);
-                   errorcount++;
-                   break;
-               }
-
-               /* 
-                * okay, now the relocation is in the segment pointed to by
-                * cur->seginfo[localseg], and we know everything else is
-                * okay to go ahead and do the relocation
-                */
-               data = outputseg[cur->seginfo[localseg].dest_seg].data;
-               data += cur->seginfo[localseg].reloc + hr->r.offset;
-
-               /*
-                * data now points to the reference that needs
-                * relocation. Calculate the relocation factor.
-                * Factor is:
-                *      offset of referred object in segment [in offset]
-                *      (- relocation of localseg, if ref is relative)
-                * For simplicity, the result is stored in 'offset'.
-                * Then add 'offset' onto the value at data.
-                */
-               
-               if (isrelative) offset -= cur->seginfo[localseg].reloc;
-               switch (hr->r.length)
-               {
-               case 1:
-                   offset += *data;
-                   if (offset < -127 || offset > 128)
-                       fprintf(error_file, "warning: relocation out of range "
-                               "at %s(%02x:%08lx)\n", cur->name,
-                               (int)hr->r.segment, hr->r.offset);
-                   *data = (char) offset;
-                   break;
-               case 2:
-                   offset += * (short *)data;
-                   if (offset < -32767 || offset > 32768)
-                       fprintf(error_file, "warning: relocation out of range "
-                               "at %s(%02x:%08lx)\n", cur->name,
-                               (int)hr->r.segment, hr->r.offset);
-                   * (short *)data = (short) offset;
-                   break;
-               case 4:
-                   * (long *)data += offset;
-                   /* we can't easily detect overflow on this one */
-                   break;
-               }
-
-               /*
-                * If the relocation was relative between two symbols in
-                * the same segment, then we're done.
-                *
-                * Otherwise, we need to output a new relocation record
-                * with the references updated segment and offset...
-                */
-               if (! isrelative 
-                   || cur->seginfo[localseg].dest_seg != seg)
-               {
-                   hr->r.segment = cur->seginfo[localseg].dest_seg;
-                   hr->r.offset += cur->seginfo[localseg].reloc;
-                   hr->r.refseg = seg;
-                   rdfaddheader(rdfheader, hr);
-               }
-               break;
-
-           case 2: /* import symbol */
-           case 7:
-               /*
-                * scan the global symbol table for the symbol
-                * and associate its location with the segment number 
-                * for this module
-                */
-               se = symtabFind(symtab, hr->i.label);
-               if (!se || se->segment == -1) {
-                   if (options.warnUnresolved) {
-                       fprintf(error_file, "warning: unresolved reference to `%s'"
-                               " in module `%s'\n", hr->i.label, cur->name);
-                       if (options.errorUnresolved==1) errorcount++;
-                   }
-                   /*
-                    * we need to allocate a segment number for this
-                    * symbol, and store it in the symbol table for
-                    * future reference
-                    */ 
-                   if (!se) {
-                       se=malloc(sizeof(*se));
-                       if (!se) {
-                           fprintf(stderr, "ldrdf: out of memory\n");
-                           exit(1);
-                       }
-                       se->name = strdup(hr->i.label);
-                       se->flags = 0;
-                       se->segment = availableseg++;
-                       se->offset = 0;
-                       symtabInsert(symtab, se);
-                   }
-                   else {
-                       se->segment = availableseg++;
-                       se->offset = 0;
-                   }
-                   /*
-                    * output a header record that imports it to the
-                    * recently allocated segment number...
-                    */
-                   newrec = *hr;
-                   newrec.i.segment = se->segment;
-                   rdfaddheader(rdfheader, &newrec);
-               }
-
-               add_seglocation(&segs, hr->i.segment, se->segment, se->offset);
-               
-               break;
-
-           case 3: /* export symbol */
-               /*
-                * need to insert an export for this symbol into the new
-                * header, unless we're stripping symbols [unless this
-                * symbol is in an explicit keep list]. *** FIXME ***
-                */
-               if (options.strip)
-                   break;
-
-               if (hr->e.segment == 2) {
-                   seg = 2;
-                   offset = cur->bss_reloc;
-               }
-               else {
-                   localseg = rdffindsegment(&cur->f, hr->e.segment);
-                   if (localseg == -1) {
-                       fprintf(stderr, "%s: exported symbol `%s' from "
-                               "unrecognised segment\n", cur->name,
-                               hr->e.label);
-                       errorcount++;
-                       break;
-                   }
-                   offset = cur->seginfo[localseg].reloc;
-                   seg = cur->seginfo[localseg].dest_seg;
-               }
-
-               hr->e.segment = seg;    
-               hr->e.offset += offset;
-               rdfaddheader(rdfheader, hr);
-               break;
-
-           case 8: /* module name */
-                /*
-                 * insert module name record if export symbols
-                 * are not stripped.
-                 */
-               if (options.strip) break;
-
-               rdfaddheader(rdfheader, hr);
-               break;
-
-           case 6: /* segment fixup */
-               /*
-                * modify the segment numbers if necessary, and
-                * pass straight through to the output module header
-                *
-                * *** FIXME ***
-                */
-               if (hr->r.segment == 2) {
-                   fprintf(stderr, "%s: segment fixup in BSS section\n",
-                           cur->name);
-                   errorcount++;
-                   break;
-               }
-               localseg = rdffindsegment(&cur->f, hr->r.segment);
-               if (localseg == -1) {
-                   fprintf(stderr, "%s: segment fixup in unrecognised"
-                           " segment (%d)\n", cur->name, hr->r.segment);
-                   errorcount++;
-                   break;
-               }
-               hr->r.segment = cur->seginfo[localseg].dest_seg;
-               hr->r.offset += cur->seginfo[localseg].reloc;
-
-               if (!get_seglocation(&segs, hr->r.refseg, &seg, &offset))
-               {
-                   fprintf(stderr, "%s: segment fixup to undefined "
-                           "segment %04x\n", cur->name, (int)hr->r.refseg);
-                   errorcount++;
-                   break;
-               }
-               hr->r.refseg = seg;
-               rdfaddheader(rdfheader, hr);
-               break;
-           }
-       }
-
-       free(header);
-       done_seglocations(&segs);
-
-    }
-
-    /*
-     * combined BSS reservation for the entire results
-     */
-    newrec.type = 5;
-    newrec.b.reclen = 4;
-    newrec.b.amount = bss_length;
-    rdfaddheader(rdfheader, &newrec);
-
-    /*
-     * Write the header
-     */
-    for (i = 0; i < nsegs; i++)
-    {
-       if (i == 2) continue;
-       rdfaddsegment (rdfheader, outputseg[i].length);
-    }
-    
-    if (options.addMBheader) {
-       struct MultiBootHdrRec *mbhrec = (struct MultiBootHdrRec *)(rdfheader->buf->buffer);
-       unsigned l = membuflength(rdfheader->buf) + 14 + 
-                    10*rdfheader->nsegments + rdfheader->seglength;
-       unsigned *ldraddr = (unsigned *)(mbhrec->mover+1);
-
-       mbhrec->mb.LoadEndAddr = MBHloadAddr+l+10+RDFLDR_LENGTH; 
-       mbhrec->mb.BSSendAddr = mbhrec->mb.LoadEndAddr;
-       *ldraddr = MBHloadAddr+l+10;
-    }
-    
-    rdfwriteheader(f, rdfheader);
-    rdfdoneheader(rdfheader);
-    /*
-     * Step through the segments, one at a time, writing out into
-     * the output file
-     */
-    
-    for (i = 0; i < nsegs; i++)
-    {
-       int16 s;
-       long l;
-       
-       if (i == 2) continue;
-
-       s = translateshort(outputseg[i].type);
-       fwrite(&s, 2, 1, f);
-       s = translateshort(outputseg[i].number);
-       fwrite(&s, 2, 1, f);
-       s = translateshort(outputseg[i].reserved);
-       fwrite(&s, 2, 1, f);
-       l = translatelong(outputseg[i].length);
-       fwrite(&l, 4, 1, f);
-
-       fwrite(outputseg[i].data, outputseg[i].length, 1, f);
-    }
-
-    fwrite("\0\0\0\0\0\0\0\0\0\0", 10, 1, f);
-}
-
-/* =========================================================================
- * Main program
- */
-
-void usage()
-{
-    printf("usage:\n");
-    printf("   ldrdf [options] object modules ... [-llibrary ...]\n");
-    printf("   ldrdf -r\n");
-    printf("options:\n");
-    printf("   -v[=n]          increases verbosity by 1, or sets it to n\n");
-    printf("   -a nn           sets segment alignment value (default 16)\n");
-    printf("   -s              strips exported symbols\n");
-    printf("   -x              warn about unresolved symbols\n");
-    printf("   -o name         write output in file 'name'\n");
-    printf("   -j path         specify objects search path\n");
-    printf("   -L path         specify libraries search path\n");
-    printf("   -mbh [address]  add multiboot header to output file. Default\n");
-    printf("                   loading address is 0x110000\n");
-    exit(0);
-}
-
-int main(int argc, char ** argv)
-{
-    char * outname = "aout.rdf";
-    int  moduleloaded = 0;
-    char *respstrings[128] = {0, };
-
-    options.verbose = 0;
-    options.align = 16;
-    options.warnUnresolved = 0;
-    options.strip = 0;
-
-    error_file = stderr;
-
-    argc --, argv ++;
-    if (argc == 0) usage();
-    while (argc && **argv == '-' && argv[0][1] != 'l')
-    {
-       switch(argv[0][1]) {
-       case 'r':
-           printf("ldrdf (linker for RDF files) version " LDRDF_VERSION "\n");
-           printf( _RDOFF_H "\n");
-           exit(0);
-       case 'v':
-           if (argv[0][2] == '=') {
-               options.verbose = argv[0][3] - '0';
-               if (options.verbose < 0 || options.verbose > 9) {
-                   fprintf(stderr, "ldrdf: verbosity level must be a number"
-                           " between 0 and 9\n");
-                   exit(1);
-               }
-           }
-           else
-               options.verbose++;
-           break;
-       case 'a':
-           options.align = atoi(argv[1]);
-           if (options.align <= 0) {
-               fprintf(stderr,
-                       "ldrdf: -a expects a positive number argument\n");
-               exit(1);
-           }
-           argv++, argc--;
-           break;
-       case 's':
-           options.strip = 1;
-           break;
-       case 'x':
-           options.warnUnresolved = 1;
-           if (argv[0][2]=='e')
-               options.errorUnresolved = 1;
-           break;
-       case 'o':
-           outname = argv[1];
-           argv++, argc--;
-           break;
-       case 'j':
-           if (!objpath)
-            {
-              options.objpath = 1;
-             objpath = argv[1];
-             argv++, argc--;
-             break;
-            }
-           else
-            {
-             fprintf(stderr,"ldrdf: more than one objects search path specified\n");
-             exit(1);
-            }
-       case 'L':
-           if (!libpath)
-             {
-              options.libpath = 1;
-             libpath = argv[1];
-             argv++, argc--;
-             break;
-            }
-           else
-            {
-             fprintf(stderr,"ldrdf: more than one libraries search path specified\n");
-             exit(1);
-            }
-       case '@': {
-             int i=0;
-             char buf[256];
-             FILE *f;
-
-              options.respfile = 1;
-             if (argv[1] != NULL) f = fopen(argv[1],"r");
-             else
-              {
-               fprintf(stderr,"ldrdf: no response file name specified\n");
-               exit(1);
-              }
-
-             if (f == NULL)
-              {
-               fprintf(stderr,"ldrdf: unable to open response file\n");
-               exit(1);
-              }
-             argc-=2;
-             while(fgets(buf,sizeof(buf)-1,f)!=NULL)
-              {
-               char *p;
-               if (buf[0]=='\n') continue;
-               if ((p = strchr(buf,'\n')) != 0)
-                *p=0;
-               if (i >= 128)
-                {
-                 fprintf(stderr,"ldrdf: too many input files\n");
-                 exit(1);
-                }
-               *(respstrings+i) = newstr(buf);
-               argc++, i++;
-              }
-             goto done;
-        }
-       case '2':
-            options.stderr_redir = 1;
-           error_file = stdout;
-           break;
-       case 'm':
-           if (argv[0][2] == 'b' && argv[0][3] == 'h') {
-               if (argv[1][0] != '-') {
-                   MBHloadAddr = atoi(argv[1]);
-               } else {
-                   MBHloadAddr = MB_DEFAULTLOADADDR;
-               }        
-               options.addMBheader = 1;
-               break;    
-           }           
-       default:
-           usage();
-       }
-       argv++, argc--;
-    }
-done:
-    if (options.verbose > 4) {
-       printf("ldrdf invoked with options:\n");
-       printf("    section alignment: %d bytes\n", options.align);
-       printf("    output name: `%s'\n", outname);
-       if (options.strip)
-           printf("    strip symbols\n");
-       if (options.warnUnresolved)
-           printf("    warn about unresolved symbols\n");
-       if (options.errorUnresolved)
-           printf("    error if unresolved symbols\n");    
-        if (options.objpath)
-            printf("    objects search path: %s\n",objpath);
-        if (options.libpath)
-            printf("    libraries search path: %s\n",libpath);
-       if (options.addMBheader)
-            printf("    loading address for multiboot header: 0x%X\n",MBHloadAddr);    
-       printf("\n");
-    }
-
-    symtab = symtabNew();
-    initsegments();
-
-    if (!symtab) {
-       fprintf(stderr, "ldrdf: out of memory\n");
-       exit(1);
-    }
-
-    if (*respstrings) argv = respstrings;
-    while (argc)
-    {
-       if (!strncmp(*argv, "-l", 2)) /* library */
-         {
-         if(libpath) add_library(newstrcat(libpath,*argv + 2));
-          else add_library(*argv + 2);
-         }
-       else {
-           if(objpath) loadmodule(newstrcat(objpath,*argv));
-           else loadmodule(*argv);
-           moduleloaded = 1;
-       }
-       argv++, argc--;
-    }
-
-    if (! moduleloaded) {
-       printf("ldrdf: nothing to do. ldrdf -h for usage\n");
-       return 0;
-    }
-
-
-    search_libraries();
-
-    if (options.verbose > 2)
-    {
-       printf ("symbol table:\n");
-       symtabDump(symtab, stdout);
-    }
-
-    write_output(outname);
-
-    if (errorcount > 0)        exit(1);
-    return 0;
-}
+***************
+*** 29,42 ****
+  #include <stdlib.h>
+  #include <string.h>
+  
+  #include "rdoff.h"
+  #include "symtab.h"
+  #include "collectn.h"
+  #include "rdlib.h"
+  #include "segtab.h"
+- #include "multboot.h"
+  
+- #define LDRDF_VERSION "1.01 alpha 2"
+  
+  #define RDF_MAXSEGS 64
+  /* #define STINGY_MEMORY */
+--- 29,42 ----
+  #include <stdlib.h>
+  #include <string.h>
+  
++ #include "multboot.h"
+  #include "rdoff.h"
+  #include "symtab.h"
+  #include "collectn.h"
+  #include "rdlib.h"
+  #include "segtab.h"
+  
++ #define LDRDF_VERSION "1.02"
+  
+  #define RDF_MAXSEGS 64
+  /* #define STINGY_MEMORY */
diff --git a/test/multisection.asm b/test/multisection.asm
new file mode 100644 (file)
index 0000000..327e518
--- /dev/null
@@ -0,0 +1,42 @@
+\r
+section .stringdata\r
+mystr1: db "Hello, this is string 1", 13, 10, '$'\r
+\r
+section .extra_code\r
+org 0x200\r
+bits 16\r
+more:\r
+   mov si, asciz1\r
+   mov ah, 0x0E\r
+   xor bx, bx\r
+.print:\r
+   lodsb\r
+   test al, al\r
+   jz .end\r
+   int  0x10\r
+   jmp short .print\r
+.end:\r
+\r
+   xor ax, ax\r
+   int 0x16\r
+\r
+   mov ax, 0x4c00\r
+   int 0x21\r
+\r
+section .appspecific\r
+asciz1: db "This is string 2", 0\r
+\r
+section .code\r
+org 0x100\r
+bits 16\r
+\r
+start:\r
+   mov dx, mystr1\r
+   mov ah, 9\r
+   int 0x21\r
+\r
+   xor ax, ax\r
+   int 0x16\r
+\r
+   jmp more\r
+\r