Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

623 lines
9.8 KiB

  1. /* asmutl.c -- microsoft 80x86 assembler
  2. **
  3. ** microsoft (r) macro assembler
  4. ** copyright (c) microsoft corp 1986. all rights reserved
  5. **
  6. ** randy nevin
  7. **
  8. ** 10/90 - Quick conversion to 32 bit by Jeff Spencer
  9. */
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include "asm86.h"
  13. #include "asmfcn.h"
  14. #include "asmctype.h"
  15. #include "asmindex.h"
  16. #include "asmmsg.h"
  17. extern char *fname;
  18. extern char hexchar[];
  19. /* put a bunch of registers into the symbol table */
  20. VOID initregs(
  21. struct mreg *makreg
  22. ){
  23. register struct mreg *index;
  24. register char *p;
  25. char * savelbufp;
  26. savelbufp = lbufp;
  27. for (index = makreg; *index->nm; index++)
  28. {
  29. lbufp = index->nm;
  30. getatom();
  31. if (symsearch())
  32. /* register already defined */
  33. errorn(E_RAD);
  34. symcreate( M_NOCREF | M_BACKREF | M_DEFINED, REGISTER);
  35. symptr->offset = index->val;
  36. symptr->symu.regsym.regtype = index->rt;
  37. symbolcnt--;
  38. }
  39. lbufp = savelbufp;
  40. }
  41. /*** scanorder - process symbol list in order
  42. *
  43. * scanorder (root, fcn);
  44. *
  45. * Entry root = root of symbol list
  46. * fcn = pointer to function to be executed
  47. * Exit none
  48. * Returns none
  49. * Calls
  50. */
  51. #if !defined XENIX286 && !defined FLATMODEL
  52. # pragma alloc_text (FA_TEXT, scanorder)
  53. #endif
  54. VOID PASCAL
  55. scanorder (
  56. SYMBOL FARSYM *root,
  57. SHORT (PASCAL *item) (SYMBOL FARSYM *)
  58. ){
  59. register SYMBOL FARSYM *p;
  60. for (p = root; p; p = p->next) {
  61. symptr = p;
  62. (*item) (p);
  63. }
  64. }
  65. /*** scanSorted - process symbol sorted order
  66. *
  67. * Entry root = root of symbol list
  68. * fcn = pointer to function to be executed
  69. * Exit none
  70. * Returns none
  71. * Calls
  72. */
  73. #if !defined XENIX286 && !defined FLATMODEL
  74. # pragma alloc_text (FA_TEXT, scanSorted)
  75. #endif
  76. VOID PASCAL
  77. scanSorted (
  78. SYMBOL FARSYM *root,
  79. SHORT (PASCAL *item) (SYMBOL FARSYM *)
  80. ){
  81. register SYMBOL FARSYM *p;
  82. for (p = root; p; p = p->alpha) {
  83. symptr = p;
  84. if (!(M_PASSED & p->attr))
  85. (*item) (p);
  86. }
  87. }
  88. /*** assignemitsylinknum - assign link number
  89. *
  90. * assignlinknum (sym);
  91. *
  92. * Entry *sym = symbol
  93. * Exit
  94. * Returns
  95. * Calls
  96. * Note Turn off BACKREF and PASSED bits in symbol attributes and
  97. * if symbol is segment, group, public or external give it a
  98. * link dictionary number
  99. */
  100. SHORT PASCAL
  101. assignlinknum (
  102. register SYMBOL FARSYM *sym
  103. ){
  104. switch (sym->symkind) {
  105. case MACRO: /* make symbol unknown at start of p2 */
  106. case STRUC:
  107. case REC:
  108. sym->attr &= ~M_BACKREF;
  109. return 0;
  110. case SEGMENT:
  111. sym->symu.segmnt.lnameIndex = lnameIndex++;
  112. goto creatLname;
  113. case CLASS:
  114. sym->symu.ext.extIndex = lnameIndex++;
  115. goto creatLname;
  116. /* group indexs holds lname index temporary */
  117. case GROUP:
  118. sym->symu.grupe.groupIndex = lnameIndex++;
  119. creatLname:
  120. emitlname (sym);
  121. }
  122. if (sym->symkind == REGISTER)
  123. sym->attr &= ~(M_PASSED);
  124. else
  125. sym->attr &= ~(M_PASSED | M_BACKREF);
  126. return 0;
  127. }
  128. /*** scansegment - output segment names
  129. *
  130. * scansegment (sym);
  131. *
  132. * Entry *sym = segment symbol chain
  133. * Exit
  134. * Returns
  135. * Calls
  136. */
  137. VOID PASCAL
  138. scansegment (
  139. register SYMBOL FARSYM *sym
  140. ){
  141. if (sym->symu.segmnt.align == (char)-1)
  142. /* PARA default */
  143. sym->symu.segmnt.align = 3;
  144. if (sym->symu.segmnt.combine == 7)
  145. /* Default no combine */
  146. sym->symu.segmnt.combine = 0;
  147. sym->symu.segmnt.lastseg = NULL;
  148. /* Output segment def */
  149. emitsegment (sym);
  150. /* Clear Offset( current segment PC ) for pass 2 */
  151. sym->offset = 0;
  152. sym->symu.segmnt.seglen = 0;
  153. }
  154. /*** scangroup - output group names
  155. *
  156. * scangroup (sym);
  157. *
  158. * Entry *sym = group chain
  159. * Exit
  160. * Returns
  161. * Calls
  162. */
  163. SHORT PASCAL
  164. scangroup (
  165. SYMBOL FARSYM *sym
  166. ){
  167. if (sym->symkind == GROUP)
  168. emitgroup (sym);
  169. return 0;
  170. }
  171. /*** scanextern - output external names
  172. *
  173. * scanextern (sym);
  174. *
  175. * Entry *sym = chain of external names
  176. * Exit
  177. * Returns
  178. * Calls
  179. */
  180. SHORT PASCAL
  181. scanextern (
  182. SYMBOL FARSYM *sym
  183. ){
  184. if (M_XTERN & sym->attr)
  185. emitextern (sym);
  186. return 0;
  187. }
  188. /*** scanglobal - output global names
  189. *
  190. * scanglobal (sym);
  191. *
  192. * Entry *sym = chain of external names
  193. * Exit
  194. * Returns
  195. * Calls
  196. */
  197. SHORT PASCAL
  198. scanglobal (
  199. SYMBOL FARSYM *sym
  200. ){
  201. if (M_GLOBAL & sym->attr)
  202. emitglobal (sym);
  203. return 0;
  204. }
  205. /*** dumpname - output module name
  206. *
  207. * dumpname ();
  208. *
  209. * Entry
  210. * Exit
  211. * Returns
  212. * Calls
  213. */
  214. VOID PASCAL
  215. dumpname ()
  216. {
  217. moduleflag = TRUE;
  218. /* put file name instead of the usual */
  219. emodule(createname(fname));
  220. }
  221. /*** showresults - display final assembly results
  222. *
  223. * showresults (fil, verbose, mbytes);
  224. *
  225. * Entry fil = file to print statistics to
  226. * verbose = TRUE if all statistics to be displayed
  227. * FALSE if only error messages to be displayed
  228. * mbytes = number of free bytes in symbol space
  229. * Exit statistics written to file
  230. * Returns none
  231. * Calls fprintf
  232. */
  233. VOID PASCAL
  234. showresults (
  235. FILE *fil,
  236. char verbose,
  237. char *pFreeBytes
  238. ){
  239. if (verbose) {
  240. fprintf (fil, __NMSG_TEXT(ER_SOU), linessrc, linestot);
  241. fprintf (fil, __NMSG_TEXT(ER_SY2), symbolcnt);
  242. }
  243. fprintf (fil, pFreeBytes);
  244. fprintf (fil, "%7hd%s\n%7hd%s\n",
  245. warnnum, __NMSG_TEXT(ER_EM1),
  246. errornum, __NMSG_TEXT(ER_EM2));
  247. #ifdef BUF_STATS
  248. if (verbose) {
  249. extern long DEBUGtl, DEBUGlb, DEBUGbp, DEBUGbl, DEBUGcs, DEBUGca;
  250. fprintf (fil, "\nTotal lines: %ld\n", DEBUGtl);
  251. fprintf (fil, "Lines buffered: %ld\n", DEBUGlb);
  252. fprintf (fil, "Stored as blank: %ld\n", DEBUGbl);
  253. fprintf (fil, "Bad lbufp: %ld\n", DEBUGbp);
  254. fprintf (fil, "Total Characters: %ld\n", DEBUGca);
  255. fprintf (fil, "Characters buffered: %ld\n", DEBUGcs);
  256. }
  257. #endif
  258. #ifdef EXPR_STATS
  259. if (verbose) {
  260. extern long cExpr, cHardExpr;
  261. fprintf(fil, "\nTotal Expressions(%ld), Simple(%ld): %hd%%\n",
  262. cExpr, cExpr - cHardExpr, (SHORT)((cExpr - cHardExpr)*100 / (cExpr+1)));
  263. }
  264. #endif
  265. }
  266. /*** resetobjidx - reset listindex to correct column
  267. *
  268. * resetobjidx ();
  269. *
  270. * Entry
  271. * Exit
  272. * Returns
  273. * Calls
  274. */
  275. VOID PASCAL CODESIZE
  276. resetobjidx ()
  277. {
  278. listindex = LSTDATA;
  279. if (!emittext && duplevel)
  280. listindex += 3 + ((duplevel <= 8)? duplevel: 8);
  281. if (highWord(pcoffset)) /* check for 32 bit listing */
  282. listindex += 4;
  283. #ifdef BCBOPT
  284. if (fNotStored)
  285. storelinepb ();
  286. #endif
  287. listline ();
  288. linebuffer[0] = 0;
  289. }
  290. /*** copyascii - copy ASCII into list buffer
  291. *
  292. * copyascii ();
  293. *
  294. * Entry objectascii = data to be copied
  295. * listindex = position for copy
  296. * Exit
  297. * Returns
  298. * Calls
  299. */
  300. VOID PASCAL CODESIZE
  301. copyascii ()
  302. {
  303. register char *p2;
  304. register char *p1;
  305. if (listindex >= LSTMAX)
  306. resetobjidx ();
  307. if (!fNeedList)
  308. return;
  309. for (p1 = listbuffer + listindex, p2 = objectascii; *p2; )
  310. *p1++ = *p2++;
  311. listindex = (char)(p1 - listbuffer);
  312. }
  313. /*** copystring - copy ASCII into list buffer
  314. *
  315. * copystring ();
  316. *
  317. * Entry objectascii = data to be copied
  318. * listindex = position for copy
  319. * Exit
  320. * Returns
  321. * Calls
  322. */
  323. VOID PASCAL CODESIZE
  324. copystring (
  325. register char *strng
  326. ){
  327. register char *p1;
  328. if (!fNeedList || fSkipList)
  329. return;
  330. goto firstTime;
  331. while (*strng) {
  332. *p1++ = *strng++;
  333. if (*strng && ++listindex > LSTMAX + 2) {
  334. resetobjidx ();
  335. firstTime:
  336. listindex = 3;
  337. p1 = listbuffer + 3;
  338. }
  339. }
  340. }
  341. /*** copytext - copy two characters to text line
  342. *
  343. * copytext (chrs)
  344. *
  345. * Entry
  346. * Exit
  347. * Returns
  348. * Calls
  349. */
  350. VOID PASCAL CODESIZE
  351. copytext (
  352. char *chrs
  353. ){
  354. if (listindex > LSTMAX+1)
  355. resetobjidx ();
  356. listbuffer[listindex++] = *chrs++;
  357. listbuffer[listindex++] = *chrs;
  358. }
  359. /*** pcdisplay - display program counter
  360. *
  361. * pcdisplay();
  362. *
  363. * Entry pcoffset = value to display
  364. * Exit hex or octal value of pc interted in list buffer
  365. * Returns none
  366. * Calls copyascii, wordascii
  367. */
  368. VOID PASCAL CODESIZE
  369. pcdisplay ()
  370. {
  371. listindex = 1;
  372. if (!fNeedList)
  373. return;
  374. offsetAscii (pcoffset);
  375. copyascii ();
  376. listindex = LSTDATA;
  377. if (objectascii[4]) /* was a 32bit number */
  378. listindex += 4;
  379. }
  380. /*** opdisplay - display program counter and opcode
  381. *
  382. * opdisplay(v);
  383. *
  384. * Entry v = opcode to display
  385. * Exit none
  386. * Returns none
  387. * Calls
  388. */
  389. VOID PASCAL CODESIZE
  390. opdisplay (
  391. UCHAR v
  392. ){
  393. if (!fNeedList)
  394. return;
  395. if (listindex == 1)
  396. pcdisplay ();
  397. objectascii[1] = hexchar[v & 0xf];
  398. objectascii[0] = hexchar[v >> 4];
  399. objectascii[2] = 0;
  400. copyascii ();
  401. listindex++;
  402. }
  403. #ifndef M8086OPT
  404. /*** inset - check for value in a set of values
  405. *
  406. * flag = inset (val, set);
  407. *
  408. * Entry val = value to check
  409. * set = array of values to check for
  410. * set[0] = number of entries in set
  411. * Exit none
  412. * Returns TRUE if val is in set
  413. * FALSE if val is not in set
  414. * Calls
  415. */
  416. char CODESIZE
  417. inset (
  418. register char v,
  419. char *s
  420. ){
  421. register USHORT i;
  422. register char *p;
  423. for (i = *s, p = ++s; i; i--)
  424. if (v == *p++)
  425. return (TRUE);
  426. return (FALSE);
  427. }
  428. #endif /* M8086OPT */
  429. /*** outofmem - issue an out of memory error message
  430. *
  431. * outofmem (text);
  432. *
  433. * Entry *text = text to append to message
  434. * Exit doesn't
  435. * Returns none
  436. * Calls endblk, parse
  437. * Note if not end of PROC, parse line as normal. Otherwise,
  438. * terminate block.
  439. */
  440. VOID PASCAL
  441. outofmem ()
  442. {
  443. closeOpenFiles();
  444. terminate((SHORT)((EX_MEME<<12) | ER_MEM), pFCBCur->fname, (char *)errorlineno, NULL );
  445. }
  446. SHORT PASCAL CODESIZE
  447. tokenIS(
  448. char *pLiteral
  449. ){
  450. return(_stricmp(naim.pszName, pLiteral) == 0);
  451. }
  452. #ifdef M8086
  453. /*** strnfcpy - copy string to near buffer
  454. *
  455. * strnfcpy (dest, src);
  456. *
  457. * Entry dest = pointer to near buffer
  458. * src = pointer to far source buffer
  459. * Exit source copied to destination
  460. * Returns none
  461. * Calls none
  462. */
  463. VOID PASCAL
  464. strnfcpy (
  465. register char *dest,
  466. register char FAR *src
  467. ){
  468. while(*src)
  469. *dest++ = *src++;
  470. *dest = NULL;
  471. }
  472. /*** strflen - compute length of far buffer
  473. *
  474. * strnflen (s1);
  475. *
  476. * Entry s1 = pointer to far buffer
  477. * Exit none
  478. * Returns number of characters in buffer
  479. * Calls none
  480. */
  481. USHORT PASCAL
  482. strflen (
  483. register char FAR *s1
  484. ){
  485. register USHORT i = 0;
  486. while (*s1++)
  487. i++;
  488. return(i);
  489. }
  490. #endif /* M8086 */