From 9eb185bfdb10f1dfccbb9a702d2801a32cd1b13d Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 30 Apr 2002 21:02:47 +0000 Subject: [PATCH] NASM 0.98.15 --- README09b.txt | 82 +++ assemble.c | 6 +- macros.c | 16 + misc/exasm.zip | Bin 6058 -> 491 bytes nasm.h | 2 +- preproc.c | 2 +- rdoff/ldrdf.c | 1378 ++----------------------------------------------- test/multisection.asm | 42 ++ 8 files changed, 176 insertions(+), 1352 deletions(-) create mode 100644 README09b.txt create mode 100644 test/multisection.asm diff --git a/README09b.txt b/README09b.txt new file mode 100644 index 0000000..affb91a --- /dev/null +++ b/README09b.txt @@ -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 27-Jul-2000 + +(end) \ No newline at end of file diff --git a/assemble.c b/assemble.c index b9271a4..f560112 100644 --- a/assemble.c +++ b/assemble.c @@ -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); diff --git a/macros.c b/macros.c index ed70a75..38a7e0f 100644 --- 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 diff --git a/misc/exasm.zip b/misc/exasm.zip index b4e9e58a0845696f5ba7f15b4d381d8899df3641..e8130182cd7dd1393bd74504e130a99179491bd6 100644 GIT binary patch delta 7 OcmZ3b|C)KjYeoPLQ3GTE literal 6058 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 diff --git a/nasm.h b/nasm.h index c0dc0e5..c9a8f06 100644 --- 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 diff --git a/preproc.c b/preproc.c index 0277a45..4ec3826 100644 --- 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); } } diff --git a/rdoff/ldrdf.c b/rdoff/ldrdf.c index 3d9d749..d9aac2f 100644 --- a/rdoff/ldrdf.c +++ b/rdoff/ldrdf.c @@ -1,1347 +1,31 @@ -/* 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 -#include -#include - -#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 + #include + + #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 + #include + ++ #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 index 0000000..327e518 --- /dev/null +++ b/test/multisection.asm @@ -0,0 +1,42 @@ + +section .stringdata +mystr1: db "Hello, this is string 1", 13, 10, '$' + +section .extra_code +org 0x200 +bits 16 +more: + mov si, asciz1 + mov ah, 0x0E + xor bx, bx +.print: + lodsb + test al, al + jz .end + int 0x10 + jmp short .print +.end: + + xor ax, ax + int 0x16 + + mov ax, 0x4c00 + int 0x21 + +section .appspecific +asciz1: db "This is string 2", 0 + +section .code +org 0x100 +bits 16 + +start: + mov dx, mystr1 + mov ah, 9 + int 0x21 + + xor ax, ax + int 0x16 + + jmp more + -- 2.7.4