Objective of Assembler Pass 1: -
Read the source code line by line.
Process assembler directives: Handle directives like the START directive, which defines the program's starting address.
Handle labels: Identify labels in the code (typically followed by a colon) that mark specific locations within the program.
Generate the symbol table: Store labels along with their corresponding addresses or values.
Process variables and constants: Allocate memory for variables and assign specific values to constants.
Generate intermediate code: Create a simplified version of the source code that the assembler can process in subsequent passes.
The first pass of an assembler converts assembly language to an intermediate form, while the second pass generates the object code by reading the intermediate file and producing the final object program.
Symbol Table: Stores labels and their associated addresses or values. This can be implemented using a hash table, with labels as keys and their corresponding addresses or values as values.
Intermediate Code: Stores a simplified version of the source code for later processing. It can be implemented as a list or an array, where each element contains information about a line of code, such as the opcode and operands.
begin
read first input line
if OPCODE ='START' then
begin
save #[OPERAND] as starting address
initialize LOCCTR to starting address
write line to intermediate file
read next input line
end {if START}
else
initialize LOCCTR to 0
while OCODE != 'END' do
begin
if this is not a comment line then
begin
if there is a symbol in the LABEL field then
begin
search SYMTAB for LABEL
if found then
set error flag (duplicate symbol)
else
insert (LABEL,LOCCTR) into SYMTAB
end {if symbol}
search OPTAB for OPCODE
if found then
add 3 {instruction length} to LOCCTR
else if OPCODE='WORD' then
add 3 to LOCCTR
else if OPCODE = 'RESW' then
add 3 * #[OPERAND] to LOCCTR
else if OPCODE = 'RESB' then
add #[OPERAND] to LOCCTR
else if OPCODE = 'BYTE' then
begin
find length of constant in bytes
add length to LOCCTR
end {if BYTE}
else
set error flag (invalid operation code)
end {if not a comment}
write line to intermediate file
read next input line
end {while not END}
write last line to intermediate file
save (LOCCTR – starting address) as program length
end {Pass 1}
input.txt :-
COPY START 1000
- +LDA ALPHA
- ADD #1
- DIV #2
- STA BETA
- SUB #4
- STA GAMMA
- +LDA GAMMA
- ADD #2
- +LDA BETA
ALPHA BYTE C'COF'
BETA RESW 2
GAMMA RESW 2
- END 1000
optab.txt :-
DIV 06
SUB 05
CMP 03
LDA 00
STA 23
ADD 01
JNC 08
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
char *decimalToHex(int decimal) {
static char hex_string[10];
sprintf(hex_string, "%X", decimal);
return hex_string;
}
int main() {
printf("PASS 1\n");
char str;
char saved_labels[20][20];
int saved_labels_index = 0;
char label[20], opcode[20], operand[20];
char optab_opcode[10], machine_code[10];
int starting_address, location_counter;
bool opcode_found = false;
FILE *input_file, *optab_file, *symtab_file, *output_file;
input_file = fopen("input.txt", "r");
optab_file = fopen("optab.txt", "r");
symtab_file = fopen("symtab.txt", "w+");
output_file = fopen("intermediate.txt", "w");
if (input_file == NULL || optab_file == NULL || symtab_file == NULL || output_file == NULL) {
printf("Error! opening file");
exit(1);
} else {
printf("All file opened successfully\n");
}
fscanf(input_file, "%s %s %s", label, opcode, operand);
if (strcmp(opcode, "START") == 0) {
starting_address = strtol(operand, NULL, 16);
location_counter = starting_address;
} else {
location_counter = 0;
starting_address = 0;
}
printf("\nIntermidia File:\n\n");
fprintf(output_file, "%s\t%s\t%s\t%s\n", "-", label, opcode, operand);
printf("%s\t%s\t%s\t%s\n", "-", label, opcode, operand);
fscanf(input_file, "%s %s %s", label, opcode, operand);
while (strcmp(opcode, "END") != 0) {
if (strcmp(label, "-") != 0) {
for (int i = 0; i < 10; i++) {
if (strcmp(saved_labels[i], label) == 0) {
printf("Error! Duplicate label: %s found at line %d\n", label, i + 1);
exit(1);
}
}
strcpy(saved_labels[saved_labels_index], label);
saved_labels_index++;
fprintf(symtab_file, "%s\t%s\n", label, decimalToHex(location_counter));
}
rewind(optab_file);
opcode_found = false;
fscanf(optab_file, "%s %s", optab_opcode, machine_code);
while (!feof(optab_file)) {
if (strcmp(optab_opcode, opcode) == 0) {
opcode_found = true;
break;
}
fscanf(optab_file, "%s %s", optab_opcode, machine_code);
}
fprintf(output_file, "%s\t%s\t%s\t%s\n", decimalToHex(location_counter), label, opcode, operand);
printf("%s\t%s\t%s\t%s\n", decimalToHex(location_counter), label, opcode, operand);
if (opcode_found) {
location_counter += 3;
} else if (strcmp(opcode, "BYTE") == 0) {
location_counter += strlen(operand) - 3;
} else if (strcmp(opcode, "RESB") == 0) {
location_counter += atoi(operand);
} else if (strcmp(opcode, "WORD") == 0) {
location_counter += 3;
} else if (strcmp(opcode, "RESW") == 0) {
location_counter += 3 * atoi(operand);
} else {
printf("Error! Invalid opcode\n");
printf("opcode: %s\n", opcode);
exit(1);
}
fscanf(input_file, "%s %s %s", label, opcode, operand);
}
fprintf(output_file, "%s\t%s\t%s\t%s\n", decimalToHex(location_counter), label, opcode, operand);
printf("%s\t%s\t%s\t%s\n", decimalToHex(location_counter), label, opcode, operand);
printf("\nSize of the program: %s\n", decimalToHex(location_counter - starting_address));
printf("\n\nThe contents of Symbol Table :\n\n");
fclose(input_file);
fclose(optab_file);
fclose(symtab_file);
fclose(output_file);
symtab_file = fopen("symtab.txt", "r");
str = fgetc(symtab_file);
while (str != EOF) {
printf("%c", str);
str = fgetc(symtab_file);
}
fclose(symtab_file);
return 0;
}