Input: Symbol Table and IR file
Pass 2- ARM Assembly to Machine Code Converter
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#define MAX_LINE_LENGTH 256
#define MAX_LABELS 100
#define MAX_INSTRUCTIONS 100
// Structure to store labels
typedef struct {
char label[MAX_LINE_LENGTH];
int address;
} Label;
// Instruction structure
typedef struct {
char mnemonic[MAX_LINE_LENGTH];
char operands[MAX_LINE_LENGTH];
int address;
} Instruction;
// Opcode Table Structure
typedef struct {
char mnemonic[10];
char opcode[10];
} Opcode;
// Sample Opcode Table (Extend as needed)
Opcode opcodeTable[] = {
{"LDR", "E59F"},
{"ADD", "E280"},
{"LDRB", "E5D0"},
{"MOVS", "E3B0"},
{"ADDS", "E090"},
{"ANDS", "E000"},
{"ORRS", "E180"},
{"EORS", "E020"},
{"CMP", "E150"},
{"BEQ", "0A00"},
{"B", "EA"},
{"SUB", "E240"},
{"STR", "E58D"},
{"BL", "EB"},
{"", ""} // End of table
};
// Global data
Label labelTable[MAX_LABELS];
int labelCount = 0;
Instruction instructions[MAX_INSTRUCTIONS];
int instructionCount = 0;
// Function to find a label's address
int findLabelAddress(const char *label) {
for (int i = 0; i < labelCount; i++) {
if (strcmp(labelTable[i].label, label) == 0) {
return labelTable[i].address;
}
}
return -1; // Not found
}
// Function to find opcode from the table
char* findOpcode(const char* mnemonic) {
for (int i = 0; opcodeTable[i].mnemonic[0] != '\0'; i++) {
if (strcmp(opcodeTable[i].mnemonic, mnemonic) == 0) {
return opcodeTable[i].opcode;
}
}
return NULL; // Not found
}
// Function to calculate object code for LDR
uint32_t calculateLDR(const char *operands, int address) {
char dest[5];
int offset;
sscanf(operands, "%[^,], [PC, #%d]", dest, &offset);
offset = (offset - 8) / 4; // Adjust offset for PC-relative addressing
int rd = atoi(&dest[1]); // Extract register number
return (strtol(findOpcode("LDR"), NULL, 16) << 16) | (rd << 12) | (offset & 0xFFF);
}
// Function to calculate object code for ADD
uint32_t calculateADD(const char *operands) {
char dest[5], op1[5];
int immediate;
sscanf(operands, "%[^,], %[^,], #%d", dest, op1, &immediate);
int rd = atoi(&dest[1]);
int rn = atoi(&op1[1]);
return (strtol(findOpcode("ADD"), NULL, 16) << 16) | (rn << 16) | (rd << 12) | (immediate & 0xFFF);
}
// Function to calculate object code for LDRB
uint32_t calculateLDRB(const char *operands) {
char dest[5], base[5];
sscanf(operands, "%[^,], [%[^]]", dest, base);
int rd = atoi(&dest[1]);
int rn = atoi(&base[1]);
return (strtol(findOpcode("LDRB"), NULL, 16) << 16) | (rn << 16) | (rd << 12);
}
// Function to calculate object code for MOVS
uint32_t calculateMOVS(const char *operands) {
char dest[5];
int immediate;
sscanf(operands, "%[^,], #%d", dest, &immediate);
int rd = atoi(&dest[1]);
int rotate = 0;
while (immediate > 255) {
immediate = (immediate >> 2) | ((immediate & 3) << 30); // Rotate right by 2
rotate++;
}
return (strtol(findOpcode("MOVS"), NULL, 16) << 16) | (rd << 12) | (rotate << 8) | immediate;
}
// Function to calculate object code for ADDS
uint32_t calculateADDS(const char *operands) {
char dest[5], op1[5], op2[5];
sscanf(operands, "%[^,], %[^,], %s", dest, op1, op2);
int rd = atoi(&dest[1]);
int rn = atoi(&op1[1]);
int rm = atoi(&op2[1]);
return (strtol(findOpcode("ADDS"), NULL, 16) << 16) | (rn << 16) | (rd << 12) | rm;
}
// Function to calculate object code for logical operations (ANDS, ORRS, EORS)
uint32_t calculateLogical(const char *mnemonic, const char *operands) {
char dest[5], op1[5], op2[5];
sscanf(operands, "%[^,], %[^,], %s", dest, op1, op2);
int rd = atoi(&dest[1]);
int rn = atoi(&op1[1]);
int rm = atoi(&op2[1]);
return (strtol(findOpcode(mnemonic), NULL, 16) << 16) | (rn << 16) | (rd << 12) | rm;
}
// Function to calculate object code for CMP
uint32_t calculateCMP(const char *operands) {
char op1[5], op2[5];
sscanf(operands, "%[^,], %s", op1, op2);
int rn = atoi(&op1[1]);
int rm = atoi(&op2[1]);
return (strtol(findOpcode("CMP"), NULL, 16) << 16) | (rn << 16) | rm;
}
// Function to calculate object code for BEQ
uint32_t calculateBEQ(const char *operands, int currentAddress) {
char label[MAX_LINE_LENGTH];
sscanf(operands, "%s", label);
int targetAddress = findLabelAddress(label);
if (targetAddress == -1) {
printf("Error: Undefined label %s\n", label);
exit(1);
}
int offset = (targetAddress - (currentAddress + 8)) / 4;
return (strtol(findOpcode("BEQ"), NULL, 16) << 16) | (offset & 0xFFFFFF);
}
// Function to calculate object code for B
uint32_t calculateB(const char *operands, int currentAddress) {
char label[MAX_LINE_LENGTH];
sscanf(operands, "%s", label);
int targetAddress = findLabelAddress(label);
if (targetAddress == -1) {
printf("Error: Undefined label %s\n", label);
exit(1);
}
int offset = (targetAddress - (currentAddress + 8)) / 4;
return (strtol(findOpcode("B"), NULL, 16) << 16) | (offset & 0xFFFFFF);
}
// Function to process an instruction
uint32_t processInstruction(const Instruction *instr) {
if (strcmp(instr->mnemonic, "LDR") == 0) {
return calculateLDR(instr->operands, instr->address);
} else if (strcmp(instr->mnemonic, "ADD") == 0) {
return calculateADD(instr->operands);
} else if (strcmp(instr->mnemonic, "LDRB") == 0) {
return calculateLDRB(instr->operands);
} else if (strcmp(instr->mnemonic, "MOVS") == 0) {
return calculateMOVS(instr->operands);
} else if (strcmp(instr->mnemonic, "ADDS") == 0) {
return calculateADDS(instr->operands);
} else if (strcmp(instr->mnemonic, "ANDS") == 0 || strcmp(instr->mnemonic, "ORRS") == 0 || strcmp(instr->mnemonic, "EORS") == 0) {
return calculateLogical(instr->mnemonic, instr->operands);
} else if (strcmp(instr->mnemonic, "CMP") == 0) {
return calculateCMP(instr->operands);
} else if (strcmp(instr->mnemonic, "BEQ") == 0) {
return calculateBEQ(instr->operands, instr->address);
} else if (strcmp(instr->mnemonic, "B") == 0) {
return calculateB(instr->operands, instr->address);
}
return 0; // Unsupported instruction
}
int main() {
FILE *symbolFile = fopen("symbol_table.txt", "r");
FILE *irFile = fopen("ir_file.txt", "r");
if (!symbolFile || !irFile) {
perror("Error opening input files");
return 1;
}
// Parse the symbol table
char line[MAX_LINE_LENGTH];
while (fgets(line, sizeof(line), symbolFile)) {
sscanf(line, "%s %x", labelTable[labelCount].label, &labelTable[labelCount].address);
labelCount++;
}
fclose(symbolFile);
// Parse the IR file
while (fgets(line, sizeof(line), irFile)) {
sscanf(line, "%x %s %[^\n]", &instructions[instructionCount].address,
instructions[instructionCount].mnemonic, instructions[instructionCount].operands);
instructionCount++;
}
fclose(irFile);
// Process each instruction
for (int i = 0; i < instructionCount; i++) {
uint32_t objCode = processInstruction(&instructions[i]);
printf("%08X\t%s\t%s\n", objCode, instructions[i].mnemonic, instructions[i].operands);
}
return 0;
}
OUR OUTPUT: Object code for the give assembly program
000000 E59F004C LDR R0, [PC, #0x004C]
000004 E2800004 ADD R0, R0, #0x00000004
000008 E5D01000 LDRB R1, [R0]
00000C E3B02000 MOVS R2, #0x00001400
00000E E0913002 ADDS R3, R1, R2
000010 59F403C0 LDR R4, [PC, #0x003C]
000014 E0944008 ADDS R4, R4, #0x00000008
000016 E5D45000 LDRB R5, [R4]
00001A E3B0000F MOVS R0, #0x0000000F
00001C E3B01019 MOVS R1, #0x00000019
00001E E1802001 ORRS R2, R0, R1
000020 E0003001 ANDS R3, R0, R1
000022 E0204001 EORS R4, R0, R1
000024 E1540005 CMP R4, R5
000028 0A000000 BEQ 0x00000044
00002A E3B0200A MOVS R6, #0x0000000A
00002C EA003048 B 0x00000048
00002E E3B03002 MOVS R6, #0x00000002
000030 E3B04004 MOVS R7, #0x00000004
000032 EA000048 B 0x00000048
Keil Software Output: