|
|
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.