SIMULATION OF ONE PASS ASSEMBLER
PROGRAM CODING:-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
struct memory
{
int content[0x50];
int startingoffset;
};
struct OPTABentry
{
char mnemonic[5];
int opcode;
};
struct OPTAB
{
struct OPTABentry *entries;
int numberofentries;
};
struct SYMTABentry
{
char symbolname[15];
int address;
int forwardreferencelist[20];
int numberofforwardreferences;
};
struct SYMTAB
{
struct SYMTABentry entries[1000];
int numberofentries;
};
void displaymemory(struct memory *mem);
void displaysymboltable(struct SYMTAB *symtable);
void updateforwardreferencelist(struct SYMTAB *symtab,char *symbolname,int faddress,struct memory*);
int insertintosymboltable(struct SYMTAB *symtab,char *symbolname,int address,struct memory *mem);
int getString(int number,char buffer[]);
struct memory* creatememory(int startingoffset)
{
int i;
struct memory *temp = (struct memory *)malloc(sizeof(struct memory));
temp->startingoffset = startingoffset;
for(i=0;i<0x50;i++)
temp->content[i] = 0x00;
return temp;
}
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;
}
void updateforwardreferencelist(struct SYMTAB *symtab,char *symbolname,int faddress,struct memory *mem)
{
int i,flag = 0;;
for(i=0;i<symtab->numberofentries;i++)
if(strcasecmp(symtab->entries[i].symbolname,symbolname) == 0)
{
flag = 1;
symtab->entries[i].forwardreferencelist[symtab->entries[i].numberofforwardreferences++] = faddress;
}
if(flag == 0)
{
insertintosymboltable(symtab,symbolname,-1,NULL);
updateforwardreferencelist(symtab,symbolname,faddress,mem);
}
printf("\nUpdating forward reference list for %s\n",symbolname);
displaysymboltable(symtab);
displaymemory(mem);
}
int insertintosymboltable(struct SYMTAB *symtab,char *symbolname,int address,struct memory *mem)
{
int i,j,temp;
char buffer[7];
for(i=0;i<symtab->numberofentries;i++)
{
if(strcasecmp(symtab->entries[i].symbolname,symbolname) == 0)
{
if(symtab->entries[i].address >=0)
return -1;
symtab->entries[i].address = address;
j=getString(address,buffer);
buffer[j]='\0';
printf("\nResolving forward references for %s\n ",symbolname);
for(j=0;j<symtab->entries[i].numberofforwardreferences;j++)
{
temp = symtab->entries[i].forwardreferencelist[j];
mem->content[temp-mem->startingoffset] = mem->content[temp-mem->startingoffset]|((address & 0xFF00) >> 8);
mem->content[temp+1-mem->startingoffset] = (mem->content[temp+1 -mem->startingoffset]|address) & 0x00FF;
}
symtab->entries[i].numberofforwardreferences = 0;
displaymemory(mem);
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()
{
int i;
struct SYMTAB *newtab = (struct SYMTAB*)malloc(sizeof(struct SYMTAB));
newtab->numberofentries = 0;
for(i=0;i<1000;i++)
newtab->entries[i].numberofforwardreferences =0;
return newtab;
}
int getString(int number,char buffer[])
{
sprintf(buffer,"%6X",number);
return strlen(buffer);
}
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;
}
void displaysymboltable(struct SYMTAB *symtable)
{
int i=0;
int j=0;
printf("\nSymbol Table:\n");
printf("\tSymbol\t\tAddress\t\tForward Ref List\n");
for(;i<symtable->numberofentries;i++)
{
printf("\t%s\t\t%0X\t\t",symtable->entries[i].symbolname,symtable->entries[i].address);
for(j=0;j<symtable->entries[i].numberofforwardreferences;j++)
{
printf("%6X",symtable->entries[i].forwardreferencelist[j]);
if(j != symtable->entries[i].numberofforwardreferences - 1)
printf(" ---> ");
}
printf("\n");
}
}
//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,struct memory *mem)
{
int i,numberofwords=1,j;
char word1[10],word2[10],word3[20],buffer[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)
{
mem->content[address-mem->startingoffset] = getopcode(optab,line);
mem->content[address+1-mem->startingoffset] = 0x00;
mem->content[address+2-mem->startingoffset] = 0x00;
return 0;
}
else
return -1;
}
if(numberofwords == 2)
{
sscanf(line,"%s %s",word1,word2);
i=0;
if(strcasecmp(word1,"START") == 0)
{
if(*startaddress >= 0)
return -5;
*startaddress = strtol(word2,NULL,16);
return 0;
}
if(getopcode(optab,word1) >= 0)
{
if(getopcode(optab,word2) >= 0)
return -3;
else
{
mem->content[address-mem->startingoffset] = getopcode(optab,word1);
if(strchr(word2,',') != NULL)
{
j=0;
while(word2[j]!=',')
{
buffer[j] = word2[j];
j++;
}
buffer[j]='\0';
if(getaddress(symtab,buffer) >= 0)
{
mem->content[address+1-mem->startingoffset] = ((getaddress(symtab,buffer) & 0xFF00) >> 8)|0x80;
mem->content[address+2-mem->startingoffset] = (getaddress(symtab,buffer) & 0x00FF);
}
else
{
printf("\nParsing Line: %s\n",line);
printf("\nEncountered forward reference for %s\n",buffer);
updateforwardreferencelist(symtab,buffer,address+1,mem);
mem->content[address+1-mem->startingoffset] = 0x80;
}
}
else
{
if(getaddress(symtab,word2) >= 0)
{
mem->content[address+1-mem->startingoffset] = (getaddress(symtab,word2) & 0xFF00) >> 8;
mem->content[address+2-mem->startingoffset] = getaddress(symtab,word2) & 0x00FF;
}
else
{
printf("\nParsing Line: %s\n",line);
printf("\nEncountered forward reference for %s\n",word2);
updateforwardreferencelist(symtab,word2,address+1,mem);
}
}
return 0;
}
}
else
{
if(strcasecmp(word2,"RSUB") == 0 && *startaddress >= 0)
{
if(insertintosymboltable(symtab,word1,address,mem)>0)
{
sscanf(line,"%s %s",word1,word2);
mem->content[address-mem->startingoffset] = getopcode(optab,word2);
mem->content[address+1-mem->startingoffset] = 0x00;
mem->content[address+2-mem->startingoffset] = 0x00;
return 0;
}
else
return -2;
}
else if(strcasecmp(word2,"START") == 0)
{
if(*startaddress > 0)
return -5;
*startaddress = 0;
return 0;
}
else
return -1;
}
}
if(numberofwords == 3)
{
i=0;
sscanf(line,"%s %s %s",word1,word2,word3);
if(getopcode(optab,word1) == -1)
{
if(strcasecmp(word2,"START") == 0)
{
if(*startaddress > 0)
return -5;
*startaddress = strtol(word3,NULL,16);
return 0;
}
if(getopcode(optab,word2) >= 0)
{
if(getopcode(optab,word3) == -1 && *startaddress > 0)
{
if(insertintosymboltable(symtab,word1,address,mem)>0)
{
mem->content[address-mem->startingoffset] = getopcode(optab,word2);
if(strchr(word3,',') != NULL)
{
j=0;
while(word3[j]!=',')
{
buffer[j] = word3[j];
j++;
}
buffer[j]='\0';
if(getaddress(symtab,buffer) >= 0)
{
mem->content[address+1-mem->startingoffset] = ((getaddress(symtab,buffer) & 0xFF00) >> 8)|0x80;
mem->content[address+2-mem->startingoffset] = (getaddress(symtab,buffer) & 0x00FF);
}
else
{
printf("\nParsing Line: %s\n",line);
printf("\nEncountered forward reference for %s\n",buffer);
updateforwardreferencelist(symtab,buffer,address+1,mem);
mem->content[address+1-mem->startingoffset] = 0x80;
mem->content[address+2-mem->startingoffset] = 00;
}
}
else
{
if(getaddress(symtab,word3) >= 0)
{
mem->content[address+1-mem->startingoffset] = (getaddress(symtab,word3) & 0xFF00) >> 8;
mem->content[address+2-mem->startingoffset] = getaddress(symtab,word3) & 0x00FF;
}
else
{
printf("\nParsing Line: %s\n",line);
printf("\nEncountered forward reference for %s\n",word3);
updateforwardreferencelist(symtab,word3,address+1,mem);
mem->content[address+1-mem->startingoffset] = 0x00;
mem->content[address+2-mem->startingoffset] = 0x00;
}
}
return 0;
}
else
return -2;
}
}
return -3;
}
else
return -1;
}
return -1;
}
int directivescanner(struct SYMTAB *symtab,char *line,int address,struct memory *m)
{
int i,numberofwords=1,tempaddress,j;
char word1[10],word2[10],word3[20],buffer[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)
{
sscanf(line,"%s %s %s",word1,word2,word3);
i=0;
if(strcasecmp(word2,"RESW") ==0)
{
insertintosymboltable(symtab,word1,address,m);
return (address+(atoi(word3)*3));
}
else if(strcasecmp(word2,"RESB") == 0)
{
insertintosymboltable(symtab,word1,address,m);
return (address+atoi(word3));
}
else if(strcasecmp(word2,"WORD") == 0)
{
insertintosymboltable(symtab,word1,address,m);
m->content[address-m->startingoffset] = (strtol(word3,NULL,16) & 0xFF0000);
m->content[address+1-m->startingoffset] = (strtol(word3,NULL,16) & 0x00FF00);
m->content[address+2-m->startingoffset] = strtol(word3,NULL,16) & 0x0000FF;
return (address+3);
}
else if(strcasecmp(word2,"BYTE") == 0)
{
insertintosymboltable(symtab,word1,address,m);
i=0;
j = strlen(word3);
tempaddress = address;
if(word3[0] == 'C' || word3[0] =='c')
{
for(i=2;i<j-1;i++)
buffer[i-2] = word3[i];
buffer[i-2]='\0';
address = address + strlen(buffer);
for(i=0;i<strlen(buffer);i++)
m->content[tempaddress+i-m->startingoffset] = buffer[i];
}
else if(word3[0] == 'X' || word3[0] =='x')
{
for(i=2;i<j-1;i++)
buffer[i-2] = word3[i];
buffer[i-2]='\0';
address = address + strlen(buffer)/2;
if(strlen(buffer)%2 != 0)
{
sprintf(buffer,"0%s",buffer);
address++;
}
for(i=0;i<strlen(buffer)-1;i+=2,tempaddress++)
{
if(buffer[i] >= 48 && buffer[i]<=57)
m->content[tempaddress-m->startingoffset] = (buffer[i]-48) << 4;
else if(buffer[i] >=65 && buffer[i]<=70)
m->content[tempaddress-m->startingoffset] = (buffer[i]-55) << 4;
if(buffer[i+1] >= 48 && buffer[i+1]<=57)
m->content[tempaddress-m->startingoffset] += buffer[i+1]-48;
else if(buffer[i+1] >=65 && buffer[i+1]<=70)
m->content[tempaddress-m->startingoffset] += buffer[i+1]-55;
}
}
else
return -1;
return (address);
}
else
return -1;
}
else
return -1;
}
struct memory* assembleprogram(char *filename)
{
FILE *fd = fopen(filename,"r");
int LOCCTR = -1;
char *line;
int start = 0, end = 0, error = 0,status;
struct OPTAB *optable = getoptable();
struct SYMTAB *symtab = getsymboltable();
struct memory *mem;
if(fd < 0 )
printf("\n error: file %s could not be opened\n",filename);
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] == ' '))
{
end = 1;
}
else
{
status = standardscanner(optable,symtab,line,LOCCTR,&LOCCTR,mem);
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,mem);
if(status > 0)
{
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)
{
mem = creatememory(LOCCTR);
start = 1;
}
else
{
LOCCTR = LOCCTR + 0x3;
}
}
}
line = getlinefromfile(fd);
}
fclose(fd);
displaysymboltable(symtab);
if(error == 0)
return mem;
}
return NULL;
}
void displaymemory(struct memory *mem)
{
int i;
printf("\nMemory Map:\n");
for(i=0;i<0x50;i++)
{
if(i%4 == 0)
printf("\t");
if(i%0x10 == 0)
printf("\n%04X\t",mem->startingoffset+i);
printf("%02X",mem->content[i]);
}
printf("\n\n");
}
int main (int argc, char *argv[])
{
char filename[256];
struct memory *mem;
printf("\nEnter the name of the file to be assembled: ");
scanf("%s",filename);
mem = assembleprogram(filename);
displaymemory(mem);
return 0;
}
SAMPLE INPUT FILE:-
MOVE START 1000
.
ALPHA RESW 1
BETA RESB 2
FIVE WORD 5
CHARZ BYTE C'F1'
C2 BYTE X'F1'
C1 RESB 1
.
.
FIRST LDA FIVE
STA UNO
LDCH UNO
STL UNO,X
UNO LDCH CHARZ
STCH C1,x
.LABEL LDA
END MOVE