Monday, October 24, 2011

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

                      
                SIMULATION OF PASS-2 OF A 2-PASS ASSEMBLER
PROGRAM CODE:-
MAIN FILE:-

#include "PASSONE.h"
#include <math.h>


struct HeaderRecord
{
char programname[6];
int startingaddress;
int lengthofcode;
};


struct TextRecord
{
int startingaddress;
int lengthofcode;
char *objectcode;
};


void writetextrecord(FILE *file,struct TextRecord* text)
{
int i=0;
fprintf(file,"T^%06X^%02X",text->startingaddress,text->lengthofcode);
for(;i<text->lengthofcode*2;i++)
{
if((i%6) == 0 && i!=text->lengthofcode*2-1)
fprintf(file,"^");
fprintf(file,"%c",text->objectcode[i]);
}
fprintf(file,"\n");
}


void writeheaderrecord(FILE *file,struct HeaderRecord *header)
{
fprintf(file,"H^%s^%06X^%06X\n",header->programname,header->startingaddress,header->lengthofcode);
}


void writeendrecord(FILE *file,int startingaddress)
{
fprintf(file,"E^%06X\n",startingaddress);
}


void performpasstwo(struct OPTAB *optab,struct SYMTAB *symtab,char *interfilename,char *outputfilename,char *listingfilename,int lengthofcode,int startaddress)
{
FILE *interfile = fopen(interfilename,"r"),*outputfile = fopen(outputfilename,"w"),*listingfile = fopen(listingfilename,"w");
char *line,objectcode[20],word1[20],word2[20],word3[20],word4[20],record[10000],buffer[20];
int i,numberofwords,j,createnewrecord=0,opcode;
struct HeaderRecord *header = (struct HeaderRecord *)malloc(sizeof(struct HeaderRecord));
struct TextRecord *textrecord;
line = getlinefromfile(interfile);
sscanf(line,"%s",word1);
if(strcasecmp(word1,"START") == 0)
sprintf(header->programname,"NONAME");
else
sprintf(header->programname,"%s",word1);
header->startingaddress =  startaddress;
header->lengthofcode = lengthofcode;
writeheaderrecord(outputfile,header);

textrecord = (struct TextRecord*)malloc(sizeof(struct TextRecord));
textrecord->startingaddress = startaddress;
textrecord->lengthofcode = 0;

while((line=getlinefromfile(interfile))!=NULL)
{
objectcode[0]='\0';
sscanf(line,"%s %s",word1,word2);
if(textrecord->startingaddress == -1)
textrecord->startingaddress = strtol(word1,NULL,16);


numberofwords=1;
for(j=0;line[j]!='\0';j++)
if(line[j] == ' ')
numberofwords++;


if(numberofwords == 2)
{
if(getopcode(optab,word2) >= 0)
{
sprintf(objectcode,"%02X0000",getopcode(optab,word2));
textrecord->lengthofcode+=6;
}
}
else if(numberofwords == 3)
{
sscanf(line,"%s %s %s",word1,word2,word3);
if(getopcode(optab,word2) == -1)
{
if(getopcode(optab,word3) >=0)
{
sprintf(objectcode,"%02X0000",getopcode(optab,word3));
textrecord->lengthofcode+=6;
}
}
else
{
opcode = getopcode(optab,word2);
if(strchr(word3,',') == NULL)
sprintf(objectcode,"%02X%04X",opcode,getaddress(symtab,word3));
else
{
j=0;
while(word3[j]!=',')
{
buffer[j] = word3[j];
j++;
}
buffer[j]='\0';
sprintf(objectcode,"%02X%04X",opcode,getaddress(symtab,buffer)|0x8000);
}
textrecord->lengthofcode+=6;
}
}
else if(numberofwords == 4)
{
sscanf(line,"%s %s %s %s",word1,word2,word3,word4);
if(getopcode(optab,word3) ==-1)
{
if(strcasecmp(word3,"RESW") == 0)
createnewrecord = 1;
else if(strcasecmp(word3,"RESB") ==0)
createnewrecord = 1;
else if(strcasecmp(word3,"WORD") == 0)
{
sprintf(objectcode,"%06X",(unsigned int)strtol(word4,NULL,16));
textrecord->lengthofcode+=6;
}
else if(strcasecmp(word3,"BYTE") == 0)
{
j = strlen(word4);
if(word4[0] == 'X' || word4[0] == 'x')
{
for(i=2;i<j-1;i++)
buffer[i-2] = word4[i];
buffer[i-2]='\0';
if(strlen(buffer)%2 != 0)
{
i=strlen(buffer);
buffer[i] = buffer[i-1];
buffer[i+1]='\0';
buffer[i-1] = '0';
}
strcat(objectcode,buffer);
textrecord->lengthofcode+= strlen(buffer);
}
else
{
for(i=2;i<j-1;i++)
sprintf(objectcode,"%s%02X",objectcode,word4[i]);
textrecord->lengthofcode+=(j-3)*2;
}
}
}
else
{
opcode = getopcode(optab,word3);
if(strchr(word4,',') == NULL)
sprintf(objectcode,"%02X%04X",opcode,getaddress(symtab,word4));
else
{
j=0;
while(word4[j]!=',')
{
buffer[j] = word4[j];
j++;
}
buffer[j]='\0';
sprintf(objectcode,"%02X%04X",opcode,getaddress(symtab,buffer)|0x8000);
}
textrecord->lengthofcode+=6;
}
}
fprintf(listingfile,"%s %s\n",line,objectcode);
if(createnewrecord == 0)
strcat(record,objectcode);
else
{
record[textrecord->lengthofcode]='\0';
textrecord->objectcode = (char *)malloc(sizeof(char)*(textrecord->lengthofcode+1));
strcpy(textrecord->objectcode,record);
textrecord->lengthofcode /= 2;
if(strlen(textrecord->objectcode) > 0)
writetextrecord(outputfile,textrecord);
textrecord->lengthofcode = 0;
textrecord->startingaddress = -1;
free(textrecord->objectcode);
createnewrecord = 0;
record[0] = '\0';
}
}
writeendrecord(outputfile,startaddress);
fclose(outputfile);
fclose(interfile);
fclose(listingfile);
}


int main (int argc, char *argv[])
{
char filename[256];
char interfilename[256];
char objectprogramfilename[256];
char listingfilename[256];
int lengthofcode=-1,startingaddress;
struct SYMTAB *symtab;
struct OPTAB *optable = getoptable();
printf("\nEnter the name of the file to be assembled: ");
scanf("%s",filename);
printf("\nEnter name for intermediate file: ");
scanf("%s",interfilename);
printf("\nEnter name for Object Program: ");
scanf("%s",objectprogramfilename);
printf("\nEnter name for Listing File: ");
scanf("%s",listingfilename);
symtab = performpassone(filename,interfilename,&lengthofcode,&startingaddress);
if(symtab != NULL)
{
displaysymboltable(symtab);
printf("\nPerforming Pass two ...\n");
performpasstwo(optable,symtab,interfilename,objectprogramfilename,listingfilename,lengthofcode,startingaddress);
printf("\nProgram Assembled.\nOutput File: %s\n",objectprogramfilename);
}
return 0;
}

<PASSONE.h> FILE:-
#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,0x28,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,int *lengthofcode,int *startingaddress)
{
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;
*startingaddress = LOCCTR;
fprintf(interfd,"%s\n",line);
}
else
{
fprintf(interfd,"%0X %s\n",LOCCTR,line);
LOCCTR = LOCCTR + 0x3;
}
}
}
line = getlinefromfile(fd);
}
fclose(fd);
fclose(interfd);
*lengthofcode = LOCCTR-*startingaddress;
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);
}
}

INPUT-FILE:-
MOVE START 1000
FIRST LDA FIVE
STA UNO
UNO LDCH CHARZ
STCH C1,x
.LABEL LDA
ALPHA RESW 1
BETA RESB 2
FIVE WORD 5
CHARZ BYTE C'F1'
C2 BYTE       X'F1'
C1 RESB 1
END MOVE


No comments:

Post a Comment