/* Mycket enkel assembler för Am2910-chipet och lab 6 i kursen Digitalteknik av Fredrik Roubert 1996 */ #include #include #include #define MAXSYMBOL 256 #define SYMBOLLEN 32 #define iswhitespace(q) (q==' ' || q=='\t' || q=='\n') typedef unsigned int symbol; const char *mnemonics[16]={ "jz", "cjs", "jmap", "cjp", "push", "jsrp", "cjv", "jrp", "rfct", "rpct", "crtn", "cjpp", "ldct", "loop", "cont", "twb" }; char symbol_names[MAXSYMBOL+1][SYMBOLLEN+1]; symbol symbol_values[MAXSYMBOL+1]; int source_line,max_symbol; char print_symboltable,print_mnemonics; FILE *source; /* Läser in nästa, av whitespace avgränsade, sträng. Returnerar strängens längd eller EOF */ int next_token(char *t) { int q,x; do { q=fgetc(source); if(q==';') while(q!=EOF && q!='\n') q=fgetc(source); if(q=='\n') source_line++; } while(q!=EOF && iswhitespace(q)); t[0]=tolower(q); x=0; while(t[x]!=EOF && !iswhitespace(t[x])) { t[++x]=tolower(fgetc(source)); if(t[x]==';') while(t[x]!=EOF && t[x]!='\n') t[x]=fgetc(source); if(t[x]=='\n') source_line++; } q=t[x]; t[x]='\0'; return (q==EOF?EOF:x); } int match_symbol(char *t) { char tt[SYMBOLLEN+1]; int x; strncpy(tt,t,SYMBOLLEN); tt[SYMBOLLEN]='\0'; if(tt[strlen(tt)-1]==':') tt[strlen(tt)-1]='\0'; for(x=0;x0;x--,p*=16) { if(!((t[x]>='0' && t[x]<='9') || (t[x]>='a' && t[x]<='f'))) { fprintf(stderr,"Parse error on line %u:\n\tInvalid character '%c' in hexadecimal constant.\n\n",source_line,t[x]); return 0; } v+=p*( (t[x]>='0' && t[x]<='9')?(t[x]-'0'):(t[x]-'a'+10) ); } break; case '#': /* dec */ for(x=l,p=1;x>0;x--,p*=10) { if(t[x]<'0' || t[x]>'9') { fprintf(stderr,"Parse error on line %u:\n\tInvalid character '%c' in decimal constant.\n\n",source_line,t[x]); return 0; } v+=p*(t[x]-'0'); } break; default: /* bin */ for(x=l,p=1;x>=0;x--,p*=2) { if(t[x]!='0' && t[x]!='1') { fprintf(stderr,"Parse error on line %u:\n\tInvalid character '%c' in binary constant.\n\n",source_line,t[x]); return 0; } v+=p*(t[x]-'0'); } } return v; } void build_symboltable(void) { char buf[255],lastbuf[255]; int l,line; max_symbol=0; lastbuf[0]='\0'; line=0; while(next_token(buf)!=EOF) { if(match_token(buf)!=-1) line++; l=strlen(buf)-1; if(buf[l]==':') { strncpy(symbol_names[max_symbol],buf,SYMBOLLEN); symbol_names[max_symbol][l>SYMBOLLEN?SYMBOLLEN:l]='\0'; if(l>SYMBOLLEN) fprintf(stderr,"Warning on line %u:\n\tSymbol name truncated to '%s'.\n\n",source_line,symbol_names[max_symbol]); symbol_values[max_symbol]=line; if(max_symbol==MAXSYMBOL) fprintf(stderr,"Internal error on line %u:\n\tToo many symbols used.\n\n",source_line); else max_symbol++; } else if(strcmp(buf,"equ")==0) { if(strlen(lastbuf)==0) { fprintf(stderr,"Parse error on line %u:\n\tToken is not preceeded by a valid symbol name.\n\n",source_line); buf[0]='\0'; } else { strncpy(symbol_names[max_symbol],lastbuf,SYMBOLLEN); if(strlen(lastbuf)>SYMBOLLEN) { symbol_names[max_symbol][SYMBOLLEN]='\0'; fprintf(stderr,"Warning on line %u:\n\tSymbol name truncated to '%s'.\n\n",source_line,symbol_names[max_symbol]); } if(max_symbol==MAXSYMBOL) fprintf(stderr,"Internal error on line %u:\n\tToo many symbols used.\n\n",source_line); else max_symbol++; } } else if(strcmp(lastbuf,"equ")==0) symbol_values[max_symbol-1]=parse_value(buf); strcpy(lastbuf,buf); } } void print_binary(int line,char instr,symbol test,symbol data,symbol plus) { int x; printf("%02x: ",line); for(x=8;x;x/=2) putchar((instr & x)?'1':'0'); putchar(' '); for(x=8;x;x/=2) putchar((test & x)?'1':'0'); putchar(' '); for(x=16;x;x/=2) putchar((data & x)?'1':'0'); putchar(' '); putchar((plus & 1024)?'1':'0'); putchar(' '); for(x=512;x>4;x/=2) putchar((plus & x)?'1':'0'); putchar(' '); for(x=4;x;x/=2) putchar((plus & x)?'1':'0'); putchar('\n'); } int assemble(void) { char buf[255],line,quit; int s,instr; symbol test,data,plus; if(print_symboltable) { for(s=0;s (%i) \"%s\"\n",instr,buf); */ } while(instr==-1); if((s=next_token(buf))==EOF) { fprintf(stderr,"Parse error on line %u:\n\tUnexpected end of file.\n\n",source_line); return -1; } s=match_symbol(buf); test=(s==-1?parse_value(buf):symbol_values[s]); if((s=next_token(buf))==EOF) { fprintf(stderr,"Parse error on line %u:\n\tUnexpected end of file.\n\n",source_line); return -1; } s=match_symbol(buf); data=(s==-1?parse_value(buf):symbol_values[s]); if((s=next_token(buf))==EOF) { fprintf(stderr,"Parse error on line %u:\n\tUnexpected end of file.\n\n",source_line); return -1; } s=match_symbol(buf); plus=(s==-1?parse_value(buf):symbol_values[s]); if(print_mnemonics) printf("%02x\t%s\t%x\t%x\t%x\n",line,mnemonics[instr],test,data,plus); else print_binary(line,instr,test,data,plus); line++; } return 1; } int main(int argc,char *argv[]) { int status,n; char *filename; if(argc<2) { fputs("You must specify a file name!\n\"am2910 -help\" for help.\n",stderr); return -1; } print_symboltable=0; print_mnemonics=0; filename=NULL; for(n=1;n\n\nUsage: am2910 [OPTION] [FILE]\n\nThe following options are supported:\n\n\t-h Display this help text\n\t-s Print out the symbol table\n\t-m Show mnemonics instead of binary digits\n"); return 1; } else if(strcmp("-s",argv[n])==0) print_symboltable=1; else if(strcmp("-m",argv[n])==0) print_mnemonics=1; else filename=argv[n]; } if((source=fopen(filename,"r"))==NULL) { fprintf(stderr,"Unable to open file '%s'.\n",filename); return -1; } source_line=1; build_symboltable(); rewind(source); source_line=1; status=assemble(); fclose(source); return status; }