0% found this document useful (0 votes)
25 views8 pages

SPCC Exp1

System programs and compiler construction experiments

Uploaded by

sanjanabhosle27
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
25 views8 pages

SPCC Exp1

System programs and compiler construction experiments

Uploaded by

sanjanabhosle27
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 8

EXPERIMENT NO.

Aim of the Experiment: Implementations of two pass Assembler.

Lab Outcome: Generate machine code by implementing two pass assemblers.

Date of Performance: -

Date of Submission: -

Implementatio Understanding Punctuality & Total


n (05) (05) Discipline (05) Marks
(15)

__________________________________________

Practical Incharge
EXPERIMENT NO. 1

Aim: Implementations of two pass Assembler

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.

Consider an assembler instruction like the following :

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.

Algorithm for pass 1:


Step 1: Start
Step 2: Initialize location counter to zero.
Step 3: Read the opcode field of the next instruction.
Step 4: Search opcode in pseudo-opcode table.
Step 5: If opcode is found in Pseudo Opcode Table
Step 5.1: If it is ‘DS’ or ‘DC’
Adjust location counter to proper alignment.
Assign length of data field to ‘L’
Go to step 9
Step 5.2: If it is ‘EQU’
Evaluate operand field
Assign value to symbol in label field
Go to step 3
Step 5.3: If it is ‘USING’ or ‘DROP’ Go to step 3
Step 5.4: If it is ‘END’
Assign storage locations to literals
Go to step 12
Step 6: Search opcode in Machine Opcode Table.
Step 7: Assign its length to ‘L’.
Step 8: Process any literals and enter them into the Literal Table.
Step 9: If the symbol is there in the label field, assign the current value of Location
Counter to the symbol.
Step 10: Location Counter = Location Counter + L.
Step 11: Go to step 3
Step 12: Stop.

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;

FILE *input, *output, *symtab, *optab;

input = fopen("input.txt", "r");


optab = fopen("opcfile.txt", "r");
output = fopen("output.txt", "w");
symtab = fopen("symbol.txt", "w");

fscanf(input, "%s\t%s\t%s\t%s", label, opcode, opr1, opr2);

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");

fscanf(input, "%s\t%s\t%s\t%s", label, opcode, opr1, opr2);


while(strcmp(opcode,"END")!=0)
{
if (strcmp(label, "**") != 0)
{
fseek(sym, 0, SEEK_SET);
while (fscanf(sym, "%s\t%s\n", value, symbol) == 2)
{
if (strcmp(label, symbol) == 0)
{
strcpy(label, value);
break;
}
}
}

//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;
}
}

//Search in symbol table


fseek(sym, 0, SEEK_SET);
while (fscanf(sym, "%s\t%s\n", value, symbol) == 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;
}
}
}

fprintf(out, "%s\t%s\t%s\t%s\n", label, opcode, opr1, opr2);


fscanf(input, "%s\t%s\t%s\t%s", label, opcode, opr1, opr2);

}
}

int isNumber(const char *str) {

if (str == NULL || *str == '\0') {


return 0;
}

for (int i = 0; str[i] != '\0'; i++) {

if (!isdigit(str[i])) {
return 0;
}
}

return 1;
}
Output:

Input Files:
File generated after Pass One of Two Pass Assembler:

Machine Code Generated after Pass Two of Two Pass Assembler:

Conclusion: Hence, we have successfully implemented Two-Pass Assembler.

You might also like