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

📄 outobj.c

📁 一个免费的汇编语言编译器的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	else if (seglen == 0x10000L) {
	    seglen = 0;                /* This special case may be needed for old linkers */
	    acbp |= 0x02;	       /* B bit */
	}


	/* A field */
	if (seg->align >= SEG_ABS)
	    /* acbp |= 0x00 */;
	else if (seg->align >= 4096) {
	    if (seg->align > 4096)
		error(ERR_NONFATAL, "segment `%s' requires more alignment"
		      " than OBJ format supports", seg->name);
	    acbp |= 0xC0;	       /* PharLap extension */
	} else if (seg->align >= 256) {
	    acbp |= 0x80;
	} else if (seg->align >= 16) {
	    acbp |= 0x60;
	} else if (seg->align >= 4) {
	    acbp |= 0xA0;
	} else if (seg->align >= 2) {
	    acbp |= 0x40;
	} else
	    acbp |= 0x20;

	obj_byte (orp, acbp);
	if (seg->align & SEG_ABS) {
	    obj_x (orp, seg->align - SEG_ABS);  /* Frame */
	    obj_byte (orp, 0);  /* Offset */
	}
	obj_x (orp, seglen);
	obj_index (orp, ++lname_idx);
	obj_index (orp, seg->segclass ? ++lname_idx : 1);
	obj_index (orp, seg->overlay ? ++lname_idx : 1);
	obj_emit2 (orp);
    }

    /*
     * Write the GRPDEF records.
     */
    orp->type = GRPDEF;
    for (grp = grphead; grp; grp = grp->next) {
	int i;

	if (grp->nindices != grp->nentries) {
	    for (i = grp->nindices; i < grp->nentries; i++) {
		error(ERR_NONFATAL, "group `%s' contains undefined segment"
		      " `%s'", grp->name, grp->segs[i].name);
		nasm_free (grp->segs[i].name);
		grp->segs[i].name = NULL;
	    }
	}
	obj_index (orp, ++lname_idx);
	for (i = 0; i < grp->nindices; i++) {
	    obj_byte (orp, 0xFF);
	    obj_index (orp, grp->segs[i].index);
	}
	obj_emit2 (orp);
    }

    /*
     * Write the PUBDEF records: first the ones in the segments,
     * then the far-absolutes.
     */
    orp->type = PUBDEF;
    orp->ori = ori_pubdef;
    for (seg = seghead; seg; seg = seg->next) {
	orp->parm[0] = seg->grp ? seg->grp->obj_index : 0;
	orp->parm[1] = seg->obj_index;
	for (pub = seg->pubhead; pub; pub = pub->next) {
	    orp = obj_name (orp, pub->name);
	    orp = obj_x (orp, pub->offset);
	    orp = obj_byte (orp, 0);  /* type index */
	    obj_commit (orp);
	}
	obj_emit (orp);
    }
    orp->parm[0] = 0;
    orp->parm[1] = 0;
    for (pub = fpubhead; pub; pub = pub->next) {   /* pub-crawl :-) */
	if (orp->parm[2] != pub->segment) {
	    obj_emit (orp);
	    orp->parm[2] = pub->segment;
	}
	orp = obj_name (orp, pub->name);
	orp = obj_x (orp, pub->offset);
	orp = obj_byte (orp, 0);  /* type index */
	obj_commit (orp);
    }
    obj_emit (orp);

    /*
     * Write the EXTDEF and COMDEF records, in order.
     */
    orp->ori = ori_null;
    for (ext = exthead; ext; ext = ext->next) {
	if (ext->commonsize == 0) {
	    if (orp->type != EXTDEF) {
		obj_emit (orp);
		orp->type = EXTDEF;
	    }
	    orp = obj_name (orp, ext->name);
	    orp = obj_index (orp, 0);
	} else {
	    if (orp->type != COMDEF) {
		obj_emit (orp);
		orp->type = COMDEF;
	    }
	    orp = obj_name (orp, ext->name);
	    orp = obj_index (orp, 0);
	    if (ext->commonelem) {
		orp = obj_byte (orp, 0x61);/* far communal */
		orp = obj_value (orp, (ext->commonsize / ext->commonelem));
		orp = obj_value (orp, ext->commonelem);
	    } else {
		orp = obj_byte (orp, 0x62);/* near communal */
		orp = obj_value (orp, ext->commonsize);
	    }
	}
	obj_commit (orp);
    }
    obj_emit (orp);

    /*
     * Write a COMENT record stating that the linker's first pass
     * may stop processing at this point. Exception is if our
     * MODEND record specifies a start point, in which case,
     * according to some variants of the documentation, this COMENT
     * should be omitted. So we'll omit it just in case.
     * But, TASM puts it in all the time so if we are using
     * TASM debug stuff we are putting it in
     */
    if (debuginfo || obj_entry_seg == NO_SEG) {
	orp->type = COMENT;
        obj_byte (orp, 0x40);
        obj_byte (orp, dLINKPASS);
	obj_byte (orp, 1);
	obj_emit2 (orp);
    } 

    /*
     * 1) put out the compiler type
     * 2) Put out the type info.  The only type we are using is near label #19
     */
    if (debuginfo) {
      int i;
      struct Array *arrtmp = arrhead;
      orp->type = COMENT;
      obj_byte (orp, 0x40);
      obj_byte (orp, dCOMPDEF);
      obj_byte (orp, 4);
      obj_byte (orp, 0);
      obj_emit2 (orp);

      obj_byte (orp, 0x40);
      obj_byte (orp, dTYPEDEF);
      obj_word (orp, 0x18); /* type # for linking */
      obj_word (orp, 6);    /* size of type */
      obj_byte (orp, 0x2a); /* absolute type for debugging */
      obj_emit2 (orp);
      obj_byte (orp, 0x40);
      obj_byte (orp, dTYPEDEF);
      obj_word (orp, 0x19); /* type # for linking */
      obj_word (orp, 0);    /* size of type */
      obj_byte (orp, 0x24); /* absolute type for debugging */
      obj_byte (orp, 0);    /* near/far specifier */
      obj_emit2 (orp);
      obj_byte (orp, 0x40);
      obj_byte (orp, dTYPEDEF);
      obj_word (orp, 0x1A); /* type # for linking */
      obj_word (orp, 0);    /* size of type */
      obj_byte (orp, 0x24); /* absolute type for debugging */
      obj_byte (orp, 1);    /* near/far specifier */
      obj_emit2 (orp);
      obj_byte (orp, 0x40);
      obj_byte (orp, dTYPEDEF);
      obj_word (orp, 0x1b); /* type # for linking */
      obj_word (orp, 0);    /* size of type */
      obj_byte (orp, 0x23); /* absolute type for debugging */
      obj_byte (orp, 0);
      obj_byte (orp, 0);
      obj_byte (orp, 0);
      obj_emit2 (orp);
      obj_byte (orp, 0x40);
      obj_byte (orp, dTYPEDEF);
      obj_word (orp, 0x1c); /* type # for linking */
      obj_word (orp, 0);    /* size of type */
      obj_byte (orp, 0x23); /* absolute type for debugging */
      obj_byte (orp, 0);
      obj_byte (orp, 4);
      obj_byte (orp, 0);
      obj_emit2 (orp);
      obj_byte (orp, 0x40);
      obj_byte (orp, dTYPEDEF);
      obj_word (orp, 0x1d); /* type # for linking */
      obj_word (orp, 0);    /* size of type */
      obj_byte (orp, 0x23); /* absolute type for debugging */
      obj_byte (orp, 0);
      obj_byte (orp, 1);
      obj_byte (orp, 0);
      obj_emit2 (orp);
      obj_byte (orp, 0x40);
      obj_byte (orp, dTYPEDEF);
      obj_word (orp, 0x1e); /* type # for linking */
      obj_word (orp, 0);    /* size of type */
      obj_byte (orp, 0x23); /* absolute type for debugging */
      obj_byte (orp, 0);
      obj_byte (orp, 5);
      obj_byte (orp, 0);
      obj_emit2 (orp);

      /* put out the array types */
      for (i= ARRAYBOT; i < arrindex; i++) {
        obj_byte (orp, 0x40);
      	obj_byte (orp, dTYPEDEF);
      	obj_word (orp, i ); /* type # for linking */
      	obj_word (orp, arrtmp->size);    /* size of type */
      	obj_byte (orp, 0x1A); /* absolute type for debugging (array)*/
      	obj_byte (orp, arrtmp->basetype ); /* base type */
      	obj_emit2 (orp);
        arrtmp = arrtmp->next ;
      }
    }
    /*
     * write out line number info with a LINNUM record
     * switch records when we switch segments, and output the
     * file in a pseudo-TASM fashion.  The record switch is naive; that
     * is that one file may have many records for the same segment
     * if there are lots of segment switches
     */
    if (fnhead && debuginfo) {
    	seg = fnhead->lnhead->segment;

    	for (fn = fnhead; fn; fn = fn->next) {
	    /* write out current file name */
            orp->type = COMENT;
            orp->ori = ori_null;
	    obj_byte (orp, 0x40);
	    obj_byte (orp, dFILNAME);
            obj_byte( orp,0);
            obj_name( orp,fn->name);
            obj_dword(orp, 0);
	    obj_emit2 (orp);

	    /* write out line numbers this file */

            orp->type = LINNUM;
            orp->ori = ori_linnum;
	    for (ln = fn->lnhead; ln; ln = ln->next) {
		if (seg != ln->segment) {
		    /* if we get here have to flush the buffer and start
                     * a new record for a new segment
		     */
		    seg = ln->segment;
		    obj_emit ( orp );
		}
		orp->parm[0] = seg->grp ? seg->grp->obj_index : 0;
		orp->parm[1] = seg->obj_index;
	        orp = obj_word(orp, ln->lineno);
                orp = obj_x(orp, ln->offset);
	        obj_commit (orp);
	    }
 	    obj_emit (orp);
	}
    }
    /*
     * we are going to locate the entry point segment now
     * rather than wait until the MODEND record, because,
     * then we can output a special symbol to tell where the
     * entry point is.
     *
     */
    if (obj_entry_seg != NO_SEG) {
	for (seg = seghead; seg; seg = seg->next) {
	    if (seg->index == obj_entry_seg) {
                entry_seg_ptr = seg;
		break;
	    }
	}
	if (!seg)
	    error(ERR_NONFATAL, "entry point is not in this module");
    }

    /*
     * get ready to put out symbol records
     */
    orp->type = COMENT;
    orp->ori = ori_local;
   
    /*
     * put out a symbol for the entry point
     * no dots in this symbol, because, borland does
     * not (officially) support dots in label names
     * and I don't know what various versions of TLINK will do
     */
    if (debuginfo && obj_entry_seg != NO_SEG) {
        orp = obj_name (orp,"start_of_program");
	orp = obj_word (orp,0x19);  /* type: near label */
	orp = obj_index (orp, seg->grp ? seg->grp->obj_index : 0);
	orp = obj_index (orp, seg->obj_index);
	orp = obj_x (orp, obj_entry_ofs);
	obj_commit (orp);
    } 
 
    /*
     * put out the local labels
     */
    for (seg = seghead; seg && debuginfo; seg = seg->next) {
        /* labels this seg */
        for (loc = seg->lochead; loc; loc = loc->next) {
            orp = obj_name (orp,loc->name);
	    orp = obj_word (orp, loc->type);
	    orp = obj_index (orp, seg->grp ? seg->grp->obj_index : 0);
	    orp = obj_index (orp, seg->obj_index);
	    orp = obj_x (orp,loc->offset);
	    obj_commit (orp);
        }
    }
    if (orp->used)
        obj_emit (orp);

    /*
     * Write the LEDATA/FIXUPP pairs.
     */
    for (seg = seghead; seg; seg = seg->next) {
	obj_emit (seg->orp);
	nasm_free (seg->orp);
    }

    /*
     * Write the MODEND module end marker.
     */
    orp->type = obj_use32 ? MODE32 : MODEND;
    orp->ori = ori_null;
    if (entry_seg_ptr) {
	orp->type = entry_seg_ptr->use32 ? MODE32 : MODEND;
	obj_byte (orp, 0xC1);
	seg = entry_seg_ptr;
	if (seg->grp) {
	    obj_byte (orp, 0x10);
	    obj_index (orp, seg->grp->obj_index);
	} else {
	    /*
	     * the below changed to prevent TLINK crashing.
	     * Previous more efficient version read:
	     *
	     *  obj_byte (orp, 0x50);
	     */
	    obj_byte (orp, 0x00);
	    obj_index (orp, seg->obj_index);
	}
	obj_index (orp, seg->obj_index);
	obj_x (orp, obj_entry_ofs);
    } else
	obj_byte (orp, 0);
    obj_emit2 (orp);
    nasm_free (orp);
}

void obj_fwrite(ObjRecord *orp) 
{
    unsigned int cksum, len;
    unsigned char *ptr;

    cksum = orp->type;
    if (orp->x_size == 32)
	cksum |= 1;
    fputc (cksum, ofp);
    len = orp->committed+1;
    cksum += (len & 0xFF) + ((len>>8) & 0xFF);
    fwriteshort (len, ofp);
    fwrite (orp->buf, 1, len-1, ofp);
    for (ptr=orp->buf; --len; ptr++)
	cksum += *ptr;
    fputc ( (-cksum) & 0xFF, ofp);
}

static const char *obj_stdmac[] = {
    "%define __SECT__ [section .text]",
    "%imacro group 1+.nolist",
    "[group %1]",
    "%endmacro",
    "%imacro uppercase 0+.nolist",
    "[uppercase %1]",
    "%endmacro",
    "%imacro export 1+.nolist",
    "[export %1]",
    "%endmacro",
    "%imacro import 1+.nolist",
    "[import %1]",
    "%endmacro",
    "%macro __NASM_CDecl__ 1",
    "%endmacro",
    NULL
};

void dbgbi_init(struct ofmt * of, void * id, FILE * fp, efunc error)
{
    (void) of;
    (void) id;
    (void) fp;
    (void) error;

    fnhead = NULL;
    fntail = &fnhead;
    arrindex = ARRAYBOT ;
    arrhead = NULL;
    arrtail = &arrhead;
}
static void dbgbi_cleanup(void)
{
    struct Segment *segtmp;
    while (fnhead) {
	struct FileName *fntemp = fnhead;
	while (fnhead->lnhead) {
	    struct LineNumber *lntemp = fnhead->lnhead;
	    fnhead->lnhead = lntemp->next;
	    nasm_free( lntemp);
	}
	fnhead = fnhead->next;
	nasm_free (fntemp->name);
	nasm_free (fntemp);
    }
    for (segtmp=seghead; segtmp; segtmp=segtmp->next) {
	while (segtmp->lochead) {
	    struct Public *loctmp = segtmp->lochead;
	    segtmp->lochead = loctmp->next;
	    nasm_free (loctmp->name);
	    nasm_free (loctmp);
	}
    }
    while (arrhead) {
	struct Array *arrtmp = arrhead;
        arrhead = arrhead->next;
        nasm_free (arrtmp);
    }
}

static void dbgbi_linnum (const char *lnfname, long lineno, long segto)
{
    struct FileName *fn;
    struct LineNumber *ln;
    struct Segment *seg;

    if (segto == NO_SEG)
	return;

    /*
     * If `any_segs' is still FALSE, we must define a default
     * segment.
     */
    if (!any_segs) {
	int tempint;		       /* ignored */
	if (segto != obj_segment("__NASMDEFSEG", 2, &tempint))
	    error (ERR_PANIC, "strange segment conditions in OBJ driver");
    }

    /*
     * Find the segment we are targetting.
     */
    for (seg = seghead; seg; seg = seg->next)
	if (seg->index == segto)
	    break;
    if (!seg)
	error (ERR_PANIC, "lineno directed to nonexistent segment?");

/*    for (fn = fnhead; fn; fn = fnhead->next) */
    for (fn = fnhead; fn; fn = fn->next) /* fbk - Austin Lunnen - John Fine*/
	if (!nasm_stricmp(lnfname,fn->name))
	    break;
    if (!fn) {
	fn = nasm_malloc ( sizeof( *fn));
	fn->name = nasm_malloc ( strlen(lnfname) + 1) ;
        strcpy (fn->name,lnfname);
	fn->lnhead = NULL;
	fn->ln

⌨️ 快捷键说明

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