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

📄 outieee.c

📁 开源的nasm编译器源码,研究编译器原理很有帮且
💻 C
📖 第 1 页 / 共 3 页
字号:
/* outieee.c	output routines for the Netwide Assembler to produce *		IEEE-std object files * * 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. *//* notes: I have tried to make this correspond to the IEEE version * of the standard, specifically the primary ASCII version.  It should * be trivial to create the binary version given this source (which is * one of MANY things that have to be done to make this correspond to * the hp-microtek version of the standard). * * 16-bit support is assumed to use 24-bit addresses * The linker can sort out segmentation-specific stuff * if it keeps track of externals * in terms of being relative to section bases * * A non-standard variable type, the 'Yn' variable, has been introduced. * Basically it is a reference to extern 'n'- denoting the low limit * (L-variable) of the section that extern 'n' is defined in.  Like the * x variable, there may be no explicit assignment to it, it is derived * from the public definition corresponding to the extern name.  This * is required because the one thing the mufom guys forgot to do well was * take into account segmented architectures. * * I use comment classes for various things and these are undefined by * the standard. * * Debug info should be considered totally non-standard (local labels are * standard but linenum records are not covered by the standard. * Type defs have the standard format but absolute meanings for ordinal * types are not covered by the standard.) * * David Lindauer, LADsoft */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>#include <stdarg.h>  /* Note: we need the ANSI version of stdarg.h */#include <ctype.h>#include "nasm.h"#include "nasmlib.h"#include "outform.h"#ifdef OF_IEEE#define ARRAY_BOT 0x1static char ieee_infile[FILENAME_MAX];static int ieee_uppercase;static efunc error;static ldfunc deflabel;static FILE *ofp;static int any_segs;static int arrindex;#define HUNKSIZE 1024		       /* Size of the data hunk */#define EXT_BLKSIZ 512#define LDPERLINE 32			/* bytes per line in output */struct ieeeSection;struct LineNumber {    struct LineNumber *next;    struct ieeeSection *segment;    long offset;    long lineno;};static struct FileName {    struct FileName *next;    char *name;    long index;} *fnhead, **fntail;static struct Array {    struct Array *next;    unsigned size;    int basetype;} *arrhead, **arrtail;static struct ieeePublic {    struct ieeePublic *next;    char *name;    long offset;    long segment;		       /* only if it's far-absolute */    long index;    int type;	 			/* for debug purposes */	} *fpubhead, **fpubtail, *last_defined;static struct ieeeExternal {    struct ieeeExternal *next;    char *name;    long commonsize;} *exthead, **exttail;static int externals;static struct ExtBack {    struct ExtBack *next;    int index[EXT_BLKSIZ];} *ebhead, **ebtail;/* NOTE: the first segment MUST be the lineno segment */static struct ieeeSection {    struct ieeeObjData *data,*datacurr;    struct ieeeSection *next;    struct ieeeFixupp *fptr, * flptr;    long index;			       /* the NASM segment id */    long ieee_index;		       /* the OBJ-file segment index */    long currentpos;    long align;			       /* can be SEG_ABS + absolute addr */    long startpos;    enum {	CMB_PRIVATE = 0,	CMB_PUBLIC = 2,	CMB_COMMON = 6    } combine;    long use32;			       /* is this segment 32-bit? */    struct ieeePublic *pubhead, **pubtail, *lochead, **loctail;    char *name;} *seghead, **segtail, *ieee_seg_needs_update;struct ieeeObjData {    struct ieeeObjData *next;    unsigned char data[HUNKSIZE];};struct ieeeFixupp {    struct ieeeFixupp *next;    enum { 	FT_SEG = 0,	FT_REL = 1,	FT_OFS = 2,	FT_EXT = 3,	FT_WRT = 4,	FT_EXTREL = 5,	FT_EXTWRT = 6,	FT_EXTSEG = 7    } ftype;    short size;    long id1;    long id2;    long offset;    long addend;};		static long ieee_entry_seg, ieee_entry_ofs;static int checksum;extern struct ofmt of_ieee;static void ieee_data_new(struct ieeeSection *);static void ieee_write_fixup (long, long, struct ieeeSection *,				int, unsigned long, long);static void ieee_install_fixup(struct ieeeSection *, struct ieeeFixupp *);static long ieee_segment (char *, int, int *);static void ieee_write_file(int debuginfo);static void ieee_write_byte(struct ieeeSection *, int);static void ieee_write_word(struct ieeeSection *, int);static void ieee_write_dword(struct ieeeSection *, long);static void ieee_putascii(char *, ...);static void ieee_putcs(int);static long ieee_putld(long, long, unsigned char *);static long ieee_putlr(struct ieeeFixupp *);static void ieee_unqualified_name(char *, char *);/*  * pup init  */static void ieee_init (FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval) {    (void) eval;    ofp = fp;    error = errfunc;    deflabel = ldef;    any_segs = FALSE;    fpubhead = NULL;    fpubtail = &fpubhead;    exthead = NULL;    exttail = &exthead;    externals = 1;    ebhead = NULL;    ebtail = &ebhead;    seghead = ieee_seg_needs_update = NULL;    segtail = &seghead;    ieee_entry_seg = NO_SEG;    ieee_uppercase = FALSE;    checksum = 0;    of_ieee.current_dfmt->init (&of_ieee,NULL,fp,errfunc);}static int ieee_set_info(enum geninfo type, char **val){    (void) type;    (void) val;    return 0;}/* * Rundown */static void ieee_cleanup (int debuginfo) {    ieee_write_file(debuginfo);    of_ieee.current_dfmt->cleanup ();    fclose (ofp);    while (seghead) {	struct ieeeSection *segtmp = seghead;	seghead = seghead->next;	while (segtmp->pubhead) {	    struct ieeePublic *pubtmp = segtmp->pubhead;	    segtmp->pubhead = pubtmp->next;	    nasm_free (pubtmp);	}	while (segtmp->fptr) {	    struct ieeeFixupp *fixtmp = segtmp->fptr;	    segtmp->fptr = fixtmp->next;	    nasm_free(fixtmp);	}	while (segtmp->data) {	    struct ieeeObjData *dattmp = segtmp->data;	    segtmp->data = dattmp->next;	    nasm_free(dattmp);	}	nasm_free (segtmp);    }    while (fpubhead) {	struct ieeePublic *pubtmp = fpubhead;	fpubhead = fpubhead->next;	nasm_free (pubtmp);    }    while (exthead) {	struct ieeeExternal *exttmp = exthead;	exthead = exthead->next;	nasm_free (exttmp);    }    while (ebhead) {	struct ExtBack *ebtmp = ebhead;	ebhead = ebhead->next;	nasm_free (ebtmp);    }}/* * callback for labels */static void ieee_deflabel (char *name, long segment,			  long offset, int is_global, char *special) {    /*     * We have three cases:     *     * (i) `segment' is a segment-base. If so, set the name field     * for the segment structure it refers to, and then     * return.     *     * (ii) `segment' is one of our segments, or a SEG_ABS segment.     * Save the label position for later output of a PUBDEF record.     *      *     * (iii) `segment' is not one of our segments. Save the label     * position for later output of an EXTDEF.     */    struct ieeeExternal *ext;    struct ExtBack *eb;    struct ieeeSection *seg;    int i;    if (special) {        error(ERR_NONFATAL, "unrecognised symbol type `%s'", special);    }    /*     * First check for the double-period, signifying something     * unusual.     */    if (name[0] == '.' && name[1] == '.') {	if (!strcmp(name, "..start")) {	    ieee_entry_seg = segment;	    ieee_entry_ofs = offset;	}	return;    }    /*     * Case (i):     */    if (ieee_seg_needs_update) {	ieee_seg_needs_update->name = name;	return;    }     if (segment < SEG_ABS && segment != NO_SEG && segment % 2)	return;    /*     * case (ii)     */    if (segment >= SEG_ABS) {	/*	 * SEG_ABS subcase of (ii).	 */	if (is_global) {	    struct ieeePublic *pub;	    pub = *fpubtail = nasm_malloc(sizeof(*pub));	    fpubtail = &pub->next;	    pub->next = NULL;	    pub->name = name;	    pub->offset = offset;	    pub->segment = segment & ~SEG_ABS;	}	return;    }    for (seg = seghead; seg && is_global; seg = seg->next)	if (seg->index == segment) {		struct ieeePublic *pub;	    last_defined = pub = *seg->pubtail = nasm_malloc(sizeof(*pub));	    seg->pubtail = &pub->next;	    pub->next = NULL;	    pub->name = name;	    pub->offset = offset;	    pub->index = seg->ieee_index;	    pub->segment = -1;	    return;	}    /*     * Case (iii).     */    if (is_global) {        ext = *exttail = nasm_malloc(sizeof(*ext));        ext->next = NULL;        exttail = &ext->next;        ext->name = name;        if (is_global == 2)	    ext->commonsize = offset;    	else	    ext->commonsize = 0;    	i = segment/2;    	eb = ebhead;    	if (!eb) {	    eb = *ebtail = nasm_malloc(sizeof(*eb));	    eb->next = NULL;	    ebtail = &eb->next;        }    	while (i > EXT_BLKSIZ) {	    if (eb && eb->next)	        eb = eb->next;	    else {	        eb = *ebtail = nasm_malloc(sizeof(*eb));	    	eb->next = NULL;	    	ebtail = &eb->next;	    }	    i -= EXT_BLKSIZ;    	}        eb->index[i] = externals++;    }	}/* * Put data out */static void ieee_out (long segto, const void *data, unsigned long type,		     long segment, long wrt) {    unsigned long size, realtype;    const unsigned char *ucdata;    long ldata;    struct ieeeSection *seg;    /*     * 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;    }    /*     * If `any_segs' is still FALSE, we must define a default     * segment.     */    if (!any_segs) {	int tempint;		       /* ignored */	if (segto != ieee_segment("__NASMDEFSEG", 2, &tempint))	    error (ERR_PANIC, "strange segment conditions in IEEE driver");    }    /*     * Find the segment we are targetting.     */    for (seg = seghead; seg; seg = seg->next)	if (seg->index == segto)	    break;    if (!seg)	error (ERR_PANIC, "code directed to nonexistent segment?");    size = type & OUT_SIZMASK;    realtype = type & OUT_TYPMASK;    if (realtype == OUT_RAWDATA) {	ucdata = data;	while (size--)	    ieee_write_byte(seg,*ucdata++);    } else if (realtype == OUT_ADDRESS || realtype == OUT_REL2ADR ||	       realtype == OUT_REL4ADR) {	if (segment == NO_SEG && realtype != OUT_ADDRESS)	    error(ERR_NONFATAL, "relative call to absolute address not"		  " supported by IEEE format");	ldata = *(long *)data;	if (realtype == OUT_REL2ADR)	    ldata += (size-2);	if (realtype == OUT_REL4ADR)	    ldata += (size-4);	ieee_write_fixup (segment, wrt, seg, size, realtype,ldata);	if (size == 2)	    ieee_write_word (seg, ldata);	else	    ieee_write_dword (seg, ldata);    }     else if (realtype == OUT_RESERVE) {	while (size--)	    ieee_write_byte(seg,0);    }}static void ieee_data_new(struct ieeeSection *segto) {        if (!segto->data)	segto->data = segto->datacurr = nasm_malloc(sizeof(*(segto->datacurr)));    else	segto->datacurr = segto->datacurr->next = nasm_malloc(sizeof(*(segto->datacurr)));    segto->datacurr->next = NULL;}/* * this routine is unalduterated bloatware.  I usually don't do this * but I might as well see what it is like on a harmless program. * If anyone wants to optimize this is a good canditate! */static void ieee_write_fixup (long segment, long wrt, struct ieeeSection * segto,				int size, unsigned long realtype, long offset) {    struct ieeeSection *target;    struct ieeeFixupp s;    /* Don't put a fixup for things NASM can calculate */    if (wrt == NO_SEG && segment == NO_SEG)	return;    s.ftype = -1;    /* if it is a WRT offset */    if (wrt != NO_SEG) {	s.ftype = FT_WRT;	s.addend = offset;	if (wrt >= SEG_ABS)	    s.id1 = -(wrt-SEG_ABS);	else {	    if (wrt %2 && realtype != OUT_REL2ADR && realtype != OUT_REL4ADR) {		wrt--;	    	for (target = seghead; target; target = target->next)	            if (target->index == wrt)	            	break;    	        if (target) {	            s.id1 = target->ieee_index;	    	    for (target = seghead; target; target = target->next)	            	if (target->index == segment)	            	    break;				    if (target) 		    	s.id2 = target->ieee_index;	            else {			/*			 * Now we assume the segment field is being used			 * to hold an extern index		 	 */			long i = segment/2;			struct ExtBack *eb = ebhead;			while (i > EXT_BLKSIZ) {			    if (eb)

⌨️ 快捷键说明

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