Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1286040
  • 博文数量: 196
  • 博客积分: 4141
  • 博客等级: 中将
  • 技术积分: 2253
  • 用 户 组: 普通用户
  • 注册时间: 2009-03-21 20:04
文章存档

2019年(31)

2016年(1)

2014年(16)

2011年(8)

2010年(25)

2009年(115)

分类:

2009-03-22 12:28:30

/* listing.c listing file generator for the Netwide Assembler
 *
 * 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.
 *
 * initial version 2/vii/97 by Simon Tatham
 */


#include
#include
#include
#include
#include

#include "nasm.h"
#include "nasmlib.h"
#include "listing.h"

/* listing file */

#define LIST_MAX_LEN 216 /* something sensible */
#define LIST_INDENT 40
#define LIST_HEXBIT 18

typedef struct MacroInhibit MacroInhibit;

/* 采用后进先出的栈的形式 */
static struct MacroInhibit {
    MacroInhibit *next;
    int level; /* 宏嵌套层次 */
    int inhibiting; /* 禁止该宏扩展 */
} *mistack;

static char xdigit[] = "0123456789ABCDEF";

#define HEX(a,b) (*(a)=xdigit[((b)>>4)&15],(a)[1]=xdigit[(b)&15]); /* 将一个 char 类型的数据转换成十六进制数 */

static char listline[LIST_MAX_LEN]; /* 存放源文件代码 */
static int listlinep; /* 相当于布尔值,判断是否要输出源代码 */

static char listdata[2 * LIST_INDENT]; /* we need less than that actually */ /* 存放机器代码 */
static long listoffset;

static long listlineno; /* 行号 */

static long listp; /* 貌似没有起作用 */

static int suppress; /* for INCBIN & TIMES special cases */

static int listlevel, listlevel_e; /* 嵌套层次 */

static FILE *listfp;

/* 输出到 *.lst 文件中,及其格式定位 */
static void list_emit(void)
{
    if (!listlinep && !listdata[0])
        return;

    /* 输出行号 */
    fprintf(listfp, "%6ld ", ++listlineno);

    /* 输出 listdata 数据,存放的是机器码 */
    if (listdata[0])
        fprintf(listfp, "%08lX %-*s", listoffset, LIST_HEXBIT + 1, listdata);
    else
        fprintf(listfp, "%*s", LIST_HEXBIT + 10, "");

    /* 显示嵌套的层次 */
    if (listlevel_e)
        fprintf(listfp, "%s<%d>", (listlevel < 10 ? " " : ""), listlevel_e);
    else if (listlinep)
        fprintf(listfp, " ");

    /* listlinep存放的是源文件的代码 */
    if (listlinep)
        fprintf(listfp, " %s", listline);

    fputc('\n', listfp);
    listlinep = FALSE;
    listdata[0] = '\0';
}

/*
 * fname: listing filename
 * error: error file
 */

static void list_init(char *fname, efunc error)
{
    listfp = fopen(fname, "w"); /* listing file */
    if (!listfp) {
        error(ERR_NONFATAL, "unable to open listing file `%s'", fname);
        return;
    }

    *listline = '\0';
    listlineno = 0;
    listp = TRUE;
    listlevel = 0;
    suppress = 0;
    mistack = nasm_malloc(sizeof(MacroInhibit));
    mistack->next = NULL;
    mistack->level = 0;
    mistack->inhibiting = TRUE;
}

static void list_cleanup(void)
{
    if (!listp)
        return;

    /* 摧毁链表 */
    while (mistack) {
        MacroInhibit *temp = mistack;
        mistack = temp->next;
        nasm_free(temp);
    }

    list_emit(); /* 保证没有遗留数据 */
    fclose(listfp);
}

/* 将 str 的数据存放到 listdata 中 */
static void list_out(long offset, char *str)
{
    /* 如果 listdata 存放不下,就先输出 listdata 中的数据 */
    if (strlen(listdata) + strlen(str) > LIST_HEXBIT) {
        strcat(listdata, "-");
        list_emit();
    }
    if (!listdata[0])
        listoffset = offset;
    strcat(listdata, str);
}

/*
 *将大小是 type & OUT_SIZMASK 的二进制代码存放进来listdata
 *
 *[ ]: 包含绝对地址
 *( ): 包含可重定位地址
 *type: 高4位显示类型,低32 - 4 = 28位是大小(貌似)
 */

static void list_output(long offset, const void *data, unsigned long type)
{
    unsigned long typ, size;

    if (!listp || suppress || user_nolist) /* fbk - 9/2/00 */
        return;

    typ = type & OUT_TYPMASK; /* 获取类型 */
    size = type & OUT_SIZMASK; /* 获取大小 */

    if (typ == OUT_RAWDATA) {
        unsigned char const *p = data;
        char q[3];
        while (size--) {
            HEX(q, *p);
            q[2] = '\0';
            list_out(offset++, q);
            p++;
        }
    } else if (typ == OUT_ADDRESS) {
        unsigned long d = *(long *)data;
        char q[11];
        unsigned char p[4], *r = p;
        if (size == 4) {
            q[0] = '[';
            q[9] = ']';
            q[10] = '\0';
            WRITELONG(r, d);
            HEX(q + 1, p[0]);
            HEX(q + 3, p[1]);
            HEX(q + 5, p[2]);
            HEX(q + 7, p[3]);
            list_out(offset, q);
        } else {
            q[0] = '[';
            q[5] = ']';
            q[6] = '\0';
            WRITESHORT(r, d);
            HEX(q + 1, p[0]);
            HEX(q + 3, p[1]);
            list_out(offset, q);
        }
    } else if (typ == OUT_REL2ADR) {
        unsigned long d = *(long *)data;
        char q[11];
        unsigned char p[4], *r = p;
        q[0] = '(';
        q[5] = ')';
        q[6] = '\0';
        WRITESHORT(r, d);
        HEX(q + 1, p[0]);
        HEX(q + 3, p[1]);
        list_out(offset, q);
    } else if (typ == OUT_REL4ADR) {
        unsigned long d = *(long *)data;
        char q[11];
        unsigned char p[4], *r = p;
        q[0] = '(';
        q[9] = ')';
        q[10] = '\0';
        WRITELONG(r, d);
        HEX(q + 1, p[0]);
        HEX(q + 3, p[1]);
        HEX(q + 5, p[2]);
        HEX(q + 7, p[3]);
        list_out(offset, q);
    } else if (typ == OUT_RESERVE) {
        char q[20];
        snprintf(q, sizeof(q), "", size);
        list_out(offset, q);
    }
}

/* 输入源代码 */
static void list_line(int type, char *line)
{
    if (!listp)
        return;
    if (user_nolist) { /* fbk - 9/2/00 */
        listlineno++; /* 如果在源代码中关闭 listing file 功能是,到达这里(实现该功能的汇编伪指令:[list -/+]) */
        return;
    }

    if (mistack && mistack->inhibiting) {
        if (type == LIST_MACRO)
            return;
        else { /* pop the mistack */
            MacroInhibit *temp = mistack;
            mistack = temp->next;
            nasm_free(temp);
        }
    }
    list_emit();
    listlinep = TRUE;
    strncpy(listline, line, LIST_MAX_LEN - 1);
    listline[LIST_MAX_LEN - 1] = '\0';
    listlevel_e = listlevel;
}

static void list_uplevel(int type)
{
    if (!listp)
        return;
    if (type == LIST_INCBIN || type == LIST_TIMES) {
        suppress |= (type == LIST_INCBIN ? 1 : 2);
        list_out(listoffset, type == LIST_INCBIN ? "" : "");
        return;
    }

    listlevel++;

    /*
     * 感觉下面代码有点冗余了
     * 插入一个 MacroInhibit 实例
     */

    if (mistack && mistack->inhibiting && type == LIST_INCLUDE) {
        MacroInhibit *temp = nasm_malloc(sizeof(MacroInhibit));
        temp->next = mistack;
        temp->level = listlevel;
        temp->inhibiting = FALSE;
        mistack = temp;
    } else if (type == LIST_MACRO_NOLIST) {
        MacroInhibit *temp = nasm_malloc(sizeof(MacroInhibit));
        temp->next = mistack;
        temp->level = listlevel;
        temp->inhibiting = TRUE;
        mistack = temp;
    }
}

static void list_downlevel(int type)
{
    if (!listp)
        return;

    if (type == LIST_INCBIN || type == LIST_TIMES) {
        suppress &= ~(type == LIST_INCBIN ? 1 : 2);
        return;
    }

    /* 删除 MacroInhibit 实例 */
    listlevel--;
    while (mistack && mistack->level > listlevel) {
        MacroInhibit *temp = mistack;
        mistack = temp->next;
        nasm_free(temp);
    }
}

ListGen nasmlist = {
    list_init,
    list_cleanup,
    list_output,
    list_line,
    list_uplevel,
    list_downlevel
};
 

阅读(2287) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~