SPCC Exp1
SPCC Exp1
Date of Performance: -
Date of Submission: -
__________________________________________
Practical Incharge
EXPERIMENT NO. 1
Theory:
An assembler is a translator that translates an assembler program into a conventional
machine language program. Basically, the assembler goes through the program one
line at a time, generates machine code for that instruction. Then the assembler proceeds
to the next instruction. In this way, the entire machine code program is created. For
most instructions this process works fine, for example for instructions that only
reference registers, the assembler can compute the machine code easily, since the
assembler knows where the registers are.
JMP LATER
...
...
LATER:
This is known as a forward reference. If the assembler is processing the file one line at
a time, then it doesn’t know where LATER is when it first encounters the jump
instruction. So, it doesn’t know if the jump is a short jump, a near jump or a far jump.
So, Assembler scan the code twice. The first time, just count how long the machine
code instructions will be, just to find out the addresses of all the labels. Also, create a
table that has a list of all the addresses and where they will be in the program. This
table is known as the symbol table. On the second scan, generate the machine code,
and use the symbol table to determine how far away jump labels are, and to generate
the most efficient instruction. This is known as a two-pass assembler. Each pass scans
the program, the first pass generates the symbol table and the second pass generates the
machine code. I have created a listing of an assembler program that has the machine
code listed, and the symbol table listed.
Program:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
void passOne();
void passTwo();
int isNumber(const char *str);
int main()
{
passOne(); //Symbol formation
passTwo();
return 0;
}
void passOne()
{
char label[10], opcode[10], opr1[10], opr2[10], start;
int loc;
if(strcmp(opcode, "START")==0)
{
loc = atoi(opr1); #atoi function is present in stdlib.h library and converts the characters to num
start = 000;
fprintf(output, "%d\t%s\t%s\t%s\t%s\n", start, label, opcode, opr1, opr2);
fscanf(input, "%s\t%s\t%s\t%s", label, opcode, opr1, opr2);
}
else {
loc=1;
}
while(strcmp(opcode,"END")!=0)
{
fprintf(output, "%d\t%s\t%s\t%s\t%s\n", loc, label, opcode, opr1, opr2);
if( (strcmp(label, "**")!= 0) && (strcmp(opcode,"EQU")!=0) )
{
fprintf(symtab, "%d\t%s\n", loc, label);
}
if(strcmp(opcode,"EQU")==0)
{
fprintf(symtab, "%s\t%s\n", opr1, label);
}
if(strcmp(opcode,"ORIGIN")==0)
{
loc=atoi(opr1)-1;
}
loc=loc+1;
fscanf(input, "%s\t%s\t%s\t%s", label, opcode, opr1, opr2);
}
fprintf(output, "%d\t%s\t%s\t%s\t%s\n", loc, label, opcode, opr1, opr2);
fclose(input);
fclose(optab);
fclose(output);
fclose(symtab);
void passTwo()
{
char label[10], opcode[10], opr1[10], opr2[10], symbol[10], value[10];
FILE *out, *input, *opc, *sym;
input=fopen("input.txt", "r");
opc=fopen("opcfile.txt", "r");
sym=fopen("symbol.txt", "r");
out=fopen("MachineCode.txt", "w");
//for opcode
fseek(opc, 0, SEEK_SET);
while(fscanf(opc, "%s\t%s\n", symbol, value)==2)
{
if(strcmp(opcode, symbol)==0)
{
strcpy(opcode, value);
break;
}
}
//for operand 1
if(!isNumber(opr1))
{
//Search in opcode table
fseek(opc, 0, SEEK_SET);
while(fscanf(opc, "%s\t%s\n", symbol, value)==2)
{
if(strcmp(opr1, symbol)==0)
{
strcpy(opr1, value);
break;
}
}
}
//for operand 2
if(!isNumber(opr2) || strcmp(opr2, "**")!=0)
{
fseek(opc, 0, SEEK_SET);
while(fscanf(opc, "%s\t%s\n", symbol, value)==2)
{
if(strcmp(opr2, symbol)==0)
{
strcpy(opr2, value);
break;
}
}
//Search in symbol table
fseek(sym, 0, SEEK_SET);
while (fscanf(sym, "%s\t%s\n", value, symbol) == 2)
{
if (strcmp(opr2, symbol) == 0)
{
strcpy(opr2, value);
break;
}
}
}
}
}
if (!isdigit(str[i])) {
return 0;
}
}
return 1;
}
Output:
Input Files:
File generated after Pass One of Two Pass Assembler: