#!/bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #!/bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # assm2.c # assm3.c # This archive created: Tue Apr 2 14:21:24 1985 # By: James Van Ornum (AT&T-Bell Laboratories) export PATH; PATH=/bin:$PATH if test -f 'assm2.c' then echo shar: over-writing existing file "'assm2.c'" fi cat << \SHAR_EOF > 'assm2.c' #include "stdio.h" #include "assm.d1" #include "assm.d2" extern int optab[]; extern int step[]; /* translate source line to machine language */ assemble() { int flg; int i; /* prlnbuf pointer */ if ((prlnbuf[SFIELD] == ';') | (prlnbuf[SFIELD] == 0)) { if (pass == LAST_PASS) println(); return; } lablptr = -1; i = SFIELD; udtype = UNDEF; if (colsym(&i) != 0 && (lablptr = stlook()) == -1) return; while (prlnbuf[++i] == ' '); /* find first non-space */ if ((flg = oplook(&i)) < 0) { /* collect operation code */ labldef(loccnt); if (flg == -1) error("Invalid operation code"); if ((flg == -2) && (pass == LAST_PASS)) { if (lablptr != -1) loadlc(loccnt, 1, 0); println(); } return; } if (opflg == PSEUDO) pseudo(&i); else if (labldef(loccnt) == -1) return; else { if (opflg == CLASS1) class1(); else if (opflg == CLASS2) class2(&i); else class3(&i); } } /****************************************************************************/ /* printline prints the contents of prlnbuf */ println() { if (lflag > 0) fprintf(stdout, "%s\n", prlnbuf); } /* colsym() collects a symbol from prlnbuf into symbol[], * leaves prlnbuf pointer at first invalid symbol character, * returns 0 if no symbol collected */ colsym(ip) int *ip; { int valid; int i; char ch; valid = 1; i = 0; while (valid == 1) { ch = prlnbuf[*ip]; if (ch == '_' || ch == '.'); else if (ch >= 'a' && ch <= 'z'); else if (ch >= 'A' && ch <= 'Z'); else if (i >= 1 && ch >= '0' && ch <= '9'); else if (i == 1 && ch == '='); else valid = 0; if (valid == 1) { if (i < SBOLSZ - 1) symbol[++i] = ch; (*ip)++; } } if (i == 1) { switch (symbol[1]) { case 'A': case 'a': case 'X': case 'x': case 'Y': case 'y': error("Symbol is reserved (A, X or Y)"); i = 0; } } symbol[0] = i; return(i); } /* symbol table lookup * if found, return pointer to symbol * else, install symbol as undefined, and return pointer */ stlook() { int found; int hptr; int j; int nptr; int pptr; int ptr; hptr = 0; for (j = 0; j < symbol[0]; j++) hptr += symbol[j]; hptr %= 128; ptr = hash_tbl[hptr]; if (ptr == -1) { /* no entry for this link */ hash_tbl[hptr] = nxt_free; return(stinstal()); } while (symtab[ptr] != 0) { /* 0 count = end of table */ found = 1; for (j = 0; j <= symbol[0]; j++) { if (symbol[j] != symtab[ptr + j]) { found = 0; pptr = ptr + symtab[ptr] + 4; nptr = (symtab[pptr + 1] << 8) + (symtab[pptr] & 0xff); nptr &= 0xffff; if (nptr == 0) { symtab[ptr + symtab[ptr] + 4] = nxt_free & 0xff; symtab[ptr + symtab[ptr] + 5] = (nxt_free >> 8) & 0xff; return(stinstal()); } ptr = nptr; break; } } if (found == 1) return(ptr); } error("Symbol not found"); return(-1); } /* instal symbol into symtab */ stinstal() { register int j; register int ptr1; register int ptr2; ptr1 = ptr2 = nxt_free; if ((ptr1 + symbol[0] + 6) >= STABSZ) { error("Symbol table full"); return(-1); } for (j = 0; j <= symbol[0]; j++) symtab[ptr1++] = symbol[j]; symtab[ptr1] = udtype; nxt_free = ptr1 + 5; return(ptr2); } /* operation code table lookup * if found, return pointer to symbol, * else, return -1 */ oplook(ip) int *ip; { register char ch; register int i; register int j; int k; int temp[2]; i = j = 0; temp[0] = temp[1] = 0; while((ch=prlnbuf[*ip])!= ' ' && ch!= 0 && ch!= '\t' && ch!= ';') { if (ch >= 'A' && ch <= 'Z') ch &= 0x1f; else if (ch >= 'a' && ch <= 'z') ch &= 0x1f; else if (ch == '.') ch = 31; else if (ch == '*') ch = 30; else if (ch == '=') ch = 29; else return(-1); temp[j] = (temp[j] * 0x20) + (ch & 0xff); if (ch == 29) break; ++(*ip); if (++i >= 3) { i = 0; if (++j >= 2) { return(-1); } } } if ((j = temp[0]^temp[1]) == 0) return(-2); k = 0; i = step[k] - 3; do { if (j == optab[i]) { opflg = optab[++i]; opval = optab[++i]; return(i); } else if (j < optab[i]) i -= step[++k]; else i += step[++k]; } while (step[k] != 0); return(-1); } /* error printing routine */ error(stptr) char *stptr; { loadlc(loccnt, 0, 1); loccnt += 3; loadv(0,0,0); loadv(0,1,0); loadv(0,2,0); fprintf(stderr, "%s\n", prlnbuf); fprintf(stderr, "***** %s\n", stptr); errcnt++; } /* load 16 bit value in printable form into prlnbuf */ loadlc(val, f, outflg) int val; int f; int outflg; { int i; i = 6 + 7*f; hexcon(4, val); if (nflag == 0) { prlnbuf[i++] = hex[3]; prlnbuf[i++] = hex[4]; prlnbuf[i++] = ':'; prlnbuf[i++] = hex[1]; prlnbuf[i] = hex[2]; } else { prlnbuf[i++] = hex[1]; prlnbuf[i++] = hex[2]; prlnbuf[i++] = hex[3]; prlnbuf[i] = hex[4]; } if ((pass == LAST_PASS)&&(oflag != 0)&&(objcnt <= 0)&&(outflg != 0)) { /* rearrange the next for franklin monitor tm */ fprintf(optr, "\n%c%c%c%c:", hex[1], hex[2], hex[3], hex[4]); objcnt = 16; } } /* load value in hex into prlnbuf[contents[i]] */ /* and output hex characters to obuf if LAST_PASS & oflag == 1 */ loadv(val,f,outflg) int val; int f; /* contents field subscript */ int outflg; /* flag to output object bytes */ { hexcon(2, val); prlnbuf[13 + 3*f] = hex[1]; prlnbuf[14 + 3*f] = hex[2]; if ((pass == LAST_PASS) && (oflag != 0) && (outflg != 0)) { fputc(hex[1], optr); fputc(hex[2], optr); fputc(' ', optr); /* add space for franklin monitor tm */ --objcnt; } } /* convert number supplied as argument to hexadecimal in hex[digit] (lsd) through hex[1] (msd) */ hexcon(digit, num) int digit; int num; { for (; digit > 0; digit--) { hex[digit] = (num & 0x0f) + '0'; if (hex[digit] > '9') hex[digit] += 'A' -'9' - 1; num >>= 4; } } /* assign to label pointed to by lablptr, * checking for valid definition, etc. */ labldef(lval) int lval; { int i; if (lablptr != -1) { lablptr += symtab[lablptr] + 1; if (pass == FIRST_PASS) { if (symtab[lablptr] == UNDEF) { symtab[lablptr + 1] = lval & 0xff; i = symtab[lablptr + 2] = (lval >> 8) & 0xff; if (i == 0) symtab[lablptr] = DEFZRO; else symtab[lablptr] = DEFABS; } else if (symtab[lablptr] == UNDEFAB) { symtab[lablptr] = DEFABS; symtab[lablptr + 1] = lval & 0xff; symtab[lablptr + 2] = (lval >> 8) & 0xff; } else { symtab[lablptr] = MDEF; symtab[lablptr + 1] = 0; symtab[lablptr + 2] = 0; error("Label multiply defined"); return(-1); } } else { i = (symtab[lablptr + 2] << 8) + (symtab[lablptr+1] & 0xff); i &= 0xffff; if (i != lval && pass == LAST_PASS) { error("Sync error"); return(-1); } } } return(0); } /* determine the value of the symbol, * given pointer to first character of symbol in symtab */ symval(ip) int *ip; { int ptr; int svalue; svalue = 0; colsym(ip); if ((ptr = stlook()) == -1) undef = 1; /* no room error */ else if (symtab[ptr + symtab[ptr] + 1] == UNDEF) undef = 1; else if (symtab[ptr + symtab[ptr] + 1] == UNDEFAB) undef = 1; else svalue = ((symtab[ptr + symtab[ptr] + 3] << 8) + (symtab[ptr + symtab[ptr] + 2] & 0xff)) & 0xffff; if (symtab[ptr + symtab[ptr] + 1] == DEFABS) zpref = 1; if (undef != 0) zpref = 1; return(svalue); } SHAR_EOF if test -f 'assm3.c' then echo shar: over-writing existing file "'assm3.c'" fi cat << \SHAR_EOF > 'assm3.c' #include "stdio.h" #include "assm.d1" #include "assm.d2" /* class 1 machine operations processor - 1 byte, no operand field */ class1() { if (pass == LAST_PASS) { loadlc(loccnt, 0, 1); loadv(opval, 0, 1); println(); } loccnt++; } /* class 2 machine operations processor - 2 byte, relative addressing */ class2(ip) int *ip; { if (pass == LAST_PASS) { loadlc(loccnt, 0, 1); loadv(opval, 0, 1); while (prlnbuf[++(*ip)] == ' '); if (evaluate(ip) != 0) { loccnt += 2; return; } loccnt += 2; if ((value -= loccnt) >= -128 && value < 128) { loadv(value, 1, 1); println(); } else error("Invalid branch address"); } else loccnt += 2; } /* class 3 machine operations processor - various addressing modes */ class3(ip) int *ip; { char ch; int code; int flag; int i; int ztmask; while ((ch = prlnbuf[++(*ip)]) == ' '); switch(ch) { case 0: case ';': error("Operand field missing"); return; case 'A': case 'a': if ((ch = prlnbuf[*ip + 1]) == ' ' || ch == 0) { flag = ACC; break; } default: switch(ch = prlnbuf[*ip]) { case '#': case '=': flag = IMM1 | IMM2; ++(*ip); break; case '(': flag = IND | INDX | INDY; ++(*ip); break; default: flag = ABS | ZER | ZERX | ABSX | ABSY | ABSY2 | ZERY; } if ((flag & (INDX | INDY | ZER | ZERX | ZERY) & opflg) != 0) udtype = UNDEFAB; if (evaluate(ip) != 0) return; if (zpref != 0) { flag &= (ABS | ABSX | ABSY | ABSY2 | IND | IMM1 | IMM2); ztmask = 0; } else ztmask = ZER | ZERX | ZERY; code = 0; i = 0; while (( ch = prlnbuf[(*ip)++]) != ' ' && ch != 0 && i++ < 4) { code *= 8; switch(ch) { case ')': /* ) = 4 */ ++code; case ',': /* , = 3 */ ++code; case 'X': /* X = 2 */ case 'x': ++code; case 'Y': /* Y = 1 */ case 'y': ++code; break; default: flag = 0; } } switch(code) { case 0: /* no termination characters */ flag &= (ABS | ZER | IMM1 | IMM2); break; case 4: /* termination = ) */ flag &= IND; break; case 25: /* termination = ,Y */ flag &= (ABSY | ABSY2 | ZERY); break; case 26: /* termination = ,X */ flag &= (ABSX | ZERX); break; case 212: /* termination = ,X) */ flag &= INDX; break; case 281: /* termination = ),Y */ flag &= INDY; break; default: flag = 0; } } if ((opflg &= flag) == 0) { error("Invalid addressing mode"); return; } if ((opflg & ztmask) != 0) opflg &= ztmask; switch(opflg) { case ACC: /* single byte - class 3 */ if (pass == LAST_PASS) { loadlc(loccnt, 0, 1); loadv(opval + 8, 0, 1); println(); } loccnt++; return; case ZERX: case ZERY: /* double byte - class 3 */ opval += 4; case INDY: opval += 8; case IMM2: opval += 4; case ZER: opval += 4; case INDX: case IMM1: if (pass == LAST_PASS) { loadlc(loccnt, 0, 1); loadv(opval, 0, 1); loadv(value, 1, 1); println(); } loccnt += 2; return; case IND: /* triple byte - class 3 */ opval += 16; case ABSX: case ABSY2: opval += 4; case ABSY: opval += 12; case ABS: if (pass == LAST_PASS) { opval += 12; loadlc(loccnt, 0, 1); loadv(opval, 0, 1); loadv(value, 1, 1); loadv(value >> 8, 2, 1); println(); } loccnt += 3; return; default: error("Invalid addressing mode"); return; } } /* pseudo operations processor */ pseudo(ip) int *ip; { int count; int i; int tvalue; int hibit; /* apple requires high bit to be on for chs */ int pi; switch(opval) { case 0: /* .byte pseudo */ labldef(loccnt); loadlc(loccnt, 0, 1); while (prlnbuf[++(*ip)] == ' '); /* field */ count = 0; do { if (prlnbuf[*ip] == '"') { /* check for hibit on flag for ascii chs */ hibit = 0 ; pi = *ip; while((i = prlnbuf[++pi]) != '"' && i != 0 ); if (i != 0 ) while(prlnbuf[++pi] == ' ' ) ; if (prlnbuf[pi] == '1' ) hibit = 0x80 ; while ((tvalue = prlnbuf[++(*ip)]) != '"') { if (tvalue == 0) { error("Unterminated ASCII string"); return; } if (tvalue == '\\') switch(tvalue = prlnbuf[++(*ip)]) { case 'n': tvalue = '\n'; break; case 't': tvalue = '\t'; break; } loccnt++; if (pass == LAST_PASS) { tvalue |= hibit ; loadv(tvalue, count, 1); if (++count >= 3) { println(); for (i = 0; i < SFIELD; i++) prlnbuf[i] = ' '; prlnbuf[i] = 0; count = 0; loadlc(loccnt, 0, 1); } } } ++(*ip); } else { if (evaluate(ip) != 0) { loccnt++; return; } loccnt++; if (value > 0xff) { error("Operand field size error"); return; } else if (pass == LAST_PASS) { loadv(value, count, 1); if (++count >= 3) { println(); for (i = 0; i < SFIELD; i++) prlnbuf[i] = ' '; prlnbuf[i] = 0; count = 0; loadlc(loccnt, 0, 1); } } } } while (prlnbuf[(*ip)++] == ','); if ((pass == LAST_PASS) && (count != 0)) println(); return; case 1: /* = pseudo */ while (prlnbuf[++(*ip)] == ' '); if (evaluate(ip) != 0) return; labldef(value); if (pass == LAST_PASS) { loadlc(value, 1, 0); println(); } return; case 2: /* .word pseudo */ labldef(loccnt); loadlc(loccnt, 0, 1); while (prlnbuf[++(*ip)] == ' '); do { if (evaluate(ip) != 0) { loccnt += 2; return; } loccnt += 2; if (pass == LAST_PASS) { loadv(value, 0, 1); loadv(value>>8, 1, 1); println(); for (i = 0; i < SFIELD; i++) prlnbuf[i] = ' '; prlnbuf[i] = 0; loadlc(loccnt, 0, 1); } } while (prlnbuf[(*ip)++] == ','); return; case 3: /* *= pseudo */ while (prlnbuf[++(*ip)] == ' '); if (prlnbuf[*ip] == '*') { if (evaluate(ip) != 0) return; if (undef != 0) { error("Undefined symbol in operand field."); return; } tvalue = loccnt; } else { if (evaluate(ip) != 0) return; if (undef != 0) { error("Undefined symbol in operand field."); return; } tvalue = value; } loccnt = value; labldef(tvalue); if (pass == LAST_PASS) { objcnt = 0; loadlc(tvalue, 1, 0); println(); } return; case 4: /* .list pseudo */ if (lflag >= 0) lflag = 1; return; case 5: /* .nlst pseudo */ if (lflag >= 0) lflag = iflag; return; case 6: /* .dbyt pseudo */ labldef(loccnt); loadlc(loccnt, 0, 1); while (prlnbuf[++(*ip)] == ' '); do { if (evaluate(ip) != 0) { loccnt += 2; return; } loccnt += 2; if (pass == LAST_PASS) { loadv(value>>8, 0, 1); loadv(value, 1, 1); println(); for (i = 0; i < SFIELD; i++) prlnbuf[i] = ' '; prlnbuf[i] = 0; loadlc(loccnt, 0, 1); } } while (prlnbuf[(*ip)++] == ','); return; case 7: /* ds pseudo */ while (prlnbuf[++(*ip)] == ' '); if (evaluate(ip) != 0) return; if (undef != 0) { error("Undefined symbol in operand field."); return; } tvalue = loccnt; labldef(loccnt); loccnt += value; if (pass == LAST_PASS) { objcnt = 0; loadlc(tvalue, 1, 0); println(); } return; case 8: /* asc pseudo */ labldef(loccnt); loadlc(loccnt, 0, 1); while (prlnbuf[++(*ip)] == ' '); /* field */ count = 0; do { if (prlnbuf[*ip] == '\'') { while ((tvalue = prlnbuf[++(*ip)]) != '\'') { if (tvalue == 0) { error("Unterminated ASCII string"); return; } if (tvalue == '\\') switch(tvalue = prlnbuf[++(*ip)]) { case 'n': tvalue = '\n'; break; case 't': tvalue = '\t'; break; } loccnt++; if (pass == LAST_PASS) { tvalue |= msb ; loadv(tvalue, count, 1); if (++count >= 3) { println(); for (i = 0; i < SFIELD; i++) prlnbuf[i] = ' '; prlnbuf[i] = 0; count = 0; loadlc(loccnt, 0, 1); } } } ++(*ip); } else { if (evaluate(ip) != 0) { loccnt++; return; } loccnt++; if (value > 0xff) { error("Operand field size error"); return; } else if (pass == LAST_PASS) { loadv(value, count, 1); if (++count >= 3) { println(); for (i = 0; i < SFIELD; i++) prlnbuf[i] = ' '; prlnbuf[i] = 0; count = 0; loadlc(loccnt, 0, 1); } } } } while (prlnbuf[(*ip)++] == ','); if ((pass == LAST_PASS) && (count != 0)) println(); return; case 13: /* msb pseudo */ while (prlnbuf[++(*ip)] == ' '); if (pass == LAST_PASS) println(); pi = *ip; if (( i = 0x20|prlnbuf[pi+1] ) == 'f' ){ msb=0; return; } else if (i=='n'){ msb=0x80; return; } error("Invalid symbol in operand field."); return; } } /* evaluate expression */ evaluate(ip) int *ip; { int tvalue; int invalid; int parflg, value2; char ch; char op; char op2; op = '+'; parflg = zpref = undef = value = invalid = 0; /* hcj: zpref should reflect the value of the expression, not the value of the intermediate symbols */ while ((ch=prlnbuf[*ip]) != ' ' && ch != ')' && ch != ',' && ch != ';') { tvalue = 0; if (ch == '$' || ch == '@' || ch == '%') tvalue = colnum(ip); else if (ch >= '0' && ch <= '9') tvalue = colnum(ip); else if (ch >= 'a' && ch <= 'z') tvalue = symval(ip); else if (ch >= 'A' && ch <= 'Z') tvalue = symval(ip); else if ((ch == '_') || (ch == '.')) tvalue = symval(ip); else if (ch == '*') { tvalue = loccnt; ++(*ip); } else if (ch == '\'') { ++(*ip); tvalue = prlnbuf[*ip] & 0xff; ++(*ip); } else if (ch == '[') { if (parflg == 1) { error("Too many ['s in expression"); invalid++; } else { value2 = value; op2 = op; value = tvalue = 0; op = '+'; parflg = 1; } goto next; } else if (ch == ']') { if (parflg == 0) { error("No matching [ for ] in expression"); invalid++; } else { parflg = 0; tvalue = value; value = value2; op = op2; } ++(*ip); } switch(op) { case '+': value += tvalue; break; case '-': value -= tvalue; break; case '/': value = (unsigned) value/tvalue; break; case '*': value *= tvalue; break; case '%': value = (unsigned) value%tvalue; break; case '^': value ^= tvalue; break; case '~': value = ~tvalue; break; case '&': value &= tvalue; break; case '|': value |= tvalue; break; case '<': tvalue >>= 8; /* fall through to '<' */ case '>': if (value != 0) { error("High or low byte operator not first in operand field"); } value = tvalue & 0xff; zpref = 0; break; default: invalid++; } if ((op=prlnbuf[*ip]) == ' ' || op == ')' || op == ',' || op == ';') break; else if (op != ']') next: ++(*ip); } if (parflg == 1) { error("Missing ] in expression"); return(1); } if (value < 0 || value >= 256) { zpref = 1; } if (undef != 0) { if (pass != FIRST_PASS) { error("Undefined symbol in operand field"); invalid++; } value = 0; } else if (invalid != 0) { error("Invalid operand field"); } else { /* This is the only way out that may not signal error */ if (value < 0 || value >= 256) { zpref = 1; } else { zpref = 0; } } return(invalid); } /* collect number operand */ colnum(ip) int *ip; { int mul; int nval; char ch; nval = 0; if ((ch = prlnbuf[*ip]) == '$') mul = 16; else if (ch >= '1' && ch <= '9') { mul = 10; nval = ch - '0'; } else if (ch == '@' || ch == '0') mul = 8; else if (ch == '%') mul = 2; while ((ch = prlnbuf[++(*ip)] - '0') >= 0) { if (ch > 9) { ch -= ('A' - '9' - 1); if (ch > 15) ch -= ('a' - 'A'); if (ch > 15) break; if (ch < 10) break; } if (ch >= mul) break; nval = (nval * mul) + ch; } return(nval); } SHAR_EOF # End of shell archive exit 0