|
|
/* asmlst.c -- microsoft 80x86 assembler
** ** microsoft (r) macro assembler ** copyright (c) microsoft corp 1986. all rights reserved ** ** randy nevin ** ** 10/90 - Quick conversion to 32 bit by Jeff Spencer */
#include <stdio.h>
#include <string.h>
#include "asm86.h"
#include "asmfcn.h"
#include "asmctype.h"
#include "asmmsg.h"
#define setpassed(sym) (sym)->attr |= (M_PASSED)
VOID PASCAL CODESIZE listPuts(char *);
#ifdef BCBOPT
extern UCHAR fNoCompact; #endif
char fBigNum;
/* size names */
static char byte[] = "BYTE"; static char word[] = "WORD"; static char dword[] = "DWORD"; static char none[] = "NONE"; char hexchar[] = "0123456789ABCDEF";
char *siznm[] = { 0, byte, word, 0, dword, 0, "FWORD", 0, "QWORD", 0, "TBYTE", "NEAR", "FAR", };
char *alignName[] = { "AT", byte, word, "PARA", "PAGE", dword };
char *combineName[] = { none, "MEMORY", /* Memory is mapped to PUBLIC in fnspar */ "PUBLIC", 0, 0, "STACK", "COMMON", none };
char headSegment[] = "Segments and Groups:";
static char *head1[] = { headSegment, "Symbols: ", headSegment };
char headSeg[] = "\tSize\tLength\t Align\tCombine Class";
static char *head2[] = { &headSeg[5], "\tType\t Value\t Attr", headSeg };
/*** offsetAscii - display dword in hex
* * offsetAscii(v); * * Entry v = dword to be displayed * Exit objectascii = converted value of v zero terminated * Returns none * Calls */
VOID PASCAL offsetAscii ( OFFSET v ){ register USHORT t; register char *p = objectascii;
#ifdef V386
if (highWord(v)) {
t = highWord(v); p[3] = hexchar[t & 15]; t >>= 4; p[2] = hexchar[t & 15]; t >>= 4; p[1] = hexchar[t & 15]; t >>= 4; p[0] = hexchar[t & 15]; p += 4;
} #endif
p[4] = 0;
t = (USHORT)v; p[3] = hexchar[t & 15]; t >>= 4; p[2] = hexchar[t & 15]; t >>= 4; p[1] = hexchar[t & 15]; p[0] = hexchar[(t >> 4) & 15]; }
/*** dispsym - display symbol
* * routine (); * * Entry * Exit * Returns * Calls */
VOID PASCAL CODESIZE dispsym ( USHORT indent, SYMBOL FARSYM *sym ){ register char *p = listbuffer;
strcpy (p, " . . . . . . . . . . . . . . . . \t"); while (indent--) *p++ = ' '; if (caseflag == CASEX && (sym->attr & (M_GLOBAL | M_XTERN))) strcpy (p, sym->lcnamp->id); else STRNFCPY (p, sym->nampnt->id);
p[STRFLEN (sym->nampnt->id)] = ' '; listPuts (listbuffer); }
/*** dispword - display word value in current radix
* * dispword (v); * * Entry v = value to display * Exit * Returns * Calls */
VOID PASCAL CODESIZE dispword ( OFFSET v ){ /* Convert value to text */ offsetAscii (v); if (symptr->symkind == EQU && symptr->symu.equ.equrec.expr.esign) listPuts ("-");
listPuts(objectascii); fBigNum = objectascii[4]; /* remember if you put a 8 digit # */ }
/*** chkheading - display heading if needed
* * chkheading (code); * * Entry code = index to heading to be printed * Exit * Returns * Calls */
VOID PASCAL CODESIZE chkheading ( USHORT code ){ if (!listed && lsting) { if (pagelength - pageline < 8) pageheader (); else skipline (); listPuts (head1[code]); skipline (); skipline (); listPuts(" N a m e "); listPuts(head2[code]); skipline (); skipline (); listed = TRUE; } }
/*** disptab - output tab character to listing
* * disptab (); * * Entry * Exit * Returns * Calls */
VOID PASCAL CODESIZE disptab () { putc ((fBigNum)? ' ': '\t', lst.fil); fBigNum = FALSE; }
/*** skipline - output blank line
* * skipline (); * * Entry * Exit * Returns * Calls */
VOID PASCAL CODESIZE skipline () { fputs(NLINE, lst.fil); bumpline (); }
/*** bumpline - bump line count
* * bumpline (); * * Entry pageline = current line number * pagelength = number of lines per page * Exit pageline incremented * new page started if pageline > pagelength * Returns none * Calls pageheader */
VOID PASCAL bumpline () { pageline++; if (pagelength <= pageline) pageheader (); }
/*** newpage - start newpage
* * newpage (); * * Entry none * Exit pagemajor incremented * pageminor = 0 * pageline set to pagelength - 1 * Returns none * Calls none */
VOID PASCAL newpage () { pagemajor++; pageminor = 0; pageline = pagelength - 1; }
/*** pageheader - output page header
* * pageheader (); * * Entry * Exit * Returns * Calls */
VOID PASCAL pageheader () { if (lsting) { pageminor++; pageline = 4; #if defined MSDOS && !defined FLATMODEL
atime[20] = '\0'; /* get rid of '\n' */ #else
atime[24] = '\0'; /* get rid of '\n' */ #endif
fprintf (lst.fil, "\f\b%s%s" NLINE "%s", titlefn, atime + 4, titlebuf); if (pagemajor == 0) listPuts("Symbols"); else { fprintf (lst.fil, "Page %5hd", pagemajor); } if (pageminor) fprintf (lst.fil, "-%hd", pageminor);
fprintf (lst.fil, NLINE "%s" NLINE NLINE, subttlbuf); } }
/*** testlist - test for listing of line
* * testlist () * * Entry * Exit * Returns * Calls */
UCHAR PASCAL CODESIZE testlist () { if (fPass1Err) /* list pass 1 errors regardless of listing status */ return (TRUE);
if (pass2 || debug) {
if (errorcode) /* list error in pass 2 regardless of listing status */ return (TRUE);
if (fSkipList) { fSkipList = FALSE; return (FALSE); }
if (loption) return (TRUE);
/* list line in pass 1 or pass 2 if listing enabled */
if (listflag && (generate || condflag) && (!macrolevel || expandflag == LIST || !(expandflag == SUPPRESS || expandflag == LISTGEN && (listbuffer[1] == '=' || listbuffer[1] == ' ') && handler != HSTRUC)) )
return (TRUE);
} return (FALSE); }
/*** listline - list line on device for user
* * listline (); * * Entry listbuffer = object part of line * linebuffer = source line * crefcount = cross reference line count * Exit crefcount incremented * Returns none * Calls */
VOID PASCAL listline () { register char *p; char *q; char *r; register SHORT i; register SHORT j; register SHORT k;
#ifdef BCBOPT
if (errorcode) goodlbufp = FALSE; #endif
crefline ();
if (testlist ()) { if (listconsole || lsting) {
p = listbuffer + LISTMAX - 3;
#ifdef FEATURE
#ifdef BCBOPT
if (fNoCompact) #endif
*p++ = '\\';
else { if (pFCBCur->pFCBParent) *p++ = 'C'; if (macrolevel) *p = (macrolevel > 9)? '+': '0' + macrolevel; } #else
if (pFCBCur->pFCBParent) p[0] = 'C';
#ifdef BCBOPT
if (fNoCompact && *linebuffer) #else
if (*linebuffer) #endif
p[1] = '\\'; else if (macrolevel) p[1] = (macrolevel > 9)? '+': '0' + macrolevel; #endif
listbuffer [LISTMAX] = 0; } if (lsting) {
bumpline (); k = LISTMAX;
/** Put out line # * */ if (pass2 && crefing == CREF_SINGLE) { fprintf (lst.fil, "%8hd", crefcount+crefinc); k += 8; }
p = listbuffer; while (!memcmp(p," ",8)) { /* leading tabs */ putc('\t',lst.fil); p += 8; }
q = r = p + strlen(p) - 1; /* last char of p */ if (q >= p && *q == ' ') {
/* coalesce end spaces to tabs */ while (q != p && *(q - 1) == ' ') /* gather spaces */ q--;
/* now q points at the first trailing space and
* r points at the last trailing space */
*q = '\0'; listPuts(p); *q = ' '; i = (short)((q - p) & 7); /* residual = strlen MOD 8 */ j = 8 - i; /* filler to next tab stop */ if (j != 8 && j <= (r - q + 1)) { putc('\t',lst.fil); q += j; } while (r >= q + 7) { putc('\t',lst.fil); q += 8; } while (r >= q++) putc(' ',lst.fil); } else listPuts(p);
p = linebuffer; i = k; /* number of columns already put out */
while (*p) { while (*p && i < pagewidth) { if (*p == '\t') { if ((i = (((i+8)>>3)<<3)) >= pagewidth) /* won't fit */ break; } else i++;
putc(*p, lst.fil ); p++; }
if (*p) { skipline (); listPuts ( pass2 && crefing == CREF_SINGLE ? "\t\t\t\t\t" : "\t\t\t\t"); i = k; } } fputs(NLINE, lst.fil); } crefinc++;
if (errorcode) { if (listconsole) /* display line */ fprintf (ERRFILE,"%s%s\n", listbuffer, linebuffer); errordisplay (); }
} if (fNeedList) memset(listbuffer, ' ', LISTMAX);
errorcode = 0; fPass1Err = 0; }
/*** storetitle - copy text of line to title buffer
* * storetitle (buf) * * Entry buf = pointer to buffer to hold title * Exit up to TITLEWIDTH - 1 characters move to *buf* and *buf* blank * filled and zero terminated * Returns none * Calls none */
VOID PASCAL storetitle ( register char *buf ){ register SHORT L_count = 0;
for (; (L_count < TITLEWIDTH - 1); L_count++) { if (PEEKC () == 0) break; else *buf++ = NEXTC (); } /* skip to end of title */ while (PEEKC ()) SKIPC (); /* blank fill buffer */ for (; L_count < TITLEWIDTH - 1; L_count++) *buf++ = ' '; *buf = 0; }
/*** displength - display value as LENGTH = value
* * displength (v); * * Entry * Exit * Returns * Calls */
VOID PASCAL CODESIZE displength ( OFFSET v ){ offsetAscii (v); listPuts("\tLength = "); listPuts(objectascii); }
/*** dispdatasize - display data size
* * dispdatasize (sym); * * Entry *sym = symbol * Exit * Returns * Calls */
VOID PASCAL dispdatasize ( SYMBOL FARSYM *sym ){ register USHORT idx;
idx = sym->symtype;
if (idx == CLABEL && sym->symu.clabel.type > 514)
dispword((OFFSET) idx);
else{
if (idx == CSFAR) idx = 12;
else if (idx == CSNEAR) idx = 11;
else if (idx > 10 || siznm[idx] == NULL){ return; }
listPuts(siznm[idx]); } }
/*** listopen - list blocks open at end of pass
* * listopen (); * * Entry * Exit * Returns * Calls * Note Format is: * Open segments: <list> * Open procedures: <list> * Open conditionals: <n> */
VOID PASCAL listopen () { SYMBOL FARSYM *sym;
if (pcsegment) { if (!listquiet) fprintf (ERRFILE,"%s:", __NMSG_TEXT(ER_SEG)); if (lsting) { fprintf (lst.fil, "%s:", __NMSG_TEXT(ER_SEG)); bumpline (); skipline (); } sym = pcsegment; while (sym) { /* Count as an error */ if (pass2) errornum++; if (lsting) { dispsym (0, sym); skipline (); } if (!listquiet) { STRNFCPY (save, sym->nampnt->id); fprintf (ERRFILE," %s", save); } /* Point to previous seg */ sym = sym->symu.segmnt.lastseg; } if (!listquiet) fprintf (ERRFILE,"\n"); } if (iProcStack > 0) { if (!listquiet) fprintf (ERRFILE,"%s:", __NMSG_TEXT(ER_PRO)); if (lsting) { fprintf (lst.fil, "%s:", __NMSG_TEXT(ER_PRO)); bumpline (); skipline (); } while (iProcStack > 0) { sym = procStack[iProcStack--];
/* Count as an error */ if (pass2) errornum++; if (lsting) { dispsym (0, sym); skipline (); } if (!listquiet) { STRNFCPY (save, sym->nampnt->id); fprintf (ERRFILE," %s", save); } } if (!listquiet) fprintf (ERRFILE,"\n"); } if (condlevel) { /* Count as an error */ if (pass2) errornum++; if (!listquiet) fprintf (ERRFILE,"%s%hd\n", __NMSG_TEXT(ER_CON), condlevel); if (lsting) { fprintf (lst.fil, "%s%hd" NLINE, __NMSG_TEXT(ER_CON), condlevel); bumpline (); } } }
/*** symbollist - list symbol
* * symbollist (sym) * * Entry *sym = symbol * Exit count = number of symbols listed * Returns * Calls */
VOID PASCAL symbollist () { SYMBOL FARSYM *sym; SHORT i;
listed = FALSE;
for (i = 0; i < MAXCHR; i++) { count = 0;
for(sym = symroot[i]; sym; sym = sym->alpha)
if (!((M_NOCREF|M_PASSED) & sym->attr)) {
symptr = sym; count++; chkheading (1); setpassed (sym); dispsym (0, sym); dispstandard (sym);
if (sym->symkind == PROC) displength ((OFFSET) sym->symu.plabel.proclen);
else if (sym->length != 1 && (sym->symkind == DVAR || sym->symkind == CLABEL))
displength ((OFFSET) sym->length);
skipline (); }
if (count) skipline (); } }
/*** dispstandard - display standard
* * dispstandard (); * * Entry * Exit * Returns * Calls * Note Format is: * PROC: N/F PROC offset Segment * CLABEL L NEAR|FAR offset Segment * DVAR V SIZE offset Segment * REGISTR REG name */
VOID PASCAL CODESIZE dispstandard ( SYMBOL FARSYM *sym ){ NAME FAR *tp; register SHORT width; SHORT cbTM;
switch (sym->symkind) { case PROC: if (sym->symtype == CSNEAR) listPuts("N PROC"); else listPuts("F PROC"); break; case CLABEL: if (sym->symtype == CSNEAR) listPuts("L NEAR"); else if (sym->symtype == CSFAR) listPuts("L FAR "); else { fprintf (lst.fil, "L "); dispdatasize (sym); } break; case DVAR: /* Data associated label */ listPuts("V "); /**Display keyword or size * */ dispdatasize (sym); break; case REGISTER: listPuts("REG "); break; case EQU: if (sym->symu.equ.equtyp == EXPR) if (sym->symtype == 0) listPuts("NUMBER"); else dispdatasize (sym);
else if (sym->symu.equ.equtyp == ALIAS) { if (sym->symu.equ.equrec.alias.equptr) tp = sym->symu.equ.equrec.alias.equptr->nampnt; else tp = NULL; listPuts("ALIAS\t "); if (tp) { STRNFCPY (save, tp->id); listPuts(save); } } else { listPuts("TEXT "); cbTM = (SHORT) strlen(sym->symu.equ.equrec.txtmacro.equtext); width = pagewidth - 46; while (cbTM > width) { memcpy(save, sym->symu.equ.equrec.txtmacro.equtext, width); save[width] = 0; listPuts(save); skipline (); listPuts("\t\t\t\t\t "); sym->symu.equ.equrec.txtmacro.equtext += width; cbTM -= width; } listPuts(sym->symu.equ.equrec.txtmacro.equtext); } break; } disptab (); if ((sym->symkind != EQU) || (sym->symu.equ.equtyp == EXPR)) if (sym->symkind != REGISTER) dispword (((sym->attr & M_XTERN) && sym->offset)? (OFFSET) sym->length * sym->symtype: sym->offset); else { STRNFCPY (save, sym->nampnt->id); listPuts(save); } disptab (); if (sym->symsegptr) { STRNFCPY (save, sym->symsegptr->nampnt->id); listPuts(save); }
if (M_XTERN & sym->attr) listPuts((sym->symu.ext.commFlag)? "\tCommunal": "\tExternal");
if (M_GLOBAL & sym->attr) listPuts("\tGlobal"); }
/*** macrolist - list macro names and lengths
* * macrolist (sym); * * Entry *sym = macro symbol entry * Exit * Returns * Calls */
SHORT PASCAL macrolist ( SYMBOL FARSYM *sym ){ SHORT i; TEXTSTR FAR *p;
if (!(M_NOCREF & sym->attr)) { if (!listed) { listed = TRUE; /* # on line is 1 */ skipline (); listPuts("Macros:"); /** Display header * */ skipline (); skipline (); listPuts("\t\tN a m e\t\t\tLines"); skipline (); skipline (); } /* Display name of macro */ dispsym (0, sym); for (i = 0, p = sym->symu.rsmsym.rsmtype.rsmmac.macrotext; p; p = p->strnext, i++) ; fprintf (lst.fil, "%4hd", i); skipline (); setpassed (sym); } return 0; }
/*** struclist - display structure and record names
* * struclist (sym); * * Entry *sym = symbol * Exit * Returns * Calls * Note Format is: * <structure name> <length> <# fields> * <field name> <offset> * Or * <Record name> <width> <# fields> * <Field name> <offset> <width> <mask> <init> */
SHORT PASCAL struclist ( SYMBOL FARSYM *sym ){ char f32bit;
if (!(M_NOCREF & sym->attr)) { if (!listed) { listed = TRUE; if (pagelength - pageline < 8) pageheader (); else skipline (); listPuts("Structures and Records:"); skipline (); skipline (); listPuts(" N a m e Width # fields"); skipline (); listPuts(" Shift Width Mask Initial"); skipline (); skipline (); } setpassed (sym); /* Display name */ dispsym (0, sym); if (sym->symkind == REC) { /* # bits in record */ dispword ((OFFSET) sym->length); disptab (); /* # of fields */ dispword ((OFFSET) sym->symu.rsmsym.rsmtype.rsmrec.recfldnum); } else { /* Length of structure */ dispword ((OFFSET) sym->symtype); disptab (); /* # of fields */ dispword ((OFFSET) sym->symu.rsmsym.rsmtype.rsmstruc.strucfldnum); } skipline (); if (sym->symkind == REC) { #ifdef V386
f32bit = (symptr->length > 16); #endif
/* Point to 1st rec */ symptr = symptr->symu.rsmsym.rsmtype.rsmrec.reclist; while (symptr) {
dispsym (2, symptr);
/* Shift count */ dispword (symptr->offset); disptab ();
/* Width */ dispword ((OFFSET) symptr->symu.rec.recwid); disptab ();
/* Mask */ #ifdef V386
if (f32bit && symptr->symu.rec.recmsk <= 0xffff) dispword((OFFSET) 0); #endif
dispword (symptr->symu.rec.recmsk); disptab ();
/* Initial value */ #ifdef V386
if (f32bit && symptr->symu.rec.recinit <= 0xffff) dispword((OFFSET) 0); #endif
dispword (symptr->symu.rec.recinit);
skipline (); setpassed (sym); symptr = symptr->symu.rec.recnxt; } } else { /* Point to 1st field */ symptr = symptr->symu.rsmsym.rsmtype.rsmstruc.struclist; while (symptr) { dispsym (2, symptr); /* offset from start */ dispword (symptr->offset); skipline (); setpassed (symptr); symptr = symptr->symu.struk.strucnxt; } } } return 0; }
/* output a string to the listing file */
VOID PASCAL CODESIZE listPuts( char *pString ){ fputs(pString, lst.fil); }
/*** segdisplay - display segment name, size, align, combine and class
* * segdisplay (); * * Entry * Exit * Returns * Calls */
VOID PASCAL CODESIZE segdisplay ( USHORT indent, SYMBOL FARSYM *sym ){
dispsym (indent, sym);
#ifdef V386
if (f386already){ listPuts((sym->symu.segmnt.use32 == 4)? "32": "16"); listPuts(" Bit\t"); } #endif
/* Length of segment */ dispword (sym->symu.segmnt.seglen); disptab (); listPuts (alignName[sym->symu.segmnt.align]); disptab ();
if (sym->symu.segmnt.align == 0 && sym->symu.segmnt.combine == 0)
dispword ((OFFSET) sym->symu.segmnt.locate); else listPuts (combineName[sym->symu.segmnt.combine]);
disptab (); if (sym->symu.segmnt.classptr) { /* Have class name */ setpassed (sym->symu.segmnt.classptr);
#ifdef XENIX286
fputc('\'', lst.fil); farPuts(lst.fil, sym->symu.segmnt.classptr->nampnt->id); fputc('\'', lst.fil); #else
# ifdef FLATMODEL
fprintf (lst.fil, "\'%s\'", # else
fprintf (lst.fil, "\'%Fs\'", # endif
sym->symu.segmnt.classptr->nampnt->id); #endif
} setpassed (sym); skipline (); }
/*** seglist - list segment
* * seglist (sym); * * Entry * Exit * Returns * Calls * Note Format is: * <Group name> <# segments> * <segment> <size> <align> <combine> <class> * Or * <segment> <size> <align> <combine> <class> */
VOID PASCAL seglist () { SYMBOL FARSYM *sym; SHORT i;
listed = FALSE;
for (i = 0; i < MAXCHR; i++) {
for(sym = symroot[i]; sym; sym = sym->alpha)
if (1 << sym->symkind & (M_SEGMENT | M_GROUP) && !((M_NOCREF|M_PASSED) & sym->attr)) { #ifdef V386
chkheading ((USHORT) ((f386already)? 2: 0) ); #else
chkheading (0); #endif
symptr = sym; setpassed (sym); if (sym->symkind == SEGMENT) { if (!sym->symu.segmnt.grouptr) /*Display segment */ segdisplay (0, sym); } else { /* Display group name */ dispsym (0, sym); listPuts ("GROUP" NLINE); bumpline (); bumpline (); /* Point to 1st seg */ symptr = sym->symu.grupe.segptr; while (symptr) { segdisplay (2, symptr); symptr = symptr->symu.segmnt.nxtseg; } } } } }
|