0% found this document useful (0 votes)
3 views

Pass 2 Explanation

This document provides a detailed step-by-step explanation of Pass 2 of a Two Pass Assembler, including code structure, functions for reading symbol and operation tables, and processing directives such as BYTE, WORD, RESB, and RESW. It outlines how to handle the intermediate file, generate object code, and manage text records while ensuring proper formatting for output files. The document concludes with final steps for writing remaining records and closing files.

Uploaded by

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

Pass 2 Explanation

This document provides a detailed step-by-step explanation of Pass 2 of a Two Pass Assembler, including code structure, functions for reading symbol and operation tables, and processing directives such as BYTE, WORD, RESB, and RESW. It outlines how to handle the intermediate file, generate object code, and manage text records while ensuring proper formatting for output files. The document concludes with final steps for writing remaining records and closing files.

Uploaded by

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

Step-by-Step Explanation of Pass 2 of Two Pass Assembler

Code Explanation
Header Files and Global Variables
# include < stdio .h >
# include < stdlib .h >
# include < string .h >

FILE * f1 , * f2 , * f3 , * f4 , * f5 , * f6 ;
int s = -1 , o = -1 , i , j ;

• We include standard input-output, standard library, and string handling header files.
• We declare file pointers for handling multiple files.
• We declare global variables for iterating through symbol and operation tables.

Structure Definitions
struct symt {
char label [30] , addr [30];
} st [30];

struct optt {
char code [30] , mine [30];
} ot [30];

• We define two structures, symt for the symbol table and optt for the operation table.
• Each structure has two fields: label and addr for the symbol table, and code and mine for the
operation table.

Functions to Read Tables


void sym () {
while (1) {
s ++;
fscanf ( f3 , " % s % s " , st [ s ]. label , st [ s ]. addr );
if ( fgetc ( f3 ) == EOF ) break ;
}
}

void opt () {
while (1) {
o ++;
fscanf ( f2 , " % s % s " , ot [ o ]. code , ot [ o ]. mine );
if ( fgetc ( f2 ) == EOF ) break ;
}
}

• The sym() function reads the symbol table from a file and stores it in the st array.
• The opt() function reads the operation table from a file and stores it in the ot array.
Main Function
void main () {
char label [20] , opcode [20] , operand [30] , a [20] , ad [30];
int address , length , start ;
f1 = fopen ( " intermediate . txt " , " r " );
f2 = fopen ( " optab . txt " , " r " );
f3 = fopen ( " symtab . txt " , " r " );
f4 = fopen ( " len . txt " , " r " );
f5 = fopen ( " output . txt " , " w " );
f6 = fopen ( " objcode . txt " , " w " );

opt ();
sym ();

• We declare local variables for labels, opcodes, operands, addresses, and lengths.

• We open the necessary files for reading and writing.

• We call the opt() and sym() functions to read the operation and symbol tables.

Reading Length and Initial Processing


fscanf ( f4 , " % x " , & length );
fscanf ( f1 , " % s % s % s " , label , opcode , operand );
if ( strcmp ( opcode , " START " ) == 0) {
fprintf ( f5 , " % s \ t % s \ t % s \ n " , label , opcode , operand );
fprintf ( f6 , " H ^% s ^00% s ^%06 X \ n " , label , operand , length );
fscanf ( f1 , " % x % s % s % s " , & address , label , opcode , operand );
start = address ;
}

• We read the length of the program from the len.txt file.

• We read the first line from the intermediate file.

• If the opcode is START, we write the header record to the object code file and store the starting
address.

Processing the Intermediate File - Initialization


char text_record [70] = " " ;
int text_start = start ;
int text_length = 0;

• We initialize the text record, text start address, and text length.

Processing the Intermediate File - Loop Start


while ( strcmp ( opcode , " END " ) != 0) {
char obj_code [10] = " " ;
int obj_code_length = 0;

• We start a loop to process each line of the intermediate file until the END opcode is encountered.

• We initialize the object code and its length.


Processing the Intermediate File - BYTE Directive
if ( strcmp ( opcode , " BYTE " ) == 0) {
fprintf ( f5 , " % x \ t % s \ t % s \ t % s \ t " , address , label , opcode , operand );
if ( operand [0] == ’C ’ && operand [1] == ’\ ’ ’) {
for ( i = 2; operand [ i ] != ’\ ’ ’; i ++) {
sprintf ( ad , " %02 X " , operand [ i ]);
strcat ( obj_code , ad );
}
obj_code_length = ( i - 2) * 2;
} else if ( operand [0] == ’X ’ && operand [1] == ’\ ’ ’) {
for ( i = 2; operand [ i ] != ’\ ’ ’; i ++) {
sprintf ( ad , " % c " , operand [ i ]);
strcat ( obj_code , ad );
}
obj_code_length = ( i - 2);
}
fprintf ( f5 , " % s \ n " , obj_code );

• For the BYTE directive, we handle both character and hexadecimal representations.

• We convert the operand to its respective object code.

• We write the line to the output file.

Processing the Intermediate File - WORD Directive


} else if ( strcmp ( opcode , " WORD " ) == 0) {
sprintf ( obj_code , " %06 X " , ( int ) strtol ( operand , NULL , 10));
obj_code_length = 6;
fprintf ( f5 , " % x \ t % s \ t % s \ t % s \ t % s \ n " , address , label , opcode , operand , obj_code );

• For the WORD directive, we convert the operand to an integer using strtol.

• We write the line to the output file.

Processing the Intermediate File - RESB and RESW Directives


} else if ( strcmp ( opcode , " RESB " ) == 0 || strcmp ( opcode , " RESW " ) == 0) {
fprintf ( f5 , " % x \ t % s \ t % s \ t % s \ n " , address , label , opcode , operand );
if ( strlen ( text_record ) > 0) {
fprintf ( f6 , " T ^%06 X ^%02 X % s \ n " , text_start , text_length , text_record );
text_record [0] = ’ \0 ’;
text_length = 0;
}
fscanf ( f1 , " % x % s % s % s " , & address , label , opcode , operand );
continue ;

• For RESB and RESW directives, we handle reserved space and write out any pending text records.

• We write the line to the output file.

• We clear the text record and reset the text length.


Processing the Intermediate File - Other Opcodes
} else {
i = 0;
while ( strcmp ( opcode , ot [ i ]. code ) != 0) i ++;
j = 0;
while ( strcmp ( operand , st [ j ]. label ) != 0) j ++;
sprintf ( obj_code , " % s % s " , ot [ i ]. mine , st [ j ]. addr );
obj_code_length = 6;
fprintf ( f5 , " % x \ t % s \ t % s \ t % s \ t % s \ n " , address , label , opcode , operand , obj_code );
}

if ( text_length + obj_code_length > 60) {


fprintf ( f6 , " T ^%06 X ^%02 X % s \ n " , text_start , text_length , text_record );
text_start = address ;
text_length = 0;
text_record [0] = ’ \0 ’;
}
strcat ( text_record , " ^ " );
strcat ( text_record , obj_code );
text_length += obj_code_length ;

fscanf ( f1 , " % x % s % s % s " , & address , label , opcode , operand );


}

• For other opcodes, we find the corresponding object code and address from the operation and symbol
tables.

• We write the line to the output file.

• We handle text record length to ensure it does not exceed 60 characters.

• We concatenate the object code to the text record.

• We read the next line from the intermediate file.

Final Steps
if ( text_length > 0) {
fprintf ( f6 , " T ^%06 X ^%02 X % s \ n " , text_start , text_length , text_record );
}
fprintf ( f5 , " % x \ t % s \ t % s \ t % s \ n " , address , label , opcode , operand );
fprintf ( f6 , " \ nE ^%06 X \ n " , start );

fclose ( f1 ); fclose ( f2 ); fclose ( f3 );


fclose ( f4 ); fclose ( f5 ); fclose ( f6 );
}

• We write the final text record if any object code remains.

• We write the last line to the output file.

• We write the end record to the object code file with the starting address.

• We close all opened files.

You might also like