/* asmutl.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 #include #include "asm86.h" #include "asmfcn.h" #include "asmctype.h" #include "asmindex.h" #include "asmmsg.h" extern char *fname; extern char hexchar[]; /* put a bunch of registers into the symbol table */ VOID initregs( struct mreg *makreg ){ register struct mreg *index; register char *p; char * savelbufp; savelbufp = lbufp; for (index = makreg; *index->nm; index++) { lbufp = index->nm; getatom(); if (symsearch()) /* register already defined */ errorn(E_RAD); symcreate( M_NOCREF | M_BACKREF | M_DEFINED, REGISTER); symptr->offset = index->val; symptr->symu.regsym.regtype = index->rt; symbolcnt--; } lbufp = savelbufp; } /*** scanorder - process symbol list in order * * scanorder (root, fcn); * * Entry root = root of symbol list * fcn = pointer to function to be executed * Exit none * Returns none * Calls */ #if !defined XENIX286 && !defined FLATMODEL # pragma alloc_text (FA_TEXT, scanorder) #endif VOID PASCAL scanorder ( SYMBOL FARSYM *root, SHORT (PASCAL *item) (SYMBOL FARSYM *) ){ register SYMBOL FARSYM *p; for (p = root; p; p = p->next) { symptr = p; (*item) (p); } } /*** scanSorted - process symbol sorted order * * Entry root = root of symbol list * fcn = pointer to function to be executed * Exit none * Returns none * Calls */ #if !defined XENIX286 && !defined FLATMODEL # pragma alloc_text (FA_TEXT, scanSorted) #endif VOID PASCAL scanSorted ( SYMBOL FARSYM *root, SHORT (PASCAL *item) (SYMBOL FARSYM *) ){ register SYMBOL FARSYM *p; for (p = root; p; p = p->alpha) { symptr = p; if (!(M_PASSED & p->attr)) (*item) (p); } } /*** assignemitsylinknum - assign link number * * assignlinknum (sym); * * Entry *sym = symbol * Exit * Returns * Calls * Note Turn off BACKREF and PASSED bits in symbol attributes and * if symbol is segment, group, public or external give it a * link dictionary number */ SHORT PASCAL assignlinknum ( register SYMBOL FARSYM *sym ){ switch (sym->symkind) { case MACRO: /* make symbol unknown at start of p2 */ case STRUC: case REC: sym->attr &= ~M_BACKREF; return 0; case SEGMENT: sym->symu.segmnt.lnameIndex = lnameIndex++; goto creatLname; case CLASS: sym->symu.ext.extIndex = lnameIndex++; goto creatLname; /* group indexs holds lname index temporary */ case GROUP: sym->symu.grupe.groupIndex = lnameIndex++; creatLname: emitlname (sym); } if (sym->symkind == REGISTER) sym->attr &= ~(M_PASSED); else sym->attr &= ~(M_PASSED | M_BACKREF); return 0; } /*** scansegment - output segment names * * scansegment (sym); * * Entry *sym = segment symbol chain * Exit * Returns * Calls */ VOID PASCAL scansegment ( register SYMBOL FARSYM *sym ){ if (sym->symu.segmnt.align == (char)-1) /* PARA default */ sym->symu.segmnt.align = 3; if (sym->symu.segmnt.combine == 7) /* Default no combine */ sym->symu.segmnt.combine = 0; sym->symu.segmnt.lastseg = NULL; /* Output segment def */ emitsegment (sym); /* Clear Offset( current segment PC ) for pass 2 */ sym->offset = 0; sym->symu.segmnt.seglen = 0; } /*** scangroup - output group names * * scangroup (sym); * * Entry *sym = group chain * Exit * Returns * Calls */ SHORT PASCAL scangroup ( SYMBOL FARSYM *sym ){ if (sym->symkind == GROUP) emitgroup (sym); return 0; } /*** scanextern - output external names * * scanextern (sym); * * Entry *sym = chain of external names * Exit * Returns * Calls */ SHORT PASCAL scanextern ( SYMBOL FARSYM *sym ){ if (M_XTERN & sym->attr) emitextern (sym); return 0; } /*** scanglobal - output global names * * scanglobal (sym); * * Entry *sym = chain of external names * Exit * Returns * Calls */ SHORT PASCAL scanglobal ( SYMBOL FARSYM *sym ){ if (M_GLOBAL & sym->attr) emitglobal (sym); return 0; } /*** dumpname - output module name * * dumpname (); * * Entry * Exit * Returns * Calls */ VOID PASCAL dumpname () { moduleflag = TRUE; /* put file name instead of the usual */ emodule(createname(fname)); } /*** showresults - display final assembly results * * showresults (fil, verbose, mbytes); * * Entry fil = file to print statistics to * verbose = TRUE if all statistics to be displayed * FALSE if only error messages to be displayed * mbytes = number of free bytes in symbol space * Exit statistics written to file * Returns none * Calls fprintf */ VOID PASCAL showresults ( FILE *fil, char verbose, char *pFreeBytes ){ if (verbose) { fprintf (fil, __NMSG_TEXT(ER_SOU), linessrc, linestot); fprintf (fil, __NMSG_TEXT(ER_SY2), symbolcnt); } fprintf (fil, pFreeBytes); fprintf (fil, "%7hd%s\n%7hd%s\n", warnnum, __NMSG_TEXT(ER_EM1), errornum, __NMSG_TEXT(ER_EM2)); #ifdef BUF_STATS if (verbose) { extern long DEBUGtl, DEBUGlb, DEBUGbp, DEBUGbl, DEBUGcs, DEBUGca; fprintf (fil, "\nTotal lines: %ld\n", DEBUGtl); fprintf (fil, "Lines buffered: %ld\n", DEBUGlb); fprintf (fil, "Stored as blank: %ld\n", DEBUGbl); fprintf (fil, "Bad lbufp: %ld\n", DEBUGbp); fprintf (fil, "Total Characters: %ld\n", DEBUGca); fprintf (fil, "Characters buffered: %ld\n", DEBUGcs); } #endif #ifdef EXPR_STATS if (verbose) { extern long cExpr, cHardExpr; fprintf(fil, "\nTotal Expressions(%ld), Simple(%ld): %hd%%\n", cExpr, cExpr - cHardExpr, (SHORT)((cExpr - cHardExpr)*100 / (cExpr+1))); } #endif } /*** resetobjidx - reset listindex to correct column * * resetobjidx (); * * Entry * Exit * Returns * Calls */ VOID PASCAL CODESIZE resetobjidx () { listindex = LSTDATA; if (!emittext && duplevel) listindex += 3 + ((duplevel <= 8)? duplevel: 8); if (highWord(pcoffset)) /* check for 32 bit listing */ listindex += 4; #ifdef BCBOPT if (fNotStored) storelinepb (); #endif listline (); linebuffer[0] = 0; } /*** copyascii - copy ASCII into list buffer * * copyascii (); * * Entry objectascii = data to be copied * listindex = position for copy * Exit * Returns * Calls */ VOID PASCAL CODESIZE copyascii () { register char *p2; register char *p1; if (listindex >= LSTMAX) resetobjidx (); if (!fNeedList) return; for (p1 = listbuffer + listindex, p2 = objectascii; *p2; ) *p1++ = *p2++; listindex = (char)(p1 - listbuffer); } /*** copystring - copy ASCII into list buffer * * copystring (); * * Entry objectascii = data to be copied * listindex = position for copy * Exit * Returns * Calls */ VOID PASCAL CODESIZE copystring ( register char *strng ){ register char *p1; if (!fNeedList || fSkipList) return; goto firstTime; while (*strng) { *p1++ = *strng++; if (*strng && ++listindex > LSTMAX + 2) { resetobjidx (); firstTime: listindex = 3; p1 = listbuffer + 3; } } } /*** copytext - copy two characters to text line * * copytext (chrs) * * Entry * Exit * Returns * Calls */ VOID PASCAL CODESIZE copytext ( char *chrs ){ if (listindex > LSTMAX+1) resetobjidx (); listbuffer[listindex++] = *chrs++; listbuffer[listindex++] = *chrs; } /*** pcdisplay - display program counter * * pcdisplay(); * * Entry pcoffset = value to display * Exit hex or octal value of pc interted in list buffer * Returns none * Calls copyascii, wordascii */ VOID PASCAL CODESIZE pcdisplay () { listindex = 1; if (!fNeedList) return; offsetAscii (pcoffset); copyascii (); listindex = LSTDATA; if (objectascii[4]) /* was a 32bit number */ listindex += 4; } /*** opdisplay - display program counter and opcode * * opdisplay(v); * * Entry v = opcode to display * Exit none * Returns none * Calls */ VOID PASCAL CODESIZE opdisplay ( UCHAR v ){ if (!fNeedList) return; if (listindex == 1) pcdisplay (); objectascii[1] = hexchar[v & 0xf]; objectascii[0] = hexchar[v >> 4]; objectascii[2] = 0; copyascii (); listindex++; } #ifndef M8086OPT /*** inset - check for value in a set of values * * flag = inset (val, set); * * Entry val = value to check * set = array of values to check for * set[0] = number of entries in set * Exit none * Returns TRUE if val is in set * FALSE if val is not in set * Calls */ char CODESIZE inset ( register char v, char *s ){ register USHORT i; register char *p; for (i = *s, p = ++s; i; i--) if (v == *p++) return (TRUE); return (FALSE); } #endif /* M8086OPT */ /*** outofmem - issue an out of memory error message * * outofmem (text); * * Entry *text = text to append to message * Exit doesn't * Returns none * Calls endblk, parse * Note if not end of PROC, parse line as normal. Otherwise, * terminate block. */ VOID PASCAL outofmem () { closeOpenFiles(); terminate((SHORT)((EX_MEME<<12) | ER_MEM), pFCBCur->fname, (char *)errorlineno, NULL ); } SHORT PASCAL CODESIZE tokenIS( char *pLiteral ){ return(_stricmp(naim.pszName, pLiteral) == 0); } #ifdef M8086 /*** strnfcpy - copy string to near buffer * * strnfcpy (dest, src); * * Entry dest = pointer to near buffer * src = pointer to far source buffer * Exit source copied to destination * Returns none * Calls none */ VOID PASCAL strnfcpy ( register char *dest, register char FAR *src ){ while(*src) *dest++ = *src++; *dest = NULL; } /*** strflen - compute length of far buffer * * strnflen (s1); * * Entry s1 = pointer to far buffer * Exit none * Returns number of characters in buffer * Calls none */ USHORT PASCAL strflen ( register char FAR *s1 ){ register USHORT i = 0; while (*s1++) i++; return(i); } #endif /* M8086 */