In Pass 1 of the SIC/XE assembler, the primary task is to scan the assembly source code to create a symbol table that maps labels to memory addresses. It also generates an intermediate code with placeholders for addresses and detects syntax errors. Pass 1 does not produce the final machine code but prepares the necessary information for Pass 2, where the actual machine code is generated and addresses are resolved.
The objective of Assembler Pass1:
Read the source code line by line.
Identify and process any assembler directives, such as the START directive, which specifies the starting address of the program.
Identify and process any labels used in the source code. Labels are typically followed by a colon and are used to mark specific locations in the program.
Generate the symbol table by storing the labels and their corresponding addresses or values.
Identify and process any variables or constants used in the source code. Variables are typically allocated memory space, while constants are assigned specific values.
Generate the intermediate code, which is a simplified representation of the source code that can be easily processed by the assembler in subsequent passes.
The first pass of an assembler converts assembly language to machine language. The second pass of an assembler reads the intermediate file, generates object code, and writes the final object program.
The data structure used in Assembler Pass1:
In terms of data structures, Pass 1 of an assembler typically uses the following:
Symbol Table: This data structure is used to store the labels and their corresponding addresses or values. It can be implemented as a hash table, where the labels are the keys and the addresses or values are the associated values.
Intermediate Code: This data structure is used to store the simplified representation of the source code. It can be implemented as a list or an array of data structures, where each data structure represents a line of code and contains information 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;
}
Pass 1 Output