Pass 1 is the initial phase where the assembler reads the entire source code (assembly program) and performs the following key tasks:
Symbol Table Creation: During Pass 1, the assembler identifies all labels (symbols) used in the program, such as variables, function names, and other identifiers. These symbols represent memory locations or addresses in the program. The assembler adds these symbols to a symbol table, which is essentially a mapping of symbolic names to their corresponding memory addresses or locations.
Determine Instruction and Data Locations: The assembler assigns addresses to instructions and data items in memory. This step involves keeping track of where the instructions and data will reside in memory after the program is assembled. The location counter (LC) is used to keep track of the current address of the instruction or data being processed.
Handling of Directives: The assembler also processes directives (like .data, .text, etc.), which provide instructions to the assembler itself about how to organize the program's data and code.
Machine Code Skeleton: While Pass 1 doesn't generate the complete machine code, it does generate a "skeleton" that will be used in the second pass to fill in the final machine code. This skeleton typically consists of the instructions with placeholders where the actual addresses or values will be filled in during Pass 2.
Resolve Forward References: A forward reference occurs when a label is used before it is defined. In Pass 1, these references are recorded, and their actual memory addresses will be resolved in Pass 2 when the full program structure is available.
Algorithm
Pass 1
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 OPCODE ≠ ‘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}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void passOne() {
char label[10], opcode[10], operand[10], mnemonic[10];
int start, locctr;
char line[100];
FILE *input, *optab, *symtab, *intermediate;
input = fopen("pass1_input_code.txt", "r");
optab = fopen("pass1_optab.txt", "r");
symtab = fopen("pass1_symtab.txt", "w");
intermediate = fopen("pass1_intermediate_code.txt", "w");
if (!input || !optab || !symtab || !intermediate) {
printf("Error: Could not open one or more files.\n");
exit(1);
}
fgets(line, sizeof(line), input);
sscanf(line, "%s %s %s", label, opcode, operand);
if (strcmp(opcode, "START") == 0) {
start = (int)strtol(operand, NULL, 16);
locctr = start;
fprintf(intermediate, "%04X\t%s\t%s\t%s\n", locctr, label, opcode, operand);
printf("%04X\t%s\t%s\t%s\n", locctr, label, opcode, operand); // Display on terminal
} else {
locctr = 0;
}
while (fgets(line, sizeof(line), input) != NULL) {
sscanf(line, "%s %s %s", label, opcode, operand);
// Write to symtab only if there's a real label (not empty or "-")
if (label[0] != '\0' && strcmp(label, "-") != 0) {
fprintf(symtab, "%s\t%04X\n", label, locctr);
}
fprintf(intermediate, "%04X\t%s\t%s\t%s\n", locctr, label, opcode, operand);
printf("%04X\t%s\t%s\t%s\n", locctr, label, opcode, operand); // Display on terminal
// Check if opcode is format 4 (starts with '+')
int format = 3; // Default to format 3
if (opcode[0] == '+') {
format = 4; // Set format to 4 if opcode starts with '+'
memmove(opcode, opcode + 1, strlen(opcode)); // Remove the '+' for lookup in OPTAB
}
// Search in OPTAB to check if the opcode exists
rewind(optab);
int found = 0;
while (fgets(line, sizeof(line), optab) != NULL) {
sscanf(line, "%s", mnemonic);
if (strcmp(opcode, mnemonic) == 0) {
found = 1;
break;
}
}
if (found) {
// Check for format 2 opcodes
if (strcmp(opcode, "CLEAR") == 0 || strcmp(opcode, "TIXR") == 0 || strcmp(opcode, "ADDR") == 0 ||
strcmp(opcode, "SUBR") == 0 || strcmp(opcode, "MULR") == 0 || strcmp(opcode, "DIVR") == 0 ||
strcmp(opcode, "COMPR") == 0 || strcmp(opcode, "SHIFTL") == 0 || strcmp(opcode, "SHIFTR") == 0 ||
strcmp(opcode, "SVC") == 0 || (opcode[strlen(opcode) - 1] == 'R' && strlen(opcode) <= 5)) {
format = 2;
} else if (strcmp(operand, "-") == 0) {
format = 1;
}
// Adjust locctr based on instruction format
if (format == 1) {
locctr += 1;
} else if (format == 2) {
locctr += 2;
} else if (format == 4) {
locctr += 4;
} else {
locctr += 3;
}
} else if (strcmp(opcode, "WORD") == 0) {
locctr += 3;
} else if (strcmp(opcode, "RESW") == 0) {
locctr += 3 * atoi(operand);
} else if (strcmp(opcode, "RESB") == 0) {
locctr += atoi(operand);
} else if (strcmp(opcode, "BYTE") == 0) {
if (operand[0] == 'C') {
locctr += strlen(operand) - 3;
} else if (operand[0] == 'X') {
locctr += (strlen(operand) - 3) / 2;
}
}
if (strcmp(opcode, "END") == 0) {
break;
}
}
fclose(input);
fclose(optab);
fclose(symtab);
fclose(intermediate);
int length = locctr - start;
printf("\nLength of the program is %04X\n", length);
printf("Pass 1 completed successfully for SIC-XE.\n");
}
int main() {
passOne();
return 0;
}
COMPUTE START 2000
SETUP LDX #3
- LDA #2
PROCESS MUL DELTA,X
- TIX INDEX
- JLT PROCESS
- +STA #FINAL
INDEX RESW 1
FINAL RESW 1
DELTA RESB 60
- END SETUP
2000 COMPUTE START 2000
2000 SETUP LDX #3
2003 - LDA #2
2006 PROCESS MUL DELTA,X
2009 - TIX INDEX
200A - JLT PROCESS
200D - +STA #FINAL
2011 INDEX RESW 1
2014 FINAL RESW 1
2017 DELTA RESB 60
2053 - END SETUP
COMPUTE 2000
SETUP 2000
PROCESS 2006
INDEX 2011
FINAL 2014
DELTA 2017
The length is calculated as: 2053 (Final LOCCTR) - 2000 (Start address) = 0053
Program Length: 53 (Hexadecimal)
2000 COMPUTE START 2000
2000 SETUP LDX #3
2003 - LDA #2
2006 PROCESS MUL DELTA,X
2009 - TIX INDEX
200A - JLT PROCESS
200D - +STA #FINAL
2011 INDEX RESW 1
2014 FINAL RESW 1
2017 DELTA RESB 60
2053 - END SETUP
Length of the program is 0053
Pass 1 completed successfully for SIC-XE.