Introduction and Problem Description:
A. Introduction:
Purpose of Pass 2: Converts the intermediate file, symbol table, and opcode table from Pass 1 into the final object code.
Primary Goal: Resolves address references, translates assembly instructions into machine code, and formats output as a structured object program.
Processing:
Converts mnemonics to opcodes using the opcode table.
Replaces symbolic references with memory addresses using the symbol table.
Adheres to specific object program formats (header, text, and end records).
Outcome: Produces a fully translated object program ready for execution or linking with other modules.
a) Instruction Translation:
Maps mnemonics to corresponding opcodes.
Resolves symbolic references to actual addresses.
Handles various addressing modes (immediate, direct, indexed).
b) Object Program Formatting:
Generates header records with metadata (program name, starting address, program length).
Creates text records for machine instructions and data.
Produces end records to specify the execution start address.
Optimizes text record organization to reduce memory fragmentation.
c) Error Handling:
Detects undefined symbols, invalid instructions, or mismatched addressing modes.
Ensures operational correctness of the program.
Pass 2 of two pass assembler algorithm:
Codes :
Code for SIC Pass 2 of two pass assembler:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct pass2
{
char locctr[10], label[20], opcode[20], operand[20];
} p2;
typedef struct optab
{
char opCode[10], value[3];
} tab;
typedef struct symtab
{
char Symbol[10], address[6];
} sym;
int main()
{
p2 b[100];
tab a[50];
sym c[50];
char sm[100], opTab[100], sd[100];
FILE *ip = fopen("SICINT.txt", "r");
FILE *kp = fopen("SICSymTab.txt", "r");
FILE *op = fopen("SICoutput.txt", "w");
FILE *ot = fopen("OpTab.txt", "r");
if (ip == NULL || kp == NULL || ot == NULL)
{
printf("Unable to open one or more files\n");
return 1;
}
int i = 0, k = 0;
int startValue = 0, endValue = 0;
int textRecordLength = 0;
char textRecord[1000] = "";
// Reading details from Intermediate file
while (fgets(sd, sizeof(sd), ip) && i < 100)
{
char loc[20] = "", lab[20] = "", oper[20] = "", open[20] = "";
int tokens = sscanf(sd, "%s %s %s %s", loc, lab, oper, open);
strcpy(b[i].locctr, loc);
if (tokens == 2)
{
strcpy(b[i].opcode, lab);
strcpy(b[i].operand, "");
}
else if (tokens == 3)
{
strcpy(b[i].opcode, lab);
strcpy(b[i].operand, oper);
}
else if (tokens == 4)
{
strcpy(b[i].label, lab);
strcpy(b[i].opcode, oper);
strcpy(b[i].operand, open);
}
i++;
}
// Reading opcodes from OpTab
while (fgets(opTab, sizeof(opTab), ot) && k < 50)
{
char opc[10] = "", val[3] = "";
sscanf(opTab, "%s %s", opc, val);
strcpy(a[k].opCode, opc);
strcpy(a[k].value, val);
k++;
}
// Reading details from SymTab
int r = 0;
while (fgets(sm, sizeof(sm), kp) && r < 50)
{
char symb[10] = "", add[6] = "";
sscanf(sm, "%s %s", symb, add);
strcpy(c[r].Symbol, symb);
strcpy(c[r].address, add);
r++;
}
char prname[7] = "______";
if (strcmp(b[0].opcode, "START") == 0)
{
startValue = strtoul(b[0].locctr, NULL, 16);
strncpy(prname, b[0].label, 6);
}
endValue = strtoul(b[i - 1].locctr, NULL, 16);
int prlength = endValue - startValue;
fprintf(op, "H%06s%06X%06X\n", prname, startValue, prlength);
int j = 0;
int currentTextAddress = startValue;
char text[100] = "";
int textlen = 0;
while (strcmp(b[j].opcode, "END") != 0)
{
char combine[10] = "", code[3] = "", val1[6] = "";
int foundOpcode = 0;
for (int p = 0; p < k; p++)
{
if (strcmp(a[p].opCode, b[j].opcode) == 0)
{
strcpy(code, a[p].value);
foundOpcode = 1;
break;
}
}
if (foundOpcode == 1)
{
int foundSymbol = 0;
int isIndexed = 0;
char operand[20] = "";
strcpy(operand, b[j].operand);
// printf("%s\n",b[j].opcode);
char *comma = strchr(operand, ',');
if (comma && strcmp(comma + 1, "X") == 0)
{
*comma = '\0';
isIndexed = 1;
}
for (int q = 0; q < r; q++)
{
if (strcmp(c[q].Symbol, operand) == 0)
{
strcpy(val1, c[q].address);
foundSymbol = 1;
break;
}
}
if (foundSymbol == 0 && strlen(b[j].operand) > 0)
{
printf("Undefined Symbol: %s\n", operand);
strcpy(val1, "0000");
printf("%s\n", b[j].operand);
}
else if (isIndexed == 1)
{
int address = (int)strtol(val1, NULL, 16);
address += 0x8000;
sprintf(val1, "%04X", address);
}
sprintf(combine, "%s%04s", code, val1);
// printf("%s\n",combine);
// Add the generated object code to the text record
strcat(text, combine);
textlen += strlen(combine) / 2;
if (textlen > 30)
{
fprintf(op, "T%06X%02X%s\n", currentTextAddress, textRecordLength, textRecord);
textRecordLength = 0;
strcpy(textRecord, "");
textlen = 0;
j--;
strcpy(text, "");
currentTextAddress = strtoul(b[(j + 1)].locctr, NULL, 16);
}
else if (textlen == 30)
{
strcat(textRecord, combine);
textRecordLength += strlen(combine) / 2;
fprintf(op, "T%06X%02X%s\n", currentTextAddress, textRecordLength, textRecord);
textRecordLength = 0;
strcpy(textRecord, "");
textlen = 0;
strcpy(text, "");
currentTextAddress = strtoul(b[(j + 1)].locctr, NULL, 16);
}
else
{
strcat(textRecord, combine);
textRecordLength += strlen(combine) / 2;
}
}
else if (strcmp(b[j].opcode, "WORD") == 0)
{
sprintf(combine, "%06X", atoi(b[j].operand));
strcat(text, combine);
textlen += 3;
if (textlen > 30)
{
fprintf(op, "T%06X%02X%s\n", currentTextAddress, textRecordLength, textRecord);
textRecordLength = 0;
strcpy(textRecord, "");
textlen = 0;
strcpy(text, "");
currentTextAddress = strtoul(b[j].locctr, NULL, 16);
}
else if (textlen == 30)
{
strcat(textRecord, combine);
textRecordLength += 3;
fprintf(op, "T%06X%02X%s\n", currentTextAddress, textRecordLength, textRecord);
textRecordLength = 0;
strcpy(textRecord, "");
textlen = 0;
j--;
strcpy(text, "");
currentTextAddress = strtoul(b[j].locctr, NULL, 16);
}
else
{
strcat(textRecord, combine);
textRecordLength += 3;
}
}
else if (strcmp(b[j].opcode, "BYTE") == 0)
{
char hex_result[100] = "";
if (b[j].operand[0] == 'C')
{
for (int m = 2; m < (strlen(b[j].operand) - 1); m++)
{
char buffer[3] = "";
sprintf(buffer, "%02X", (int)b[j].operand[m]);
strcat(hex_result, buffer);
}
}
else if (b[j].operand[0] == 'X')
{
strncpy(hex_result, (b[j].operand + 2), (strlen(b[j].operand) - 3));
hex_result[(strlen(b[j].operand) - 3)] = '\0';
}
strcat(text, hex_result);
textlen += strlen(hex_result) / 2;
if (textlen > 30)
{
fprintf(op, "T%06X%02X%s\n", currentTextAddress, textRecordLength, textRecord);
textRecordLength = 0;
strcpy(textRecord, "");
textlen = 0;
j--;
strcpy(text, "");
currentTextAddress = strtoul(b[j].locctr, NULL, 16);
}
else if (textlen == 30)
{
strcat(textRecord, hex_result);
textRecordLength += strlen(hex_result) / 2;
fprintf(op, "T%06X%02X%s\n", currentTextAddress, textRecordLength, textRecord);
textRecordLength = 0;
strcpy(textRecord, "");
textlen = 0;
strcpy(text, "");
currentTextAddress = strtoul(b[j].locctr, NULL, 16);
}
else
{
strcat(textRecord, hex_result);
textRecordLength += strlen(hex_result) / 2;
}
}
else if (strcmp(b[j].opcode, "RESW") == 0 || strcmp(b[j].opcode, "RESB") == 0 || strcmp(b[j].opcode, "EQU") == 0)
{
if (textRecordLength > 0)
{
fprintf(op, "T%06X%02X%s\n", currentTextAddress, textRecordLength, textRecord);
textRecordLength = 0;
strcpy(textRecord, "");
textlen = 0;
strcpy(text, "");
}
currentTextAddress = strtoul(b[(j + 1)].locctr, NULL, 16);
}
else
{
if (j != 0)
{
printf("Invalid Instruction\n");
printf("%d\n", j);
exit(0);
}
}
j++;
}
if (textRecordLength > 0)
{
fprintf(op, "T%06X%02X%s\n", currentTextAddress, textRecordLength, textRecord);
}
fprintf(op, "E%06X\n", startValue);
fclose(op);
fclose(ip);
fclose(kp);
fclose(ot);
FILE *output = fopen("SICoutput.txt", "r");
if (output == NULL)
{
printf("Unable to open output.txt\n");
return 1;
}
char line[256];
printf("\n--- The Object program ---\n");
while (fgets(line, sizeof(line), output))
{
printf("%s", line);
}
fclose(output);
return 0;
}
Code for SIC/XE Pass 2 of two pass assembler:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
char base[6] = "", Base[6] = "";
typedef struct
{
char locctr[10], label[20], opcode[20], operand[20];
} p2;
typedef struct
{
char opCode[10], value[3], format[2];
} tab;
typedef struct
{
char Symbol[10], address[6];
} sym;
int getRegisterNumber(char reg)
{
switch (reg)
{
case 'A':
return 0;
case 'X':
return 1;
case 'L':
return 2;
case 'B':
return 3;
case 'S':
return 4;
case 'T':
return 5;
case 'F':
return 6;
case 'P':
return 8;
case 'W':
return 9;
default:
return 0;
}
}
int main()
{
p2 b[100];
tab a[102];
sym c[100];
char sm[100], opTab[100], sd[100];
FILE *ip = fopen("SICXEINT.txt", "r");
FILE *kp = fopen("SICXESymTab.txt", "r");
FILE *op = fopen("SICXEoutput.txt", "w");
FILE *ot = fopen("OpTab.txt", "r");
if (ip == NULL || kp == NULL || ot == NULL)
{
printf("Unable to open one or more files\n");
return 1;
}
int i = 0, k = 0;
int startValue = 0, endValue = 0;
int textRecordLength = 0;
char textRecord[1000] = "";
// Reading details from Intermediate file
while (fgets(sd, sizeof(sd), ip) && i < 100)
{
char loc[20] = "", lab[20] = "", oper[20] = "", open[20] = "";
int tokens = sscanf(sd, "%s %s %s %s", loc, lab, oper, open);
if (strcmp(loc, "BASE") == 0)
{
strcpy(base, lab);
continue;
}
strcpy(b[i].locctr, loc);
if (tokens == 2)
{
strcpy(b[i].opcode, lab);
strcpy(b[i].operand, "");
}
else if (tokens == 3)
{
strcpy(b[i].opcode, lab);
strcpy(b[i].operand, oper);
}
else if (tokens == 4)
{
strcpy(b[i].label, lab);
strcpy(b[i].opcode, oper);
strcpy(b[i].operand, open);
}
i++;
}
// Reading opcodes from OpTab
while (fgets(opTab, sizeof(opTab), ot) && k < 102)
{
char opc[10] = "", val[3] = "", fmt[2] = "";
sscanf(opTab, "%s %s %s", opc, val, fmt);
strcpy(a[k].opCode, opc);
strcpy(a[k].value, val);
strcpy(a[k].format, fmt);
k++;
}
// Reading details from SymTab
int r = 0;
while (fgets(sm, sizeof(sm), kp) && r < 100)
{
char symb[10] = "", add[6] = "";
sscanf(sm, "%s %s", symb, add);
if (strcmp(base, symb) == 0)
{
strcpy(Base, add);
}
strcpy(c[r].Symbol, symb);
strcpy(c[r].address, add);
r++;
}
char prname[7] = "______";
if (strcmp(b[0].opcode, "START") == 0)
{
startValue = strtoul(b[0].locctr, NULL, 16);
strncpy(prname, b[0].label, 6);
}
endValue = strtoul(b[i - 1].locctr, NULL, 16);
int prlength = endValue - startValue;
fprintf(op, "H%06s%06X%06X\n", prname, startValue, prlength);
int j = 0;
int currentTextAddress = startValue;
char text[100] = "";
int textlen = 0;
while (strcmp(b[j].opcode, "END") != 0)
{
char combine[10] = "", code[3] = "", val1[6] = "", form[2];
int foundOpcode = 0;
for (int p = 0; p < k; p++)
{
if (strcmp(a[p].opCode, b[j].opcode) == 0)
{
strcpy(code, a[p].value);
strcpy(form, a[p].format);
foundOpcode = 1;
break;
}
}
if (foundOpcode == 1)
{
int foundSymbol = 0;
int isIndexed = 0;
char operand[20] = "";
strcpy(operand, b[j].operand);
int n = 1, i = 1, x = 0, bFlag = 0, p = 0, e = 0;
if (strcmp(form, "2") == 0)
{
char reg1 = '0', reg2 = '0';
if (strlen(b[j].operand) > 0)
{
if (strchr(b[j].operand, ','))
{
sscanf(b[j].operand, "%c,%c", ®1, ®2);
}
else
{
reg1 = b[j].operand[0];
}
reg1 = getRegisterNumber(reg1);
reg2 = getRegisterNumber(reg2);
sprintf(combine, "%s%X%X", code, reg1, reg2);
}
}
else if ((strcmp(form, "3") == 0) || (strcmp(form, "4") == 0))
{
char *comma = strchr(operand, ',');
if (comma && strcmp(comma + 1, "X") == 0)
{
*comma = '\0';
isIndexed = 1;
x = 1;
}
if (operand[0] == '#')
{
i = 1;
n = 0;
strcpy(operand, operand + 1);
}
else if (operand[0] == '@')
{
n = 1;
i = 0;
strcpy(operand, operand + 1);
}
for (int q = 0; q < r; q++)
{
if (strcmp(c[q].Symbol, operand) == 0)
{
strcpy(val1, c[q].address);
foundSymbol = 1;
break;
}
}
if (strcmp(form, "4") == 0)
{
e = 1;
}
if (foundSymbol)
{
int pcValue = strtoul(b[(j + 1)].locctr, NULL, 16);
int symAddr = strtoul(val1, NULL, 16);
int displacement = 0;
if (strcmp(form, "3") == 0)
{
displacement = symAddr - pcValue;
if (displacement >= -0x800 && displacement <= 0x7FF)
{
p = 1;
}
else
{
bFlag = 1;
pcValue = strtoul(Base, NULL, 16);
displacement = symAddr - pcValue;
}
}
if (e)
{
sprintf(val1, "%05X", symAddr);
}
else
{
sprintf(val1, "%03X", displacement & 0xFFF);
}
}
else if (strlen(b[j].operand) > 0)
{
if (i == 1 && isdigit(operand[0]))
{
if (strcmp(form, "3") == 0)
sprintf(val1, "%03X", strtoul(operand, NULL, 16)); // Immediate value
else
sprintf(val1, "%05X", atoi(operand)); // Immediate value
}
else
{
printf("Undefined Symbol: %s\n", operand);
strcpy(val1, "0000");
}
}
int niBits = (n << 1) | i;
int xbpeBits = (x << 3) | (bFlag << 2) | (p << 1) | e;
if (e)
{
sprintf(combine, "%02X%1X%05s", strtol(code, NULL, 16) + niBits, xbpeBits, val1);
}
else
{
sprintf(combine, "%02X%1X%03s", strtol(code, NULL, 16) + niBits, xbpeBits, val1);
}
}
strcat(text, combine);
textlen += strlen(combine) / 2;
if (textlen > 30)
{
fprintf(op, "T%06X%02X%s\n", currentTextAddress, textRecordLength, textRecord);
textRecordLength = 0;
strcpy(textRecord, "");
textlen = 0;
j--;
strcpy(text, "");
currentTextAddress = strtoul(b[(j + 1)].locctr, NULL, 16);
}
else if (textlen == 30)
{
strcat(textRecord, combine);
textRecordLength += strlen(combine) / 2;
fprintf(op, "T%06X%02X%s\n", currentTextAddress, textRecordLength, textRecord);
textRecordLength = 0;
strcpy(textRecord, "");
textlen = 0;
strcpy(text, "");
currentTextAddress = strtoul(b[(j + 1)].locctr, NULL, 16);
}
else
{
strcat(textRecord, combine);
textRecordLength += strlen(combine) / 2;
}
}
else if (strcmp(b[j].opcode, "WORD") == 0)
{
sprintf(combine, "%06X", atoi(b[j].operand));
strcat(text, combine);
textlen += 3;
if (textlen > 30)
{
fprintf(op, "T%06X%02X%s\n", currentTextAddress, textRecordLength, textRecord);
textRecordLength = 0;
strcpy(textRecord, "");
textlen = 0;
strcpy(text, "");
j--;
currentTextAddress = strtoul(b[(j + 1)].locctr, NULL, 16);
}
else if (textlen == 30)
{
strcat(textRecord, combine);
textRecordLength += 3;
fprintf(op, "T%06X%02X%s\n", currentTextAddress, textRecordLength, textRecord);
textRecordLength = 0;
strcpy(textRecord, "");
textlen = 0;
strcpy(text, "");
currentTextAddress = strtoul(b[(j + 1)].locctr, NULL, 16);
}
else
{
strcat(textRecord, combine);
textRecordLength += 3;
}
}
else if (strcmp(b[j].opcode, "BYTE") == 0)
{
char hex_result[100] = "";
if (b[j].operand[0] == 'C')
{
for (int m = 2; m < (strlen(b[j].operand) - 1); m++)
{
char buffer[3] = "";
sprintf(buffer, "%02X", (int)b[j].operand[m]);
strcat(hex_result, buffer);
}
}
else if (b[j].operand[0] == 'X')
{
strncpy(hex_result, (b[j].operand + 2), (strlen(b[j].operand) - 3));
hex_result[(strlen(b[j].operand) - 3)] = '\0';
}
strcat(text, hex_result);
textlen += strlen(hex_result) / 2;
if (textlen > 30)
{
fprintf(op, "T%06X%02X%s\n", currentTextAddress, textRecordLength, textRecord);
textRecordLength = 0;
strcpy(textRecord, "");
textlen = 0;
j--;
strcpy(text, "");
currentTextAddress = strtoul(b[(j + 1)].locctr, NULL, 16);
}
else if (textlen == 30)
{
strcat(textRecord, hex_result);
textRecordLength += strlen(hex_result) / 2;
fprintf(op, "T%06X%02X%s\n", currentTextAddress, textRecordLength, textRecord);
textRecordLength = 0;
strcpy(textRecord, "");
textlen = 0;
strcpy(text, "");
currentTextAddress = strtoul(b[(j + 1)].locctr, NULL, 16);
}
else
{
strcat(textRecord, hex_result);
textRecordLength += strlen(hex_result) / 2;
}
}
else if (((strcmp(b[j].opcode, "RESW") == 0) || (strcmp(b[j].opcode, "RESB") == 0)))
{
if (textRecordLength > 0)
{
fprintf(op, "T%06X%02X%s\n", currentTextAddress, textRecordLength, textRecord);
textRecordLength = 0;
strcpy(textRecord, "");
textlen = 0;
strcpy(text, "");
}
currentTextAddress = strtoul(b[(j + 1)].locctr, NULL, 16);
}
else
{
if (j != 0)
{
printf("Invalid Instruction\n");
exit(0);
}
}
j++;
}
if (textRecordLength > 0)
{
fprintf(op, "T%06X%02X%s\n", currentTextAddress, textRecordLength, textRecord);
}
fprintf(op, "E%06X\n", startValue);
fclose(op);
fclose(ip);
fclose(kp);
fclose(ot);
FILE *output = fopen("SICXEoutput.txt", "r");
if (output == NULL)
{
printf("Unable to open output.txt\n");
return 1;
}
char line[256];
printf("\n--- The Object Program ---\n");
while (fgets(line, sizeof(line), output))
{
printf("%s", line);
}
fclose(output);
return 0;
}
Sample Inputs and Outputs of SIC Pass 2 of two pass assembler:
Sample Input and Output 1
Sample Input and Output 2
Sample Input and Output 3
Sample Inputs and Outputs of SIC/XE Pass 2 of two pass assembler:
Sample Input and Output 1
Sample Input and Output 2