/* 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 };
|