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

📄 outieee.c

📁 32位汇编编译器nasm源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
        }
        i++;
        pub = pub->next;
    }
    /*
     * Write the externals
     */
    ext = exthead;
    i = 1;
    while (ext) {
        char buf[256];
        ieee_unqualified_name(buf, ext->name);
        ieee_putascii("NX%X,%02X%s.\r\n", i++, strlen(buf), buf);
        ext = ext->next;
    }
    ieee_putcs(FALSE);

    /*
     * IEEE doesn't have a standard pass break record
     * so use the ladsoft variant
     */
    ieee_putascii("CO100,06ENDSYM.\r\n");

    /*
     * now put types
     */
    i = ARRAY_BOT;
    for (arr = arrhead; arr && debuginfo; arr = arr->next) {
        ieee_putascii("TY%X,20,%X,%lX.\r\n", i++, arr->basetype,
                      arr->size);
    }
    /*
     * now put locals
     */
    i = 1;
    for (seg = seghead; seg && debuginfo; seg = seg->next) {
        for (loc = seg->lochead; loc; loc = loc->next) {
            char buf[256];
            ieee_unqualified_name(buf, loc->name);
            ieee_putascii("NN%X,%02X%s.\r\n", i, strlen(buf), buf);
            if (loc->segment == -1)
                ieee_putascii("ASN%X,R%X,%lX,+.\r\n", i, loc->index,
                              loc->offset);
            else
                ieee_putascii("ASN%X,%lX,%lX,+.\r\n", i, loc->segment * 16,
                              loc->offset);
            if (debuginfo) {
                if (loc->type >= 0x100)
                    ieee_putascii("ATN%X,T%X.\r\n", i, loc->type - 0x100);
                else
                    ieee_putascii("ATN%X,%X.\r\n", i, loc->type);
            }
            i++;
        }
    }

    /*
     *  put out section data;
     */
    seg = seghead;
    if (!debuginfo && !strcmp(seg->name, "??LINE"))
        seg = seg->next;
    while (seg) {
        if (seg->currentpos) {
            long size, org = 0;
            data = seg->data;
            ieee_putascii("SB%X.\r\n", seg->ieee_index);
            fix = seg->fptr;
            while (fix) {
                size = HUNKSIZE - (org % HUNKSIZE);
                size =
                    size + org >
                    seg->currentpos ? seg->currentpos - org : size;
                size = fix->offset - org > size ? size : fix->offset - org;
                org = ieee_putld(org, org + size, data->data);
                if (org % HUNKSIZE == 0)
                    data = data->next;
                if (org == fix->offset) {
                    org += ieee_putlr(fix);
                    fix = fix->next;
                }
            }
            while (org < seg->currentpos && data) {
                size =
                    seg->currentpos - org >
                    HUNKSIZE ? HUNKSIZE : seg->currentpos - org;
                org = ieee_putld(org, org + size, data->data);
                data = data->next;
            }
            ieee_putcs(FALSE);

        }
        seg = seg->next;
    }
    /*
     * module end record
     */
    ieee_putascii("ME.\r\n");
}

static void ieee_write_byte(struct ieeeSection *seg, int data)
{
    int temp;
    if (!(temp = seg->currentpos++ % HUNKSIZE))
        ieee_data_new(seg);
    seg->datacurr->data[temp] = data;
}

static void ieee_write_word(struct ieeeSection *seg, int data)
{
    ieee_write_byte(seg, data & 0xFF);
    ieee_write_byte(seg, (data >> 8) & 0xFF);
}

static void ieee_write_dword(struct ieeeSection *seg, long data)
{
    ieee_write_byte(seg, data & 0xFF);
    ieee_write_byte(seg, (data >> 8) & 0xFF);
    ieee_write_byte(seg, (data >> 16) & 0xFF);
    ieee_write_byte(seg, (data >> 24) & 0xFF);
}
static void ieee_putascii(char *format, ...)
{
    char buffer[256];
    int i, l;
    va_list ap;

    va_start(ap, format);
    vsprintf(buffer, format, ap);
    l = strlen(buffer);
    for (i = 0; i < l; i++)
        if ((buffer[i] & 0xff) > 31)
            checksum += buffer[i];
    va_end(ap);
    fprintf(ofp, buffer);
}

/*
 * put out a checksum record */
static void ieee_putcs(int toclear)
{
    if (toclear) {
        ieee_putascii("CS.\r\n");
    } else {
        checksum += 'C';
        checksum += 'S';
        ieee_putascii("CS%02X.\r\n", checksum & 127);
    }
    checksum = 0;
}

static long ieee_putld(long start, long end, unsigned char *buf)
{
    long val;
    if (start == end)
        return (start);
    val = start % HUNKSIZE;
    /* fill up multiple lines */
    while (end - start >= LDPERLINE) {
        int i;
        ieee_putascii("LD");
        for (i = 0; i < LDPERLINE; i++) {
            ieee_putascii("%02X", buf[val++]);
            start++;
        }
        ieee_putascii(".\r\n");
    }
    /* if no partial lines */
    if (start == end)
        return (start);
    /* make a partial line */
    ieee_putascii("LD");
    while (start < end) {
        ieee_putascii("%02X", buf[val++]);
        start++;
    }
    ieee_putascii(".\r\n");
    return (start);
}
static long ieee_putlr(struct ieeeFixupp *p)
{
/*
 * To deal with the vagaries of segmentation the LADsoft linker
 * defines two types of segments: absolute and virtual.  Note that
 * 'absolute' in this context is a different thing from the IEEE
 * definition of an absolute segment type, which is also supported. If a
 * sement is linked in virtual mode the low limit (L-var) is
 * subtracted from each R,X, and P variable which appears in an
 * expression, so that we can have relative offsets.  Meanwhile
 * in the ABSOLUTE mode this subtraction is not done and
 * so we can use absolute offsets from 0.  In the LADsoft linker
 * this configuration is not done in the assemblker source but in
 * a source the linker reads.  Generally this type of thing only
 * becomes an issue if real mode code is used.  A pure 32-bit linker could
 * get away without defining the virtual mode...
 */
    char buf[40];
    long size = p->size;
    switch (p->ftype) {
    case FT_SEG:
        if (p->id1 < 0)
            sprintf(buf, "%lX", -p->id1);
        else
            sprintf(buf, "L%lX,10,/", p->id1);
        break;
    case FT_OFS:
        sprintf(buf, "R%lX,%lX,+", p->id1, p->addend);
        break;
    case FT_REL:
        sprintf(buf, "R%lX,%lX,+,P,-,%X,-", p->id1, p->addend, p->size);
        break;

    case FT_WRT:
        if (p->id2 < 0)
            sprintf(buf, "R%lX,%lX,+,L%lX,+,%lX,-", p->id2, p->addend,
                    p->id2, -p->id1 * 16);
        else
            sprintf(buf, "R%lX,%lX,+,L%lX,+,L%lX,-", p->id2, p->addend,
                    p->id2, p->id1);
        break;
    case FT_EXT:
        sprintf(buf, "X%lX", p->id1);
        break;
    case FT_EXTREL:
        sprintf(buf, "X%lX,P,-,%lX,-", p->id1, size);
        break;
    case FT_EXTSEG:
        /* We needed a non-ieee hack here.
         * We introduce the Y variable, which is the low
         * limit of the native segment the extern resides in
         */
        sprintf(buf, "Y%lX,10,/", p->id1);
        break;
    case FT_EXTWRT:
        if (p->id2 < 0)
            sprintf(buf, "X%lX,Y%lX,+,%lX,-", p->id2, p->id2,
                    -p->id1 * 16);
        else
            sprintf(buf, "X%lX,Y%lX,+,L%lX,-", p->id2, p->id2, p->id1);
        break;
    }
    ieee_putascii("LR(%s,%lX).\r\n", buf, size);

    return (size);
}

/* Dump all segment data (text and fixups )*/

static void ieee_unqualified_name(char *dest, char *source)
{
    if (ieee_uppercase) {
        while (*source)
            *dest++ = toupper(*source++);
        *dest = 0;
    } else
        strcpy(dest, source);
}
void dbgls_init(struct ofmt *of, void *id, FILE * fp, efunc error)
{
    int tempint;
    (void)of;
    (void)id;
    (void)fp;
    (void)error;

    fnhead = NULL;
    fntail = &fnhead;
    arrindex = ARRAY_BOT;
    arrhead = NULL;
    arrtail = &arrhead;
    ieee_segment("??LINE", 2, &tempint);
    any_segs = FALSE;
}
static void dbgls_cleanup(void)
{
    struct ieeeSection *segtmp;
    while (fnhead) {
        struct FileName *fntemp = fnhead;
        fnhead = fnhead->next;
        nasm_free(fntemp->name);
        nasm_free(fntemp);
    }
    for (segtmp = seghead; segtmp; segtmp = segtmp->next) {
        while (segtmp->lochead) {
            struct ieeePublic *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);
    }
}

/*
 * because this routine is not bracketed in
 * the main program, this routine will be called even if there
 * is no request for debug info
 * so, we have to make sure the ??LINE segment is avaialbe
 * as the first segment when this debug format is selected
 */
static void dbgls_linnum(const char *lnfname, long lineno, long segto)
{
    struct FileName *fn;
    struct ieeeSection *seg;
    int i = 0;
    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 != ieee_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 = fn->next) {
        if (!nasm_stricmp(lnfname, fn->name))
            break;
        i++;
    }
    if (!fn) {
        fn = nasm_malloc(sizeof(*fn));
        fn->name = nasm_malloc(strlen(lnfname) + 1);
        fn->index = i;
        strcpy(fn->name, lnfname);
        fn->next = NULL;
        *fntail = fn;
        fntail = &fn->next;
    }
    ieee_write_byte(seghead, fn->index);
    ieee_write_word(seghead, lineno);
    ieee_write_fixup(segto, NO_SEG, seghead, 4, OUT_ADDRESS,
                     seg->currentpos);

}
static void dbgls_deflabel(char *name, long segment,
                           long offset, int is_global, char *special)
{
    struct ieeeSection *seg;
    int used_special;           /* have we used the special text? */

    /* Keep compiler from warning about special and used_special */
    used_special = special ? FALSE : FALSE;

    /*
     * If it's a special-retry from pass two, discard it.
     */
    if (is_global == 3)
        return;

    /*
     * First check for the double-period, signifying something
     * unusual.
     */
    if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
        return;
    }

    /*
     * Case (i):
     */
    if (ieee_seg_needs_update)
        return;
    if (segment < SEG_ABS && segment != NO_SEG && segment % 2)
        return;

    if (segment >= SEG_ABS || segment == NO_SEG) {
        return;
    }

    /*
     * If `any_segs' is still FALSE, we might need to define a
     * default segment, if they're trying to declare a label in
     * `first_seg'.  But the label should exist due to a prior
     * call to ieee_deflabel so we can skip that.
     */

    for (seg = seghead; seg; seg = seg->next)
        if (seg->index == segment) {
            struct ieeePublic *loc;
            /*
             * Case (ii). Maybe MODPUB someday?
             */
            if (!is_global) {
                last_defined = loc = nasm_malloc(sizeof(*loc));
                *seg->loctail = loc;
                seg->loctail = &loc->next;
                loc->next = NULL;
                loc->name = nasm_strdup(name);
                loc->offset = offset;
                loc->segment = -1;
                loc->index = seg->ieee_index;
            }
        }
}
static void dbgls_typevalue(long type)
{
    int elem = TYM_ELEMENTS(type);
    type = TYM_TYPE(type);

    if (!last_defined)
        return;

    switch (type) {
    case TY_BYTE:
        last_defined->type = 1; /* unsigned char */
        break;
    case TY_WORD:
        last_defined->type = 3; /* unsigned word */
        break;
    case TY_DWORD:
        last_defined->type = 5; /* unsigned dword */
        break;
    case TY_FLOAT:
        last_defined->type = 9; /* float */
        break;
    case TY_QWORD:
        last_defined->type = 10;        /* qword */
        break;
    case TY_TBYTE:
        last_defined->type = 11;        /* TBYTE */
        break;
    default:
        last_defined->type = 0x10;      /* near label */
        break;
    }

    if (elem > 1) {
        struct Array *arrtmp = nasm_malloc(sizeof(*arrtmp));
        int vtype = last_defined->type;
        arrtmp->size = elem;
        arrtmp->basetype = vtype;
        arrtmp->next = NULL;
        last_defined->type = arrindex++ + 0x100;
        *arrtail = arrtmp;
        arrtail = &(arrtmp->next);
    }
    last_defined = NULL;
}
static void dbgls_output(int output_type, void *param)
{
    (void)output_type;
    (void)param;
}
static struct dfmt ladsoft_debug_form = {
    "LADsoft Debug Records",
    "ladsoft",
    dbgls_init,
    dbgls_linnum,
    dbgls_deflabel,
    null_debug_routine,
    dbgls_typevalue,
    dbgls_output,
    dbgls_cleanup,
};
static struct dfmt *ladsoft_debug_arr[3] = {
    &ladsoft_debug_form,
    &null_debug_form,
    NULL
};
struct ofmt of_ieee = {
    "IEEE-695 (LADsoft variant) object file format",
    "ieee",
    NULL,
    ladsoft_debug_arr,
    &null_debug_form,
    NULL,
    ieee_init,
    ieee_set_info,
    ieee_out,
    ieee_deflabel,
    ieee_segment,
    ieee_segbase,
    ieee_directive,
    ieee_filename,
    ieee_cleanup
};

#endif                          /* OF_IEEE */

⌨️ 快捷键说明

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