//----------------------------------------------------------
// Title : Design suitable data structures and implement pass-I
// of a two-pass assembler for 8 bit microprocessor/
// pseudo-machine. Implementation should consist of a few
// instructions from each category and few assembler directives
//----------------------------------------------------------
//header file declaration
#include<stdio.h>
#include<conio.h>
#include<string.h>
// global declaration of variables
char line[100]; // line ( asm file )
int lc,fck=0, flagl=0; // lc=location counter , fck = work as flag, flagl=flag for label
int indexir=0; // index for intermadiate code
int indexsym=0; // index for symbol table
int mindex=0; // index for mnemonic table
int lindex=0; // index for litral table
// struct for literal table
struct littable
{
int add, val;
}l[50];
// struct for symbol table
struct symtable
{
char sname[50];
int add, length1;
}s[50];
// struct for mnemonic opcode table
struct mot
{
int addr, len;
char code[20], hexcode[20];
}m[50];
//struct for Intermediate code
struct ir
{
int add;
char hexcode[50];
char op[50];
}ic[50];
// struct for pseudo opcode table
struct pseudo
{
char inst;
int length;
};
// functions declatations
void opid(char aaa[50]);
void opcproc(char aa[50]);
void chekps(char a[20]);
void mneopchk(char b[20]);
void psuproc();
// this function is use to check whether operand is register. or not and making entry in symbol table if it is not register.
void opid(char aaa[50])
{ // aaa[50]= it contains op1 or op2
int i;
if(strcmp(aaa,"AREG")==0)
{
// printf("AREG..!");
}
else if(strcmp(aaa,"BREG")==0)
{
// printf("BREG..!");
}
else if(strcmp(aaa,"CREG")==0)
{
// printf("CREG..!");
}
else if(strcmp(aaa,"DREG")==0)
{
// printf("DREG..!");
}
else if(aaa[0]==\'=\') //if op2 is literal then check whether first character of string2 i.e. op2 is \'=\' or not if it is present then
{
l[lindex].val=aaa[2]; // put that literal value in index of literal table
lindex++; // increment the index of literal table
}
else
{
for(i=0;i=indexsym;i++) // use \'for loop\' upto index of symbol table that is last entry of the symbol table
{
if(strcmp(s[i].sname,aaa)==0) // checking the entry of operand in symbol table
{
// if it is already exists then break this condn
break;
}
else
{
indexsym++; // increment the index of symbol table
strcpy(s[indexsym].sname,aaa); // create new entry for operand in symbol table
}
}
}
}
// this function is use for symbol checking
void symchk()
{
int i, templen1;
char label[10], opc[10], field[50];
// label=label, opc=opcode, field = operands
sscanf(line,"%s%s%s",label,opc,field); // split the line into label, opc, field
flagl=1; // assign flagl=1 if label is present.
chekps(opc); // case 2 : label \'opcode\' op1,op2 AND AGAIN check the \'opc\' with pseudo and mnemonic opcode and if it is not there then again return to symchk fn.
if(fck==1) // if flag=1 i.e. if it is pseudo code then
{
indexsym++; // preincrement the index of symbol table
fck=0; // first load 0 in flag \'fck\'
opcproc(field); // pass the operands present in \'field\' to opcode process
flagl=0; // again set flagl=0 for checking the label
strcpy(s[indexsym].sname,label); // copy label (name) into \'sname\' that is, this is new entry for symbol table
s[indexsym].add=lc-m[mindex-1].len; // decrement the value of lc to get the length of previous instruction
s[indexsym].length1=1; // set the length of label = 1
}
}
// this funtion is used to separate the operands (into op1 and op2)
void opcproc(char aa[50])
{
char op1[20], op2[20];
int flag3=0;
int i,j=0;
strcpy(ic[indexir].op,aa); // create entry for operand in intermediate code table
indexir++; // increment the index of intermediate code
for(i=0; i<strlen(aa); i++) // execute upto the length of array \'aa\' (operand)
{
if(aa[i] == \',\') // if separator found then copy remaining string to string2 i.e. op2 with the help of while loop
{
i++;
while(i<strlen(aa))
{
op2[j]=aa[i];
i++;
j++;
}
op2[j]=\'\\0\'; // to avoid garbage value , insert null char
opid(op2); // call this fn for checking whether op2 is regi. or not
break; // use for checking the all character in op2
}
else if(aa[i] == \' \') // if space is found then copy string to string1 i.e. op1 with the help of while loop
{
while(i<strlen(aa))
{
op1[i]=aa[i];
i++;
}
op1[i]=\'\\0\'; // to avoid garbage value , insert null char
opid(op1); // call this fn for checking whether op2 is regi. or not
break; // use for checking the all character in op2
}
else
{
op1[i]=aa[i]; // copy the whole string \'aa\' in op1
flag3++;
}
}
op1[flag3]=\'\\0\'; // use for checking the all character in op2
}
//this function is use for pseudo processing
void psuproc()
{
char ps[20]="START"; // declare ps as \'START\'
char s2[50], s3[20], s4[20]; // declare s2, s3 and s4 for first , second and third string of each line
int i,a,flag2=0;
sscanf(line,"%s%s",s2,s3); // separate the first and second string from line and insert into s2 and s3
if(strcmp(s2,ps)==0) // compare first string with ps i.e. \'START\' and if AFTER START \'DC\' OR ANY OTHER STRING IS PRESENT THEN error occurs ( here we are not handling the error )
{
lc=atoi(s3); // convert length (string) to integer
// if \'START\' is found then second string after \'START\' si compulsory \'lc\'
// load the value as initial value of \'lc\'
}
else if(strcmp(s3,"DS")==0) // check whether second string is DS or not
{
sscanf(line,"%s%s%s",s2,s3,s4); // separate first, second and third string from line and insert it into s2, s3 and s4
for(i=0;i<=indexsym;i++) // use \'for loop\' upto index of symbol table that is last entry of the symbol table
{
if(strcmp(s2,s[i].sname)==0) // check whether first string \'s2\' is already in the symbol table or not
{
flag2=1; // if flag2=1 then label is already present in symbol table
s[i].add=lc; // load value of lc into address field
a=atoi(s4); // convert third string \'s4\' into integer
a=a*4; // multiply value of \'a\'*4 to convert word into byte
s[i].length1=a; // load the value of \'a\' into length1 in symbol table
lc=lc+a; // load the new value of lc by adding value of \'a\' in the old value of \'lc\'
fck=0; // if DS or DC is processed , label should not be re-entered in the symbol table
break;
}
}
if(flag2==0) // if flag2=0 it is not found in symbol table thats why we create new entry for symbol table
{
indexsym++; // before entry, increment the index of the symbol table
strcpy(s[indexsym].sname,s2); // check whether first string \'s2\' is already in the symbol table or not
s[indexsym].add=lc; // load value of lc in address field of symbol table
a=atoi(s4); // convert operand (string ) to integer
a=a*4; // conversion of word to byte ( * 4 )
s[indexsym].length1=a; // load value of \'a\' in length field of symbol table
lc=lc+a; // update old value of lc with previous value of \'a\'
fck=0; // if DS or DC is processed , label should not be re-entered in the symbol table
}
}
// for DC , logic is same as above
else if(strcmp(s3,"DC")==0) // check whether second string is DS or not
{
sscanf(line,"%s%s%s",s2,s3,s4); // separate first, second and third string from line and insert it into s2, s3 and s4
for(i=0;i<=indexsym;i++) // use \'for loop\' upto index of symbol table that is last entry of the symbol table
{
if(strcmp(s2,s[i].sname)==0) // check whether first string \'s2\' is already in the symbol table or not
{
flag2=1; // if flag2=1 then label is already present in symbol table
s[i].add=lc; // load value of lc into address field
s[i].length1=4; // \'load by default 4\' in length field
lc=lc+4 ; // update value of lc \'by adding 4\'
fck=0; // if DS or DC is processed , label should not be re-entered in the symbol table
break;
}
}
if(flag2==0)
{
indexsym++; // before entry, increment the index of the symbol table
strcpy(s[indexsym].sname,s2); // check whether first string \'s2\' is already in the symbol table or not
s[indexsym].add=lc; // load value of lc into address field
s[indexsym].length1=4; // load value \'4\' in length field of symbol table
lc=lc+4; // update lc with adding \'4\' with old value of \'lc\'
fck=0; // if DS or DC is processed , label should not be re-entered in the symbol table
}
}
else if(strcmp(s2,"END")==0) // if END is found print all the data present is the table
{
printf("\\n\\n------------------------------------------------------");
printf("\\n\\t\\t MNEMONIC TABLE"); // print the Mnemonic Table
printf("\\n------------------------------------------------------");
printf("\\nOPCODE\\t\\tHEX CODE\\tLENGTH\\t\\tADDRESS");
for(i=0;i<mindex;i++) // execute \'for loop\' upto index of mnemonic table
{
printf("\\n%s\\t\\t%s\\t\\t%d\\t\\t%d",m[i].code,m[i].hexcode,m[i].len,m[i].addr);
}
printf("\\n\\n------------------------------------------------------");
printf("\\n\\t\\t SYMBOL TABLE"); // print the Symbol Table
printf("\\n------------------------------------------------------");
printf("\\nSYMBOL\\t\\tLENGTH\\t\\tADDRESS");
for(i=1;i<=indexsym;i++) // execute \'for loop\' upto index of symbol table
{
printf("\\n%s\\t\\t%d\\t\\t%d\\t",s[i].sname,s[i].length1,s[i].add);
}
printf("\\n\\n------------------------------------------------------");
printf("\\n\\t\\t LITERAL TABLE "); // print the Literal Code
printf("\\n------------------------------------------------------");
printf("\\nVALUE\\t\\tADDRESS");
for(i=0;i<lindex;i++) // execute \'for loop\' upto index of Literal table
{
l[i].add=lc; // load the value of \'lc\' in address field in literal table
lc=lc+4; // update the value of \'lc\' by adding 4 in old value
printf("\\n%c\\t\\t%d\\t",l[i].val,l[i].add); // print the actual value and address of the literal
}
printf("\\n\\n------------------------------------------------------");
printf("\\n\\t\\t INTERMEDIATE CODE "); // print the Intermediate Table
printf("\\n------------------------------------------------------");
printf("\\nADDRESS\\t\\tHEX CODE\\tOPREANDS");
for(i=0;i<indexir;i++) // execute \'for loop\' upto index of Intermediate Code
{
printf("\\n%d\\t\\t%s\\t\\t%s\\t",ic[i].add,ic[i].hexcode,ic[i].op);
}
}
}
// main function
int main()
{
int i;
char s1[100]; // s1=first symbol of first file
static const char filename[] = "asm.asm";
FILE *file = fopen ( filename, "r" ); // open asm file
clrscr();
if(file!=NULL) // check every line of asm file still EOF
{
while(fgets(line,sizeof line,file)!=NULL) // fetching first line ( if we use while loop ,then fetching each line upto EOF)
{
sscanf(line,"%s",s1); // separate first string from line and insert into s1
chekps(s1); // pass string s1 to check whether it is in pseudo code file or Mnemonic code file and if it is not in both table then it is in symbol table
}
}
fclose(file); // close the above file that is asm file
getch();
return 0;
}
// this fn is used for checking the string is present in Pseudo table or not
void chekps(char a[20])
{
char line1[100], ss1[20]; // line1= just for fetching the line from pseudo code file
// ss1[20]= it contain the first string of the line present in pseudo code
// a[20]= it contain the first string of the line in asm file
int flag=0;
static const char filename1[] = "pseudo.txt";
FILE *file1 = fopen ( filename1, "r" ); // open pseudo code file
while(fgets(line1,sizeof line1,file1)!=NULL) // fetching the line from pseudo code still EOF (if we use while loop ,then fetching each line upto EOF)
{
sscanf(line1,"%s",ss1); // separate the first string of line from pseudo code file and insert in \'ss1\'
if(strcmp(a,ss1)==0) // checking \'ss1\'(string from pseudo code file) with \'a\'(string from asm file)
{
flag=1; // if strings are matched the flag=1
psuproc(); // call this function for checking whether the string is START, DC, DS, and END or any other.
fclose(file1); // close the pseudo code file
}
}
if(flag==0) // if string is not found in pseudo code table ( POT ) then call to mnemonic function (MOT)
{
mneopchk(a); // pass the string to check whether it is mnemonic or not
fclose(file1); // close the pseudo code file
}
}
// this fn is used for checking the string is present in mnemonic table or not
void mneopchk(char b[20])
{
char line2[100], ss1[20], clen[20], opr[50];
// line2= just for fetching the line from mnemonic file
// clen= store the length
int flag1=0;
static const char filename2[] = "mnemonic.txt";
FILE *file2 = fopen ( filename2, "r" ); //open mnemonic opcode file
while(fgets(line2,sizeof line2,file2)!=NULL) // fetching the line from mnemonic code still EOF ( if we use while loop ,then fetching each line upto EOF)
{
sscanf(line2,"%s",ss1); // separate the first string of line from mnemonic code file and insert in \'ss2\'
if(strcmp(b,ss1)==0) // checking \'ss1\'(string from mnemonic code file) with \'b\'(string from asm file)
{
flag1=1; // if match found then flag1=1
fck=1;// declare this because to create entry for label after processing mnemonic and pseudo code
sscanf(line2,"%s%s%s",m[mindex].code,clen,m[mindex].hexcode);
//insert name in \'code\' , length in \'clen\' and hexcode in \'hexcode\'
m[mindex].addr=lc; // load value of lc to \'address field of mnemonic table\'
m[mindex].len=atoi(clen) ; // first convert the length from char array to integer and then load it into \'len\'
ic[indexir].add=lc; // load the value of lc to \'intermediate code\'
strcpy(ic[indexir].hexcode,m[mindex].hexcode); // create entry for hexcode in intermediate code i.e.
// copy the hexcode from MOT to IC
lc=lc+m[mindex].len; // increment the value of lc by adding old value of lc + length of the particular index
mindex++ ; // increment the index
if(flagl==0) // if string is not mnemonic then given string is operands ( op1,op2)
{
sscanf(line,"%s %s",ss1,opr); // separate the operands from the given line and inset into \'opr\'
opcproc(opr); // call this function to separate the opearands (opr) into op1 and op2
}
fclose(file2); // close the mnemonic code file
}
}
if(flag1==0) // if string is not found in \'pseudo\' and \'mnemonic\' then it is a symbol
{
symchk(b); // pass the first string of asm file to create entry for symbol table or updating.
fclose(file2); // close the mnemonic code file
}
}
// end of the program