Monday, October 24, 2011

SYSTEM SOFTWARE LAB-SIMULATION OF PASS-1 OF A 2-PASS ASSEMBLER

             SIMULATION OF PASS-1 OF A 2-PASS ASSEMBLER


PROGRAM CODE:-

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>


struct OPTABentry
{
char mnemonic[5];
int opcode;
};


struct OPTAB
{
struct OPTABentry *entries;
int numberofentries;
};


struct SYMTABentry
{
char symbolname[15];
int address;
};


struct SYMTAB
{
struct SYMTABentry entries[1000];
int numberofentries;
};


int getopcode(struct OPTAB *optable,char *mnemonic)
{
int i;
for(i=0;i<optable->numberofentries;i++)
{
if(strcasecmp(optable->entries[i].mnemonic,mnemonic) == 0)
return optable->entries[i].opcode;
}
return -1;
}


int getaddress(struct SYMTAB *symtab,char *symbolname)
{
int i;
for(i=0;i<symtab->numberofentries;i++)
{
if(strcasecmp(symtab->entries[i].symbolname,symbolname) == 0)
return symtab->entries[i].address;
}
return -1;
}


int insertintosymboltable(struct SYMTAB *symtab,char *symbolname,int address)
{
if(getaddress(symtab,symbolname) > 0)
return -1;
strcpy(symtab->entries[symtab->numberofentries].symbolname,symbolname);
symtab->entries[symtab->numberofentries].address = address;
symtab->numberofentries++;
return 1;
}


struct OPTAB* createoptable(char mnemonics[][6],int opcode[],int n)
{
int i;
struct OPTAB* optable = (struct OPTAB*)malloc(sizeof(struct OPTAB));
optable->entries = (struct OPTABentry*)malloc(sizeof(struct OPTABentry)*n);
optable->numberofentries = n;
for(i=0;i<n;i++)
{
strcpy(optable->entries[i].mnemonic,mnemonics[i]);
optable->entries[i].opcode = opcode[i];
}
return optable;
}


struct OPTAB* getoptable()
{
char mnemonics[][6] = {"ADD\0","AND\0","COMP\0","DIV\0","J\0","JEQ\0","JGT\0","JLT\0","JSUB\0","LDA\0","LDCH\0","LDL\0","LDX\0","MUL\0","OR\0","RD\0","RSUB\0","STA\0","STCH\0","STL\0","STSW\0","STX\0","SUB\0","TD\0","TIX\0","WD\0"};
int opcode[] = {0x18,0x40,0x24,0x3C,0x30,0x34,0x38,0x48,0x00,0x50,0x08,0x04,0x20,0x44,0xD8,0x4C,0x0C,0x54,0x14,0xE8,0x10,0x1C,0xE0,0x2C,0xDC};
return createoptable(mnemonics,opcode,26);
}


struct SYMTAB* getsymboltable()
{
struct SYMTAB *newtab = (struct SYMTAB*)malloc(sizeof(struct SYMTAB));
newtab->numberofentries = 0;
return newtab;
}


//returns -1 for invalid mnemonic
//returns -2 for duplicate label
//returns -3 for invalid label name, label name is a mnemonic
//returns -4 for comments or empty lines
//returns -5 for redundant START instructions
//returns 0 on successful scan
int standardscanner(struct OPTAB *optab,struct SYMTAB *symtab,char *line,int address,int *startaddress)
{
int position=0,i,numberofwords=1;
char buffer[20],temp[20],temp2[20];
if(line[0] == '.' || line[0]=='\0')
return -4;
for(i=0;line[i] != '\0';i++)
{
if(line[i] == ' ' || line[i] == '\t')
numberofwords++;
}
if(numberofwords == 1)
{
if(strcasecmp(line,"RSUB") == 0)
return 0;
else
return -1;
}
if(numberofwords == 2)
{
i=0;
position =0 ;
while(line[position]!= ' ' && line[position]!='\t' && line[position] != '\0')
buffer[i++] = line[position++];
buffer[i] = '\0';
position++;
strcpy(temp,buffer);
i=0;
while(line[position]!= ' ' && line[position]!='\t' && line[position] != '\0')
buffer[i++] = line[position++];
buffer[i] = '\0';
position++;
if(strcasecmp(temp,"START") == 0)
{
if(*startaddress >= 0)
return -5;
*startaddress = strtol(buffer,NULL,16);
return 0;
}
if(getopcode(optab,temp) >= 0)
{
if(getopcode(optab,buffer) >= 0)
return -3;
else
return 0;
}
else
{
if(strcasecmp(buffer,"RSUB") == 0 && *startaddress >= 0)
return insertintosymboltable(symtab,temp,address)>0?0:-2;
else if(strcasecmp(buffer,"START") == 0)
{
if(*startaddress > 0)
return -5;
*startaddress = 0;
return 0;
}
else
return -1;
}
}
if(numberofwords == 3)
{
i=0;
position =0 ;
while(line[position]!= ' ' && line[position]!='\t' && line[position] != '\0')
buffer[i++] = line[position++];
buffer[i] = '\0';
position++;
strcpy(temp,buffer);
i=0;
while(line[position]!= ' ' && line[position]!='\t' && line[position] != '\0')
buffer[i++] = line[position++];
buffer[i] = '\0';
position++;
strcpy(temp2,buffer);
i=0;
while(line[position]!= ' ' && line[position]!='\t' && line[position] != '\0')
buffer[i++] = line[position++];
buffer[i] = '\0';
position++;
if(getopcode(optab,temp) == -1)
{
if(strcasecmp(temp2,"START") == 0)
{
if(*startaddress > 0)
return -5;
*startaddress = strtol(buffer,NULL,16);
return 0;
}
if(getopcode(optab,temp2) >= 0)
if(getopcode(optab,buffer) == -1 && *startaddress > 0)
return insertintosymboltable(symtab,temp,address)>0?0:-2;
return -3;
}
else
return -1;
}
return -1;
}


int directivescanner(struct SYMTAB *symtab,char *line,int address)
{
int position=0,i,numberofwords=1,tempaddress;
char buffer[20],temp[20];
if(line[0] == '.' || line[0]=='\0')
return 0;
for(i=0;line[i] != '\0';i++)
{
if(line[i] == ' ' || line[i] == '\t')
numberofwords++;
}
if(numberofwords == 3)
{
i=0;
position =0;
while(line[position]!= ' ' && line[position]!='\t' && line[position] != '\0')
buffer[i++] = line[position++];
buffer[i] = '\0';
position++;
strcpy(temp,buffer);
i=0;
while(line[position]!= ' ' && line[position]!='\t' && line[position] != '\0')
buffer[i++] = line[position++];
buffer[i] = '\0';
position++;
if(strcasecmp(buffer,"RESW") ==0)
{
i=0;
while(line[position]!= ' ' && line[position]!='\t' && line[position] != '\0')
buffer[i++] = line[position++];
buffer[i] = '\0';
position++;
insertintosymboltable(symtab,temp,address);
return (address+(atoi(buffer)*3));
}
else if(strcasecmp(buffer,"RESB") == 0)
{
i=0;
while(line[position]!= ' ' && line[position]!='\t' && line[position] != '\0')
buffer[i++] = line[position++];
buffer[i] = '\0';
position++;
insertintosymboltable(symtab,temp,address);
return (address+atoi(buffer));
}
else if(strcasecmp(buffer,"WORD") == 0)
{
insertintosymboltable(symtab,temp,address);
return (address+3);
}
else if(strcasecmp(buffer,"BYTE") == 0)
{
i=0;
while(line[position]!= ' ' && line[position]!='\t' && line[position] != '\0')
buffer[i++] = line[position++];
buffer[i] = '\0';
position++;
tempaddress = address;
if(buffer[0] == 'C' || buffer[0] =='c')
address = address + (i-3);
else if(buffer[0] == 'X' || buffer[0] =='x')
address = address + (int)ceil((double)(i-3.0)/2.0);
else
return -1;
insertintosymboltable(symtab,temp,tempaddress);
return (address);
}
else
return -1;
}
else
return -1;
}


char* getlinefromfile(FILE *file)
{
char ch='\0';
char previouschar='\0';
int position=0;
int stringstart=0;
char *buffer=(char*)malloc(sizeof(char)*1000);
while(ch != '\n')
{
if((ch = fgetc(file)) != EOF)
{
if(ch == '\'')
{
if(stringstart == 0)
stringstart=1;
else 
if(stringstart == 1)
stringstart = 0;
}
if(ch == '\n')
{
if(previouschar ==' ' || previouschar =='\t')
position--;
}
else
if(!(position == 0 && (ch==' '|| ch=='\t')))
if(!((previouschar == ' ' || previouschar == '\t') && (ch == ' ' || ch =='\t')) || stringstart==1)
{
if(ch == '\t')
ch = ' ';
previouschar = ch;
buffer[position++]=ch;
}
}
else
return NULL;
}
buffer[position]='\0';
return buffer;
}


struct SYMTAB* performpassone(char *filename,char *intermediatefilename)
{
FILE *fd = fopen(filename,"r");
FILE *interfd = fopen(intermediatefilename,"w");
int LOCCTR = -1;
char *line;
int start = 0, end = 0, error = 0,status;
struct OPTAB *optable = getoptable();
struct SYMTAB *symtab = getsymboltable();
if(fd < 0 )
printf("\n error: file %s could not be opened\n",filename);
else if(interfd < 0)
printf("\n error: file %s could not be created or opened\n",intermediatefilename);
else
{
line = getlinefromfile(fd);
while(line!=NULL && end!=1)
{
if((line[0]=='E' || line[0] == 'e') && (line[1]=='N' || line[1] == 'n') && (line[2]=='D' || line[2] == 'd') && (line[3]=='\0' || line[3] == '\t' || line[3] == ' '))
{
fprintf(interfd,"%s\n",line);
end = 1;
}
else
{
status = standardscanner(optable,symtab,line,LOCCTR,&LOCCTR);
if(status != 0)
{
if(status == -2)
{
printf("error:\t%s\n\tduplicate label\n",line);
error=end = 1;
}
else if(status == -1)
{
printf("error:\t%s\n\tnot an instruction\n",line);
error=end = 1;
}
else if(status == -3)
{
status = directivescanner(symtab,line,LOCCTR);
if(status > 0)
{
fprintf(interfd,"%0X %s\n",LOCCTR,line);
LOCCTR = status;
}
else
{
printf("\nerror :\t%s\n\t\tunable to assemble line\n",line);
error=end = 1;
}
}
else if(status == -5)
{
printf("\n%s\n",line);
printf("\nStart Instruction already encountered\n");
end = 1;
}
}
else
{
if(start == 0 && LOCCTR >0)
{
start = 1;
fprintf(interfd,"%s\n",line);
}
else
{
fprintf(interfd,"%0X %s\n",LOCCTR,line);
LOCCTR = LOCCTR + 0x3;
}
}
}
line = getlinefromfile(fd);
}
fclose(fd);
fclose(interfd);
if(error == 0)
return symtab;
}
return NULL;
}


void displaysymboltable(struct SYMTAB *symtable)
{
int i=0;
printf("\nSymbol Table:\n");
printf("\tSymbol\t\tAddress\n");
for(;i<symtable->numberofentries;i++)
{
printf("\t%s\t\t%0X\n",symtable->entries[i].symbolname,symtable->entries[i].address);
}
}


int main (int argc, char *argv[])
{
char filename[256];
char interfilename[256];
struct SYMTAB *symtab;
printf("\nEnter the name of the file to be assembled: ");
scanf("%s",filename);
printf("\nEnter name for intermediate file: ");
scanf("%s",interfilename);
symtab = performpassone(filename,interfilename);
if(symtab != NULL)
displaysymboltable(symtab);
return 0;
}

SAMPLE-INPUT-FILE:-
MOVE START 1000
FIRST LDA FIVE
STA ALPHA
LDCH CHARZ
STCH C1
.LABEL LDA
ALPHA RESW 1
FIVE WORD 5
CHARZ BYTE X'F1'
C1 RESB 1

No comments:

Post a Comment