|
|
1.1 ! root 1: /* ! 2: * Segmented assembler. ! 3: * Segmented assemblers are much ! 4: * more of a pain then non segmented ! 5: * ones. Here we try to make them ! 6: * easy to use, at the expense of ! 7: * driving the implementor absolutely ! 8: * crazy. ! 9: */ ! 10: #include "asm.h" ! 11: ! 12: main(argc, argv) ! 13: char *argv[]; ! 14: { ! 15: register char *p; ! 16: register c, i; ! 17: char *sfn; ! 18: int nfile, sfx; ! 19: static char copen[] = "%s: cannot open.\n"; ! 20: ! 21: nfile = argc-1; ! 22: efp = stdout; ! 23: for (i=1; i<argc; ++i) { ! 24: p = argv[i]; ! 25: if (*p == '-') { ! 26: argv[i] = NULL; ! 27: --nfile; ! 28: ++p; ! 29: while (c = *p++) { ! 30: switch(c) { ! 31: ! 32: case 'g': ! 33: ++gflag; ! 34: break; ! 35: ! 36: case 'l': ! 37: ++lflag; ! 38: efp = stderr; ! 39: break; ! 40: ! 41: case 'o': ! 42: if (++i >= argc) ! 43: usage(); ! 44: ofn = argv[i]; ! 45: argv[i] = NULL; ! 46: --nfile; ! 47: break; ! 48: case 'x': ! 49: ++xflag; ! 50: break; ! 51: ! 52: default: ! 53: usage(); ! 54: } ! 55: } ! 56: } ! 57: } ! 58: if (nfile == 0) ! 59: usage(); ! 60: #if CPM ! 61: ofp = fopen(ofn, "wb"); ! 62: #else ! 63: ofp = fopen(ofn, "w"); ! 64: #if !INTEL ! 65: if (ofp != NULL) ! 66: ofp = freopen(ofn, "r+w", ofp); ! 67: #endif ! 68: #endif ! 69: if (ofp == NULL) { ! 70: fprintf(stderr, "%s: cannot create.\n", ofn); ! 71: exit(1); ! 72: } ! 73: #if !RSX && !CPM ! 74: setbuf(ofp, NULL); ! 75: #endif ! 76: syminit(); ! 77: locinit(); ! 78: for (pass = 0; pass < 3; ++pass) { ! 79: if (pass==1 && gflag) ! 80: symglob(); ! 81: if (pass == 2) { ! 82: locadjust(); ! 83: outinit(); ! 84: } ! 85: sfx = 1; ! 86: page = 0; ! 87: lop = NLPP; ! 88: if (sfp != NULL) { ! 89: fseek(sfp, (long)0, 0); ! 90: line = 0; ! 91: } ! 92: loczero(); ! 93: fuzz = 0; ! 94: #if MINIT ! 95: minit(); ! 96: #endif ! 97: dot->s_kind = S_USER; ! 98: dot->s_type = E_DIR; ! 99: dot->s_addr = defloc->l_offset; ! 100: dot->s_base.s_lp = defloc; ! 101: setinbss(); ! 102: if (pass != 0) { ! 103: for (i=0; i<10; ++i) { ! 104: tsymp[i].tp_bp = NULL; ! 105: tsymp[i].tp_fp = tsymp[i].tp_lfp; ! 106: } ! 107: } ! 108: for (;;) { ! 109: if (sfp == NULL) { ! 110: sfn = NULL; ! 111: while (sfx<argc && (sfn=argv[sfx++])==NULL) ! 112: ; ! 113: if (sfn == NULL) ! 114: break; ! 115: if ((sfp = fopen(sfn, "r")) == NULL) { ! 116: fprintf(stderr, copen, sfn); ! 117: exit(1); ! 118: } ! 119: if (nfile != 1) ! 120: ifn = sfn; ! 121: line = 0; ! 122: lop = NLPP; ! 123: } ! 124: if (getline() == 0) { ! 125: if (nfile == 1) ! 126: break; ! 127: fclose(sfp); ! 128: sfp = NULL; ! 129: continue; ! 130: } ! 131: ++line; ! 132: cp = cb; ! 133: ep = eb; ! 134: ip = ib; ! 135: if (setjmp(env) == 0) ! 136: asm(); ! 137: if (pass == 2) ! 138: list(); ! 139: } ! 140: newloc(NULL); ! 141: } ! 142: outfinish(); ! 143: if (nerr != 0) { ! 144: if (lflag) ! 145: fprintf(efp, "%d error%s detected\n", ! 146: nerr, ((nerr != 1) ? "s" : "")); ! 147: unlink(ofn); ! 148: exit(1); ! 149: } ! 150: #if 0 ! 151: #if !RSX && !CPM ! 152: chmod(ofn, 0755); ! 153: #endif ! 154: #endif ! 155: exit(0); ! 156: } ! 157: ! 158: asm() ! 159: { ! 160: register struct sym *sp; ! 161: register struct tsym *tp; ! 162: register c; ! 163: address cs; ! 164: struct tsymp *tsp; ! 165: struct expr e1; ! 166: char id[NCPLN]; ! 167: char *p; ! 168: int d; ! 169: ! 170: laddr = dot->s_addr; ! 171: lmode = SLIST; ! 172: loop: ! 173: while ((c=getnb()) == ';') ! 174: ; ! 175: if (c==0 || c=='/') ! 176: return; ! 177: if (ctype[c] == DIGIT) { ! 178: if (get() != ':') ! 179: qerr("invalid local symbol"); ! 180: tsp = &tsymp[c-'0']; ! 181: if (pass == 0) { ! 182: tp = (struct tsym *) new(sizeof(struct tsym)); ! 183: tp->t_fp = NULL; ! 184: tp->t_lp = dot->s_base.s_lp; ! 185: tp->t_addr = dot->s_addr; ! 186: if (tsp->tp_lfp == NULL) ! 187: tsp->tp_lfp = tp; else ! 188: tsp->tp_llp->t_fp = tp; ! 189: tsp->tp_llp = tp; ! 190: } else { ! 191: tp = tsp->tp_fp; ! 192: if (pass == 1) { ! 193: fuzz = tp->t_addr - dot->s_addr; ! 194: tp->t_lp = dot->s_base.s_lp; ! 195: tp->t_addr = dot->s_addr; ! 196: } else ! 197: phase(tp->t_lp, tp->t_addr); ! 198: } ! 199: tsp->tp_bp = tp; ! 200: tsp->tp_fp = tp->t_fp; ! 201: goto loop; ! 202: } ! 203: if (ctype[c] != LETTER) ! 204: qerr("invalid identifier"); ! 205: getid(id, c); ! 206: if ((c=getnb()) == ':') { ! 207: sp = lookup(id, 1); ! 208: if (sp == dot) ! 209: err('.', "'.' declared as label"); ! 210: if (pass == 0) ! 211: if (sp->s_type!=S_NEW && (sp->s_flag&S_ASG)==0) ! 212: sp->s_flag |= S_MDF; ! 213: if (pass != 2) { ! 214: fuzz = sp->s_addr - dot->s_addr; ! 215: sp->s_kind = S_USER; ! 216: sp->s_type = E_DIR; ! 217: sp->s_base.s_lp = dot->s_base.s_lp; ! 218: sp->s_addr = dot->s_addr; ! 219: } else { ! 220: if ((sp->s_flag&S_MDF) != 0) ! 221: err('m', "multiply defined symbol"); ! 222: phase(sp->s_base.s_lp, sp->s_addr); ! 223: } ! 224: lmode = ALIST; ! 225: goto loop; ! 226: } ! 227: if (c == '=') { ! 228: expr(&e1, 0); ! 229: if ((sp=lookup(id, 1)) == dot) { ! 230: #if INTEL ! 231: dot->s_addr = e1.e_addr; ! 232: #else ! 233: if (okdot(&e1)) { ! 234: if (inbss == 0) ! 235: zblock(e1.e_addr-dot->s_addr); ! 236: else ! 237: dot->s_addr = e1.e_addr; ! 238: } ! 239: #endif ! 240: } else { ! 241: if (sp->s_type!=S_NEW && (sp->s_flag&S_ASG)==0) ! 242: err('m', "multiply defined symbol"); ! 243: sp->s_kind = S_USER; ! 244: sp->s_type = e1.e_type; ! 245: if (e1.e_type == E_ASEG) ! 246: sp->s_base.s_segn = e1.e_base.e_segn; ! 247: else if (e1.e_type == E_DIR) ! 248: sp->s_base.s_lp = e1.e_base.e_lp; ! 249: else if (e1.e_type==E_SYM || e1.e_type==E_SEG) ! 250: sp->s_base.s_sp = e1.e_base.e_sp; ! 251: sp->s_addr = e1.e_addr; ! 252: sp->s_flag |= S_ASG; ! 253: } ! 254: laddr = e1.e_addr; ! 255: lmode = ALIST; ! 256: goto loop; ! 257: } ! 258: unget(c); ! 259: lmode = CLIST; ! 260: if ((sp=lookup(id, 0)) == NULL) { ! 261: uerr(id); ! 262: return; ! 263: } ! 264: switch (sp->s_kind) { ! 265: ! 266: case S_BYTE: ! 267: case S_WORD: ! 268: do { ! 269: expr(&e1, 0); ! 270: if (sp->s_kind == S_BYTE) ! 271: outrb(&e1, 0); else ! 272: outrw(&e1, 0); ! 273: } while ((c = getnb()) == ','); ! 274: unget(c); ! 275: if (sp->s_kind == S_BYTE) ! 276: lmode = BLIST; else ! 277: lmode = WLIST; ! 278: break; ! 279: ! 280: case S_ASCII: ! 281: if ((d = getnb()) == '\0') ! 282: qerr("end of line in string"); ! 283: while ((c = getmap(d)) >= 0) ! 284: outab(c); ! 285: lmode = BLIST; ! 286: break; ! 287: ! 288: case S_BLK: ! 289: cs = absexpr()*sp->s_addr; ! 290: if (inbss == 0) ! 291: zblock(cs); else ! 292: dot->s_addr += cs; ! 293: lmode = ALIST; ! 294: break; ! 295: ! 296: case S_TITLE: ! 297: p = tb; ! 298: if (c = getnb()) { ! 299: do { ! 300: if (p < &tb[NTIT-1]) ! 301: *p++ = c; ! 302: } while (c = get()); ! 303: } ! 304: *p = 0; ! 305: unget(c); ! 306: ! 307: case S_PAGE: ! 308: lop = NLPP; ! 309: lmode = NLIST; ! 310: break; ! 311: ! 312: case S_GLOBL: ! 313: do { ! 314: getid(id, -1); ! 315: lookup(id, 1)->s_flag |= S_GBL; ! 316: } while ((c = getnb()) == ','); ! 317: unget(c); ! 318: lmode = SLIST; ! 319: break; ! 320: ! 321: case S_COMM: ! 322: getid(id, -1); ! 323: if (getnb() != ',') ! 324: qerr("expected comma"); ! 325: cs = locrup(absexpr()); ! 326: sp = lookup(id, 1); ! 327: if (sp->s_kind == S_NEW) { ! 328: sp->s_flag |= S_GBL; ! 329: if (cs > sp->s_addr) ! 330: sp->s_addr = cs; ! 331: } ! 332: lmode = SLIST; ! 333: break; ! 334: ! 335: case S_LOC: ! 336: newloc((struct loc *) sp->s_addr); ! 337: lmode = SLIST; ! 338: break; ! 339: ! 340: default: ! 341: machine(sp); ! 342: } ! 343: goto loop; ! 344: } ! 345: ! 346: okdot(esp) ! 347: register struct expr *esp; ! 348: { ! 349: if (esp->e_type!=E_DIR || esp->e_base.e_lp!=dot->s_base.s_lp) { ! 350: rerr("not a direct address in this segment"); ! 351: return (0); ! 352: } ! 353: if (esp->e_addr < dot->s_addr) { ! 354: aerr("cannot move . back"); ! 355: return (0); ! 356: } ! 357: return (1); ! 358: } ! 359: ! 360: zblock(n) ! 361: address n; ! 362: { ! 363: while (n--) ! 364: outab(0); ! 365: } ! 366: ! 367: usage() ! 368: { ! 369: fprintf(stderr, "Usage: as [-glx] [-o file] file [file ...]\n"); ! 370: exit(1); ! 371: } ! 372: ! 373: phase(lp, a) ! 374: struct loc *lp; ! 375: address a; ! 376: { ! 377: if (dot->s_base.s_lp!=lp || dot->s_addr!=a) ! 378: err('p', "phase error"); ! 379: } ! 380: ! 381: newloc(nlp) ! 382: register struct loc *nlp; ! 383: { ! 384: register struct loc *olp; ! 385: ! 386: if ((olp = dot->s_base.s_lp) != NULL) { ! 387: olp->l_fuzz = fuzz; ! 388: olp->l_break = dot->s_addr - olp->l_offset; ! 389: } ! 390: if (nlp != NULL) { ! 391: dot->s_base.s_lp = nlp; ! 392: dot->s_addr = nlp->l_break + nlp->l_offset; ! 393: fuzz = nlp->l_fuzz; ! 394: } ! 395: setinbss(); ! 396: #if !INTEL ! 397: if (pass == 2) ! 398: outchk(HUGE, HUGE); ! 399: #endif ! 400: } ! 401: ! 402: loczero() ! 403: { ! 404: register struct loc *lp; ! 405: register i; ! 406: ! 407: for (i=0; i<nloc; ++i) { ! 408: lp = loc[i]; ! 409: while (lp != NULL) { ! 410: lp->l_fuzz = 0; ! 411: lp->l_break = 0; ! 412: lp = lp->l_lp; ! 413: } ! 414: } ! 415: } ! 416: ! 417: locadjust() ! 418: { ! 419: register struct sym *sp; ! 420: register struct loc *lp; ! 421: register struct tsym *tp; ! 422: address offset; ! 423: int i; ! 424: ! 425: #if !SEG ! 426: offset = 0; ! 427: #endif ! 428: for (i=0; i<nloc; ++i) { ! 429: #if SEG ! 430: offset = 0; ! 431: #endif ! 432: lp = loc[i]; ! 433: while (lp != NULL) { ! 434: lp->l_offset = offset; ! 435: offset += locrup(lp->l_break); ! 436: lp = lp->l_lp; ! 437: } ! 438: } ! 439: for (i=0; i<10; ++i) { ! 440: tp = tsymp[i].tp_lfp; ! 441: while (tp != NULL) { ! 442: if ((lp = tp->t_lp) != NULL) ! 443: tp->t_addr += lp->l_offset; ! 444: tp = tp->t_fp; ! 445: } ! 446: } ! 447: for (i=0; i<NHASH; ++i) { ! 448: sp = symhash[i]; ! 449: while (sp != NULL) { ! 450: if (sp->s_kind == S_USER && ! 451: sp->s_type == E_DIR && ! 452: (lp=sp->s_base.s_lp) != NULL) ! 453: sp->s_addr += lp->l_offset; ! 454: sp = sp->s_sp; ! 455: } ! 456: } ! 457: } ! 458: ! 459: setinbss() ! 460: { ! 461: register struct loc *lp; ! 462: ! 463: inbss = 0; ! 464: lp = dot->s_base.s_lp; ! 465: #if SEG ! 466: if (lp->l_seg == BSS) ! 467: #else ! 468: if (lp->l_seg==L_BSSI || lp->l_seg==L_BSSD) ! 469: #endif ! 470: ++inbss; ! 471: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.