Introduction and Problem Description:
A. PASS 1 of SIC/XE Assembler:
a. Introduction
Purpose:
Implements Pass 1 of a SIC/XE Assembler, which builds the Symbol Table and generates an intermediate file for Pass 2.
Main Tasks:
Reads the OpTab (opcode table).
Processes the source file to calculate addresses and handle directives.
Creates the Symbol Table (SymTab) with labels, types, and values.
Generates the Intermediate File with location counters and source code.
Outcome:
Produces the Symbol Table and intermediate file required for Pass 2.
b. Problem Description:
Processing OpTab and Source File
Reads OpTab from OpTab.txt to load opcodes, values, and formats.
Processes each line of the assembly file (SICXEinput1.txt) to split it into label, opcode, and operand.
Initializes location counter (LOCCTR) based on the START directive.
Building the Symbol Table (SymTab)
Labels are added to SymTab with their type:
A (Absolute): Fixed address, not relocated.
R (Relative): Address adjusted during relocation.
Handles EQU directives to assign labels with values based on expressions.
Address Calculations:
Directives like RESW, RESB, WORD, and BYTE are processed to calculate memory requirements:
RESW: Reserves 3 bytes per word.
RESB: Reserves specified bytes.
WORD: Reserves 3 bytes.
BYTE: Reserves bytes based on length of the operand.
Error Handling:
Detects duplicate labels.
Validates undefined symbols in EQU expressions.
Checks for invalid opcodes.
Objective:
Build Symbol Table and Intermediate File for Pass 2.
Ensure correct address calculation and handling of directives to facilitate object code generation in the next pass.
B. PASS 2 SIC/XE Assembler:
a. Introduction
Purpose:
To implement Pass 2 of a SIC/XE Assembler, which processes the intermediate file generated in Pass 1 to produce the final object code and listing file.
The assembler uses the opcode table (OpTab), symbol table (SymTab), and various directives to convert assembly code into Object Program.
Main Tasks of Pass 2:
Read the Intermediate File (produced in Pass 1) and the OpTab (opcode table).
Process each line to calculate object code instructions based on opcode formats, addressing modes, and operands.
Handle special cases like immediate addressing, indirect addressing, PC-relative addressing, base-relative addressing, and extended format.
Generate Text Records, Header Records, and End Records to form the Object Program.
Create a Listing File that includes the source code with corresponding object code for easier debugging.
Outcome:
The program produces two output files:
SICXEoutput.txt (Object Program)
SICXElistingfile.txt (Listing File)
b. Problem Description
1. Reading Files:
The program reads four input files:
SICXEINT.txt: Intermediate file containing labels, opcodes, operands, and location counters from Pass 1.
OpTab.txt: Opcode table with corresponding machine code values and instruction formats (1, 2, 3, or 4).
SICXESymTab.txt: Symbol table with labels, addresses, and types (Absolute or Relative).
SICXEoutput.txt: Output file to write the final object code.
2. Processing the Intermediate File:
The intermediate file is read line by line and split into:
Location Counter (LOCCTR)
Label
Opcode
Operand
The program checks each line's opcode and processes it accordingly.
3. Addressing Modes and Opcode Handling:
The program handles different opcode formats and addressing modes:
Format 2 Instructions: Use register numbers for operands.
Format 3/4 Instructions: Handle PC-relative, base-relative, and extended addressing.
Immediate Addressing: Denoted by # in the operand.
Indirect Addressing: Denoted by @ in the operand.
Indexed Addressing: Uses a combination of symbol and ,X to access an indexed address.
For format 3/4 instructions, the n,i,x,b,p,e flags are calculated to determine the instruction's behavior:
Indirect addressing
Immediate addressing
Indexed addressing
Base-relative addressing
PC-relative addressing
Extended format
4. Generating Object Code:
The program builds the object code by combining:
Opcode value
Addressing mode flags (n,i,x,b,p,e)
Displacement or address for the operand
For each line in the intermediate file, the corresponding object code is written to the text record.
5. Handling Special Directives:
The assembler processes the following special directives:
WORD: Converts the operand to a 6-character hexadecimal object code.
BYTE: Converts character constants (e.g., C'EOF') or hexadecimal constants (e.g., X'F1') to object code.
RESW and RESB: Skip memory locations but do not generate object code.
BASE: Sets a base register for base-relative addressing.
END: Marks the end of the program and generates the End Record in the object file.
6. Objective:
The main goal of this program is to:
Convert Assembly Code into Object Code by processing the intermediate file.
Handle Complex Addressing Modes like immediate, indirect, indexed, PC-relative, and base-relative addressing to ensure accurate object code generation.
7. Generate a Complete Object Program with the following records:
Header Record (H): Contains the program name, start address, and program length.
Text Records (T): Contains the object code for instructions and data within a memory block.
End Record (E): Specifies the starting execution address.
Create a Listing File for easier debugging and cross-referencing of source code with object code.
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
Parse line into lab, oper, open (label, opcode, operand)
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)
if OPCODE = "EQU" then
begin
Initialize value = 0, texp = 'A'
if OPERAND = '*' then
Set value = LOCCTR, texp = 'R'
else
Evaluate expression in OPERAND
Update value, texp, and location
Write to intermediate file and symbol table
end (if EQU)
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 if OPCODE = "BASE" or OPCODE = "END" then
Continue processing without updating LOCCTR
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
Close all files
end (Pass 1)
Pass 2:
begin
Read first input line from "SICXEINT.txt"
if OPCODE = "START" then
begin
Save #[OPERAND] as starting address
Initialize LOCCTR to starting address
Write header record to object program
Write line to listing file
Read next input line
end (if START)
else
Initialize LOCCTR to 0
Initialize first text record
while OPCODE ≠ "END" do
begin
if this is not a comment line then
begin
Search OPTAB for OPCODE
if found then
begin
if there is a symbol in OPERAND field then
begin
Search SYMTAB for OPERAND
if found then
Store symbol value as operand address
else
Store 0 as operand address
Set error flag (undefined symbol)
end (if symbol in OPERAND)
else
Store 0 as operand address
Assemble object code instruction
end (if OPCODE found)
else if OPCODE = "BYTE" or "WORD" then
Convert constant to object code
if object code will not fit into the current text record then
begin
Write text record to object program
Initialize new text record
end (if object code exceeds record size)
Add object code to text record
end (if not a comment)
Write listing line
Read next input line
end (while OPCODE ≠ "END")
Write last text record to object program
Write end record to object program
Write last listing line
Close all files
end (Pass 2)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
typedef struct INPUT
{
char label[20], opcode[20], operand[20];
} INSTR;
typedef struct SymTab
{
char label[20], type;
int value;
} SMT;
typedef struct OpTab
{
char opCode[10], value[3], format[2];
} OPTAB;
char texp;
int location;
int old_loc;
int main()
{
INSTR a[100];
OPTAB b[102];
SMT c[100];
char sd[100];
char pName[20];
FILE *fp = fopen("SICXEinput1.txt", "r");
FILE *ip = fopen("SICXEINT.txt", "w");
FILE *kp = fopen("SICXESymTab.txt", "w");
FILE *optab = fopen("OpTab.txt", "r");
if (fp == NULL || ip == NULL || kp == NULL || optab == NULL)
{
printf("Unable to open one or more files\n");
return 1;
}
int Size = 0;
while (fscanf(optab, "%s %s %s", b[Size].opCode, b[Size].value, b[Size].format) != EOF)
{
Size++;
}
fclose(optab);
int i = 0;
int s = 0;
int startValue = 0, locctr = 0;
while (fgets(sd, sizeof(sd), fp) && i < 100)
{
char lab[20] = "", oper[20] = "", open[20] = "";
int tokens = sscanf(sd, "%s %s %s", lab, oper, open);
char etype = '-';
strcpy(a[i].label, "");
strcpy(a[i].opcode, "");
strcpy(a[i].operand, "");
if (tokens == 1)
strcpy(a[i].opcode, lab);
else if (tokens == 2)
{
strcpy(a[i].opcode, lab);
strcpy(a[i].operand, oper);
}
else if (tokens == 3)
{
strcpy(a[i].label, lab);
strcpy(a[i].opcode, oper);
strcpy(a[i].operand, open);
if (i == 1)
strcpy(pName, a[i].label);
}
strcpy(c[s].label, a[i].label);
c[s].type = etype;
c[s].value = locctr;
s++;
if ((strcmp(a[i].opcode, "START") == 0) && (i == 0))
{
etype = 'A';
locctr = startValue = strtoul(a[0].operand, NULL, 16);
fprintf(ip, "%04X\t%s", startValue, sd);
strcpy(c[s].label, a[i].label);
c[s].type = etype;
c[s].value = startValue;
s++;
fprintf(kp, "%s\t%c\t%04X\n", a[i].label, etype, startValue);
}
else
{
if (strcmp(a[i].opcode, "EQU") == 0)
{
int value = 0;
char etype;
if (a[i].operand[0] == '*')
{
texp = 'R';
value = locctr;
locctr = value;
fprintf(kp, "%s\t%c\t%04X\n", a[i].label, texp, value);
fprintf(ip, "%04X\t%s", value, sd);
i++;
continue;
}
// Case 3: Symbol or Expression
char expression[50], orgexp[50];
strcpy(expression, a[i].operand);
strcpy(orgexp, a[i].operand);
char *currentPosition = orgexp;
int relativeCount = 0;
char operator= '+';
char *token = strtok(expression, "+-*/");
while (token != NULL)
{
int termValue = 0;
char termType = 'A';
int found = 0;
for (int j = 0; j < s; j++)
{
if (strcmp(c[j].label, token) == 0)
{
termValue = c[j].value;
termType = c[j].type;
found = 1;
break;
}
}
printf("%d\n", found);
if (!found)
{
if (isdigit(token[0]))
{
termValue = strtoul(token, NULL, 10);
termType = 'A';
}
else
{
printf("Error: Undefined or invalid symbol '%s' in EQU directive\n", token);
return 1;
}
}
if ((operator== '*' || operator== '/') && termType == 'R')
{
printf("Error: Invalid operation '%c' on relative term '%s' in EQU directive at line %d\n", operator, token, i + 1);
return 1;
}
if (operator== '-' && termType == 'R' && relativeCount> 0)
{
relativeCount--;
termType = 'A';
}
else if (termType == 'R')
{
relativeCount++;
}
if (operator== '+')
{
value += termValue;
}
else if (operator== '-')
{
value -= termValue;
}
currentPosition += strlen(token);
while (*currentPosition == ' ' && currentPosition < token)
{
currentPosition++;
}
if (*currentPosition == '+' || *currentPosition == '-' || *currentPosition == '*' || *currentPosition == '/')
{
operator= * currentPosition;
currentPosition++;
}
else
{
operator= '+';
}
token = strtok(NULL, "+-*/");
}
if (relativeCount > 1)
{
printf("Error: Multiple unpaired relative terms in EQU directive\n");
return 1;
}
if (relativeCount == 1)
texp = 'R';
else
texp = 'A';
location = value;
printf("EQU processed: %s = %04X (%c)\n", a[i].label, value, texp);
fprintf(kp, "%s\t%c\t%04X\n", a[i].label, texp, value);
fprintf(ip, "%04X\t%s", value, sd);
i++;
continue;
}
if (tokens == 3)
{
for (int j = 0; j < i; j++)
{
if (strcmp(a[i].label, a[j].label) == 0 && i != j)
{
printf("Duplicate label found: %s\n", a[j].label);
return 1;
}
}
if (strcmp(a[i].opcode, "RESW") == 0 || strcmp(a[i].opcode, "RESB") == 0)
{
etype = 'R';
}
else if (strcmp(a[i].opcode, "BYTE") == 0 || strcmp(a[i].opcode, "BYTE") == 0)
{
etype = 'A';
}
else if (strcmp(a[i].opcode, "EQU") == 0)
{
if (a[i].operand[0] == '*')
{
etype = 'R';
}
else if (isdigit(a[i].operand[0]))
{
etype = 'A';
}
else
{
old_loc = locctr;
locctr = location;
etype = texp;
}
}
else
{
etype = '-';
}
fprintf(kp, "%s\t%c\t%04X\n", a[i].label, etype, locctr);
if (locctr == location)
locctr = old_loc;
}
if ((strcmp(a[i].opcode, "END") == 0))
continue;
else if (strcmp(a[i].opcode, "BASE") == 0)
{
fprintf(ip, "\t%s", sd);
}
else
{
fprintf(ip, "%04X\t%s", locctr, sd);
}
int found = 0;
for (int k = 0; k < Size; k++)
{
if (strcmp(b[k].opCode, a[i].opcode) == 0)
{
found = 1;
int format = atoi(b[k].format);
if (format == 4 || a[i].opcode[0] == '+')
{
locctr += 4;
}
else
{
locctr += format;
}
break;
}
}
if (found == 0)
{
if (strcmp(a[i].opcode, "WORD") == 0)
{
locctr += 3;
}
else if (strcmp(a[i].opcode, "RESW") == 0)
{
locctr += 3 * atoi(a[i].operand);
}
else if (strcmp(a[i].opcode, "RESB") == 0)
{
locctr += atoi(a[i].operand);
}
else if (strcmp(a[i].opcode, "BYTE") == 0)
{
if (a[i].operand[0] == 'X')
{
locctr += (strlen(a[i].operand) - 3) / 2;
}
else if (a[i].operand[0] == 'C')
{
locctr += strlen(a[i].operand) - 3;
}
}
else if ((strcmp(a[i].opcode, "BASE") == 0) || (strcmp(a[i].opcode, "END") == 0))
{
continue;
}
else
{
printf("Invalid opcode found: %s\n", a[i].opcode);
}
}
}
i++;
}
fprintf(ip, "%04X\t\t\tEND\t\t%s", locctr, pName);
int prLength = locctr - startValue;
printf("The program length is: %04X\n", prLength);
fclose(fp);
fclose(ip);
fclose(kp);
return 0;
}
#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];
char etype;
} sym;
int INDEX;
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 *lf = fopen("SICXElistingfile.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] = "";
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++;
}
for (int index = 0; index < i; index++)
{
printf("%s %s %s %s\n", b[index].locctr, b[index].label, b[index].opcode, b[index].operand);
}
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++;
}
int r = 0;
while (fgets(sm, sizeof(sm), kp) && r < 100)
{
char symb[10] = "", add[6] = "";
char etype;
sscanf(sm, "%s %c %s", symb, &etype, add);
if (strcmp(base, symb) == 0)
{
strcpy(Base, add);
}
strcpy(c[r].Symbol, symb);
c[r].etype = etype;
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);
fprintf(lf, "%s\t%s\t%s\t%s\n", b[0].locctr, b[0].label, b[0].opcode, b[0].operand);
}
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);
fprintf(lf, "%s\t\t%s\t%s\t%s%X%X\n", b[j].locctr, b[j].opcode, b[j].operand, 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)
{
if (isIndexed != 1 || INDEX == 0)
{
displacement = symAddr - pcValue;
}
else
{
displacement = symAddr - pcValue - INDEX;
}
if (displacement >= -0x800 && displacement <= 0x7FF)
{
p = 1;
}
else
{
bFlag = 1;
pcValue = strtoul(Base, NULL, 16);
if (isIndexed != 1 || INDEX == 0)
{
displacement = symAddr - pcValue;
}
else
{
displacement = symAddr - pcValue - INDEX;
}
}
}
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);
fprintf(lf, "%s\t%s\t%s\t%s\t%02X%1X%05s\n", b[j].locctr, b[j].label, b[j].opcode, b[j].operand, strtol(code, NULL, 16) + niBits, xbpeBits, val1);
}
else
{
sprintf(combine, "%02X%1X%03s", strtol(code, NULL, 16) + niBits, xbpeBits, val1);
fprintf(lf, "%s\t%s\t%s\t%s\t%02X%1X%03s\n", b[j].locctr, b[j].label, b[j].opcode, b[j].operand, 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);
fprintf(lf, "%s\t%s\t%s\t%s\t%06X\n", b[j].locctr, b[j].label, b[j].opcode, b[j].operand, atoi(b[j].operand));
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);
}
fprintf(lf, "%s\t%s\t%s\t%s\t%s\n", b[j].locctr, b[j].label, b[j].opcode, b[j].operand, hex_result);
}
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';
fprintf(lf, "%s\t%s\t%s\t%s\t%s\n", b[j].locctr, b[j].label, b[j].opcode, b[j].operand, hex_result);
}
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) || (strcmp(b[j].opcode, "EQU") == 0)))
{
fprintf(lf, "%s\t%s\t%s\t%s\n", b[j].locctr, b[j].label, b[j].opcode, b[j].operand);
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 Input and Output 1
Sample Input and Output 2
Sample Input and Output 3